battery_monitor.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #
3 # Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 
17 
18 import rospy
19 import colorsys
20 import copy
21 import actionlib
22 
23 from std_msgs.msg import ColorRGBA
24 from cob_msgs.msg import PowerState
25 from cob_light.msg import LightMode, LightModes, SetLightModeAction, SetLightModeGoal
26 from cob_light.srv import StopLightMode, StopLightModeRequest
27 
28 from simple_script_server import *
30 
31 
33 
34  def __init__(self):
35  self.power_state = PowerState()
37  self.temperature = 0.0
38  self.is_charging = False
39  self.topic_name = 'power_state'
40  self.mode = LightMode()
41 
42  self.threshold_warning = rospy.get_param("~threshold_warning", 20.0) # % of battery level
43  self.threshold_error = rospy.get_param("~threshold_error", 10.0) # % of battery level
44  self.threshold_critical = rospy.get_param("~threshold_critical", 5.0)# % of battery level
45 
46  self.enable_light = rospy.get_param("~enable_light", True)
47  self.num_leds = rospy.get_param("~num_leds", 1)
48  self.track_id_light = {}
49  if self.enable_light:
50  if not rospy.has_param("~light_components"):
51  rospy.logwarn("parameter light_components does not exist on ROS Parameter Server")
52  return
53  self.light_components = rospy.get_param("~light_components")
54  for component in self.light_components:
55  self.track_id_light[component] = None
56  self.mode = LightMode()
57  self.mode.priority = 8
58 
59  self.enable_sound = rospy.get_param("~enable_sound", True)
60  self.sound_components = {}
61  if self.enable_sound:
62  if not rospy.has_param("~sound_components"):
63  rospy.logwarn("parameter sound_components does not exist on ROS Parameter Server")
64  return
65  self.sound_components = rospy.get_param("~sound_components")
66 
67  self.sound_critical = rospy.get_param("~sound_critical", "My battery is empty, please recharge now.")
68  self.sound_warning = rospy.get_param("~sound_warning", "My battery is nearly empty, please consider recharging.")
69 
70  self.last_time_warned = rospy.get_time()
71  self.last_time_power_received = rospy.get_time()
72  rospy.Subscriber(self.topic_name, PowerState, self.power_callback)
73 
74  rospy.Timer(rospy.Duration(1), self.timer_callback)
75 
76  def power_callback(self, msg):
77  self.last_time_power_received = rospy.get_time()
78  self.power_state = msg
79 
80  def set_light(self, mode, track=False):
81  if self.enable_light:
82  for component in self.light_components:
83  action_server_name = component + "/set_light"
84  client = actionlib.SimpleActionClient(action_server_name, SetLightModeAction)
85  # trying to connect to server
86  rospy.logdebug("waiting for %s action server to start",action_server_name)
87  if not client.wait_for_server(rospy.Duration(5)):
88  # error: server did not respond
89  rospy.logerr("%s action server not ready within timeout, aborting...", action_server_name)
90  else:
91  rospy.logdebug("%s action server ready",action_server_name)
92 
93  # sending goal
94  goal = SetLightModeGoal()
95  goal.mode = mode
96  client.send_goal(goal)
97  client.wait_for_result()
98  res = client.get_result()
99  if track:
100  self.track_id_light[component] = res.track_id
101 
102  def stop_light(self):
103  if self.enable_light:
104  for component in self.light_components:
105  if self.track_id_light[component] is not None:
106  srv_server_name = component + "/stop_mode"
107  try:
108  rospy.wait_for_service(srv_server_name, timeout=2)
109  srv_proxy = rospy.ServiceProxy(srv_server_name, StopLightMode)
110  req = StopLightModeRequest()
111  req.track_id = self.track_id_light[component]
112  srv_proxy(req)
113  self.track_id_light[component] = None
114  except Exception as e:
115  rospy.logerr("%s service failed: %s",srv_server_name, e)
116 
117  def say(self, text):
118  if self.enable_sound:
119  for component in self.sound_components:
120  sss.say(component, [text])
121 
122  def timer_callback(self, event):
123  # warn if battery is empty
124  if not self.is_charging:
125  # 5%
126  if self.power_state.relative_remaining_capacity <= self.threshold_critical and (rospy.get_time() - self.last_time_warned) > 5:
127  self.last_time_warned = rospy.get_time()
128  mode = copy.copy(self.mode)
129  mode.mode = LightModes.FLASH
130  color = ColorRGBA(1, 0, 0, 1)
131  mode.colors = []
132  mode.colors.append(color)
133  mode.frequency = 5
134  mode.pulses = 4
135  self.set_light(mode)
136 
137  self.say(self.sound_critical)
138 
139  # 10%
140  elif self.power_state.relative_remaining_capacity <= self.threshold_error and (rospy.get_time() - self.last_time_warned) > 15:
141  self.last_time_warned = rospy.get_time()
142  mode = copy.copy(self.mode)
143  mode.mode = LightModes.FLASH
144  color = ColorRGBA(1, 0, 0, 1)
145  mode.colors = []
146  mode.colors.append(color)
147  mode.frequency = 2
148  mode.pulses = 2
149  self.set_light(mode)
150  # 20%
151  elif self.power_state.relative_remaining_capacity <= self.threshold_warning and (rospy.get_time() - self.last_time_warned) > 30:
152  self.last_time_warned = rospy.get_time()
153  mode = copy.copy(self.mode)
154  mode.mode = LightModes.FLASH
155  color = ColorRGBA(1, 1, 0, 1)
156  mode.colors = []
157  mode.colors.append(color)
158  mode.frequency = 2
159  mode.pulses = 2
160  self.set_light(mode)
161 
162  self.say(self.sound_warning)
163 
164  if self.is_charging == False and self.power_state.charging == True:
165  self.is_charging = True
166 
167  if self.is_charging == True and (self.power_state.charging == False
168  or (rospy.get_time() - self.last_time_power_received) > 2):
169  self.is_charging = False
170  self.relative_remaining_capacity = 0.0
171  self.stop_light()
172 
173  elif self.is_charging == True:
174  # only change color mode if capacity change is bigger than 2%
175  if abs(self.relative_remaining_capacity - self.power_state.relative_remaining_capacity) > 2:
176  rospy.logdebug('adjusting leds')
177  mode = copy.copy(self.mode)
178  if self.num_leds > 1:
179  leds = int(self.num_leds * self.power_state.relative_remaining_capacity / 100.)
180  mode.mode = LightModes.CIRCLE_COLORS
181  mode.frequency = 60.0
182  mode.colors = []
183  color = ColorRGBA(0.0, 1.0, 0.7, 0.4)
184  for _ in range(leds):
185  mode.colors.append(color)
186  else:
187  mode.mode = LightModes.BREATH
188  mode.frequency = 0.4
189  # 0.34 => green in hsv space
190  hue = 0.34 * (self.power_state.relative_remaining_capacity / 100.0)
191  rgb = colorsys.hsv_to_rgb(hue, 1, 1)
192  color = ColorRGBA(rgb[0], rgb[1], rgb[2], 1.0)
193  mode.colors = []
194  mode.colors.append(color)
195 
196  self.relative_remaining_capacity = self.power_state.relative_remaining_capacity
197  self.set_light(mode, True)
198 
199 
200 if __name__ == "__main__":
201  rospy.init_node("battery_monitor")
203  rospy.spin()
def set_light(self, mode, track=False)


cob_monitoring
Author(s): Florian Weisshardt , Felix Messmer
autogenerated on Wed Apr 7 2021 03:03:11