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 
49  if rospy.has_param("~color_charging"):
50  charging_color_param = rospy.get_param("~color_charging")
51  else:
52  # set to cyan as default
53  charging_color_param = [0.0, 1.0, 0.7, 0.4]
54  self.color_charging = ColorRGBA(*charging_color_param)
55 
56  if rospy.has_param("~color_warning"):
57  color_warning_param = rospy.get_param("~color_warning")
58  else:
59  # set to cyan as default
60  color_warning_param = [1.0, 1.0, 0.0, 1.0]
61  self.color_warning = ColorRGBA(*color_warning_param)
62 
63  if rospy.has_param("~color_error"):
64  color_error_param = rospy.get_param("~color_error")
65  else:
66  # set to cyan as default
67  color_error_param = [1.0, 0.0, 0.0, 1.0]
68  self.color_error = ColorRGBA(*color_error_param)
69 
70  if rospy.has_param("~color_critical"):
71  color_critical_param = rospy.get_param("~color_critical")
72  else:
73  # set to cyan as default
74  color_critical_param = [1.0, 0.0, 0.0, 1.0]
75  self.color_critical = ColorRGBA(*color_critical_param)
76 
77  self.interval_duration_warning = rospy.get_param("~interval_duration_warning", 30.0)
78  self.interval_duration_error = rospy.get_param("~interval_duration_error", 15.0)
79  self.interval_duration_critical = rospy.get_param("~interval_duration_critical", 5.0)
80 
81  self.track_id_light = {}
82  if self.enable_light:
83  if not rospy.has_param("~light_components"):
84  rospy.logwarn("parameter light_components does not exist on ROS Parameter Server")
85  return
86  self.light_components = rospy.get_param("~light_components")
87  for component in self.light_components:
88  self.track_id_light[component] = None
89  self.mode = LightMode()
90  self.mode.priority = 8
91 
92  self.enable_sound = rospy.get_param("~enable_sound", True)
93  self.sound_components = {}
94  if self.enable_sound:
95  if not rospy.has_param("~sound_components"):
96  rospy.logwarn("parameter sound_components does not exist on ROS Parameter Server")
97  return
98  self.sound_components = rospy.get_param("~sound_components")
99 
100  self.sound_critical = rospy.get_param("~sound_critical", "My battery is empty, please recharge now.")
101  self.sound_warning = rospy.get_param("~sound_warning", "My battery is nearly empty, please consider recharging.")
102 
103  self.last_time_warned = rospy.get_time()
104  self.last_time_power_received = rospy.get_time()
105  rospy.Subscriber(self.topic_name, PowerState, self.power_callback)
106 
107  rospy.Timer(rospy.Duration(1), self.timer_callback)
108 
109  def power_callback(self, msg):
110  self.last_time_power_received = rospy.get_time()
111  self.power_state = msg
112 
113  def set_light(self, mode, track=False):
114  if self.enable_light:
115  for component in self.light_components:
116  action_server_name = component + "/set_light"
117  client = actionlib.SimpleActionClient(action_server_name, SetLightModeAction)
118  # trying to connect to server
119  rospy.logdebug("waiting for %s action server to start",action_server_name)
120  if not client.wait_for_server(rospy.Duration(5)):
121  # error: server did not respond
122  rospy.logerr("%s action server not ready within timeout, aborting...", action_server_name)
123  else:
124  rospy.logdebug("%s action server ready",action_server_name)
125 
126  # sending goal
127  goal = SetLightModeGoal()
128  goal.mode = mode
129  client.send_goal(goal)
130  client.wait_for_result()
131  res = client.get_result()
132  if track:
133  self.track_id_light[component] = res.track_id
134 
135  def stop_light(self):
136  if self.enable_light:
137  for component in self.light_components:
138  if self.track_id_light[component] is not None:
139  srv_server_name = component + "/stop_mode"
140  try:
141  rospy.wait_for_service(srv_server_name, timeout=2)
142  srv_proxy = rospy.ServiceProxy(srv_server_name, StopLightMode)
143  req = StopLightModeRequest()
144  req.track_id = self.track_id_light[component]
145  srv_proxy(req)
146  self.track_id_light[component] = None
147  except Exception as e:
148  rospy.logerr("%s service failed: %s",srv_server_name, e)
149 
150  def say(self, text):
151  if self.enable_sound:
152  for component in self.sound_components:
153  sss.say(component, [text])
154 
155  def timer_callback(self, event):
156  # warn if battery is empty
157  if not self.is_charging:
158  # 5%
159  if self.power_state.relative_remaining_capacity <= self.threshold_critical and (rospy.get_time() - self.last_time_warned) > self.interval_duration_critical:
160  self.last_time_warned = rospy.get_time()
161  mode = copy.copy(self.mode)
162  mode.mode = LightModes.FLASH
163  color = self.color_critical
164  mode.colors = []
165  mode.colors.append(color)
166  mode.frequency = 4
167  mode.pulses = 8
168  self.set_light(mode)
169 
170  self.say(self.sound_critical)
171 
172  # 10%
173  elif self.power_state.relative_remaining_capacity <= self.threshold_error and (rospy.get_time() - self.last_time_warned) > self.interval_duration_error:
174  self.last_time_warned = rospy.get_time()
175  mode = copy.copy(self.mode)
176  mode.mode = LightModes.FLASH
177  color = self.color_error
178  mode.colors = []
179  mode.colors.append(color)
180  mode.frequency = 2
181  mode.pulses = 2
182  self.set_light(mode)
183  # 20%
184  elif self.power_state.relative_remaining_capacity <= self.threshold_warning and (rospy.get_time() - self.last_time_warned) > self.interval_duration_warning:
185  self.last_time_warned = rospy.get_time()
186  mode = copy.copy(self.mode)
187  mode.mode = LightModes.FLASH
188  color = self.color_warning
189  mode.colors = []
190  mode.colors.append(color)
191  mode.frequency = 2
192  mode.pulses = 2
193  self.set_light(mode)
194 
195  self.say(self.sound_warning)
196 
197  if self.is_charging == False and self.power_state.charging == True:
198  self.is_charging = True
199 
200  if self.is_charging == True and (self.power_state.charging == False
201  or (rospy.get_time() - self.last_time_power_received) > 2):
202  self.is_charging = False
203  self.relative_remaining_capacity = 0.0
204  self.stop_light()
205 
206  elif self.is_charging == True:
207  # only change color mode if capacity change is bigger than 2%
208  if abs(self.relative_remaining_capacity - self.power_state.relative_remaining_capacity) > 2:
209  rospy.logdebug('adjusting leds')
210  mode = copy.copy(self.mode)
211  if self.num_leds > 1:
212  leds = int(self.num_leds * self.power_state.relative_remaining_capacity / 100.)
213  mode.mode = LightModes.CIRCLE_COLORS
214  mode.frequency = 60.0
215  mode.colors = []
216  color = self.color_charging
217  for _ in range(leds):
218  mode.colors.append(color)
219  else:
220  mode.mode = LightModes.BREATH
221  mode.frequency = 0.4
222  # 0.34 => green in hsv space
223  hue = 0.34 * (self.power_state.relative_remaining_capacity / 100.0)
224  rgb = colorsys.hsv_to_rgb(hue, 1, 1)
225  color = ColorRGBA(rgb[0], rgb[1], rgb[2], 1.0)
226  mode.colors = []
227  mode.colors.append(color)
228 
229  self.relative_remaining_capacity = self.power_state.relative_remaining_capacity
230  self.set_light(mode, True)
231 
232 
233 if __name__ == "__main__":
234  rospy.init_node("battery_monitor")
236  rospy.spin()
msg
battery_monitor.battery_monitor.enable_sound
enable_sound
Definition: battery_monitor.py:92
battery_monitor.battery_monitor.threshold_warning
threshold_warning
Definition: battery_monitor.py:42
battery_monitor.battery_monitor.interval_duration_error
interval_duration_error
Definition: battery_monitor.py:78
battery_monitor.battery_monitor.color_critical
color_critical
Definition: battery_monitor.py:75
battery_monitor.battery_monitor.last_time_power_received
last_time_power_received
Definition: battery_monitor.py:104
battery_monitor.battery_monitor.threshold_error
threshold_error
Definition: battery_monitor.py:43
battery_monitor.battery_monitor.sound_warning
sound_warning
Definition: battery_monitor.py:101
battery_monitor.battery_monitor.power_state
power_state
Definition: battery_monitor.py:35
battery_monitor.battery_monitor
Definition: battery_monitor.py:32
battery_monitor.battery_monitor.relative_remaining_capacity
relative_remaining_capacity
Definition: battery_monitor.py:36
battery_monitor.battery_monitor.power_callback
def power_callback(self, msg)
Definition: battery_monitor.py:109
battery_monitor.battery_monitor.sound_critical
sound_critical
Definition: battery_monitor.py:100
battery_monitor.battery_monitor.sound_components
sound_components
Definition: battery_monitor.py:93
actionlib::SimpleActionClient
simple_script_server
battery_monitor.battery_monitor.light_components
light_components
Definition: battery_monitor.py:86
battery_monitor.battery_monitor.is_charging
is_charging
Definition: battery_monitor.py:38
battery_monitor.battery_monitor.temperature
temperature
Definition: battery_monitor.py:37
battery_monitor.battery_monitor.interval_duration_critical
interval_duration_critical
Definition: battery_monitor.py:79
battery_monitor.battery_monitor.track_id_light
track_id_light
Definition: battery_monitor.py:81
battery_monitor.battery_monitor.say
def say(self, text)
Definition: battery_monitor.py:150
battery_monitor.battery_monitor.stop_light
def stop_light(self)
Definition: battery_monitor.py:135
battery_monitor.battery_monitor.last_time_warned
last_time_warned
Definition: battery_monitor.py:103
battery_monitor.battery_monitor.set_light
def set_light(self, mode, track=False)
Definition: battery_monitor.py:113
battery_monitor.battery_monitor.color_warning
color_warning
Definition: battery_monitor.py:61
battery_monitor.battery_monitor.color_error
color_error
Definition: battery_monitor.py:68
battery_monitor.battery_monitor.num_leds
num_leds
Definition: battery_monitor.py:47
battery_monitor.battery_monitor.threshold_critical
threshold_critical
Definition: battery_monitor.py:44
battery_monitor.battery_monitor.__init__
def __init__(self)
Definition: battery_monitor.py:34
battery_monitor.battery_monitor.color_charging
color_charging
Definition: battery_monitor.py:54
battery_monitor.battery_monitor.mode
mode
Definition: battery_monitor.py:40
battery_monitor.battery_monitor.timer_callback
def timer_callback(self, event)
Definition: battery_monitor.py:155
battery_monitor.battery_monitor.enable_light
enable_light
Definition: battery_monitor.py:46
battery_monitor.battery_monitor.topic_name
topic_name
Definition: battery_monitor.py:39
battery_monitor.battery_monitor.interval_duration_warning
interval_duration_warning
Definition: battery_monitor.py:77


cob_monitoring
Author(s): Florian Weisshardt , Felix Messmer
autogenerated on Fri Aug 2 2024 09:45:52