emergency_stop_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 sys
19 import copy
20 from enum import IntEnum
21 
22 import rospy
23 from std_msgs.msg import Empty
24 from sensor_msgs.msg import JointState
25 from diagnostic_msgs.msg import DiagnosticStatus, DiagnosticArray
26 
27 from cob_msgs.msg import *
28 from cob_light.msg import LightMode, LightModes, SetLightModeGoal, SetLightModeAction
29 from cob_light.srv import StopLightMode, StopLightModeRequest
30 
31 from simple_script_server import *
33 
34 class EMState(IntEnum):
35  EM_UNKNOWN = -1
36  EM_FREE = 0
37  EM_BUTTON = 1
38  EM_BRAKE = 2
39  EM_LASER = 3
40  EM_WIRELESS = 4
41  EM_FALL = 5
42  EM_INTERNAL = 6
43 
44 
46  def __init__(self):
47  self.color = "None"
48  self.enable_sound = rospy.get_param("~enable_sound", False)
49  self.enable_light = rospy.get_param("~enable_light", False)
50  self.diagnostics_based = rospy.get_param("~diagnostics_based", False)
51  self.motion_based = rospy.get_param("~motion_based", False)
52  self.topic_based = rospy.get_param("~topic_based", False)
53  self.track_id_light = None
54 
55  if(self.enable_light):
56  if not rospy.has_param("~light_components"):
57  rospy.logwarn("parameter light_components does not exist on ROS Parameter Server, aborting...")
58  sys.exit(1)
59  self.light_components = rospy.get_param("~light_components")
60 
61  # set colors (also neccessary if self.enable_light is false)
62  self.color_error = rospy.get_param("~color_error","red")
63  self.color_warn = rospy.get_param("~color_warn","yellow")
64  self.color_ok = rospy.get_param("~color_ok","green")
65  self.color_off = rospy.get_param("~color_off","black")
66 
67  if(self.enable_sound):
68  if not rospy.has_param("~sound_components"):
69  rospy.logwarn("parameter sound_components does not exist on ROS Parameter Server, aborting...")
70  sys.exit(1)
71  self.sound_components = rospy.get_param("~sound_components")
72 
73  self.sound_em_button_released = rospy.get_param("~sound_em_button_released", "button released")
74  self.sound_em_button_issued = rospy.get_param("~sound_em_button_issued", "button issued")
75  self.sound_em_brake_released = rospy.get_param("~sound_em_brake_released", "brake released")
76  self.sound_em_brake_issued = rospy.get_param("~sound_em_brake_issued", "brake issued")
77  self.sound_em_laser_released = rospy.get_param("~sound_em_laser_released", "laser released")
78  self.sound_em_laser_issued = rospy.get_param("~sound_em_laser_issued", "laser issued")
79  self.sound_em_wireless_released = rospy.get_param("~sound_em_wireless_released", "wireless released")
80  self.sound_em_wireless_issued = rospy.get_param("~sound_em_wireless_issued", "wireless issued")
81  self.sound_em_fall_released = rospy.get_param("~sound_em_fall_released", "fall released")
82  self.sound_em_fall_issued = rospy.get_param("~sound_em_fall_issued", "fall issued")
83  self.sound_em_internal_released = rospy.get_param("~sound_em_internal_released", "internal released")
84  self.sound_em_internal_issued = rospy.get_param("~sound_em_internal_issued", "internal issued")
85 
86  self.em_state = EMState.EM_UNKNOWN
87  self.last_em_topic_state = EmergencyStopState.EMFREE
88 
89  if not self.topic_based:
90  self.diag_status = -1
91  rospy.Subscriber("/diagnostics_agg", DiagnosticArray, self.diagnostics_agg_callback, queue_size=1)
92  else:
93  self.diag_status = DiagnosticStatus.OK
94 
95  if(self.diagnostics_based):
96  rospy.Subscriber("/diagnostics_toplevel_state", DiagnosticStatus, self.diagnostics_callback, queue_size=1)
97  self.last_diag = rospy.get_rostime()
98 
99  self.motion_status = -1
100  if(self.motion_based):
101  rospy.Subscriber("/joint_states", JointState, self.jointstate_callback, queue_size=1)
102  self.last_vel = rospy.get_rostime()
103 
104  if(self.topic_based):
105  emergency_stop_topic = rospy.get_param("~emergency_stop_topic", "/emergency_stop_state")
106  rospy.Subscriber(emergency_stop_topic, EmergencyStopState, self.emergency_stop_callback, queue_size=1)
107  self.last_topic = rospy.get_rostime()
108 
109  self.pub_em_button_released = rospy.Publisher('em_button_released' , Empty, queue_size=1)
110  self.pub_brake_released = rospy.Publisher('brake_released' , Empty, queue_size=1)
111  self.pub_em_laser_released = rospy.Publisher('em_laser_released' , Empty, queue_size=1)
112  self.pub_em_wireless_released = rospy.Publisher('em_wireless_released', Empty, queue_size=1)
113  self.pub_em_fall_released = rospy.Publisher('em_fall_released' , Empty, queue_size=1)
114  self.pub_em_internal_released = rospy.Publisher('em_internal_released', Empty, queue_size=1)
115 
116  def diagnostics_agg_callback(self, msg):
117  diagnostics_errors = []
118  diagnostics_errors_detail = []
119 
120  #all diagnostics that have warning/error/stale
121  for status in msg.status:
122  if "Safety" in status.name:
123  if status.level > DiagnosticStatus.WARN:
124  diagnostics_errors.append(status)
125 
126  #reduce list to most detailed description only
127  for i, status in enumerate(diagnostics_errors):
128  tmp = diagnostics_errors[:i]+diagnostics_errors[i+1:]
129  if not next((True for status2 in tmp if status2.name.startswith(status.name)), False):
130  diagnostics_errors_detail.append(status)
131 
132  if not diagnostics_errors_detail:
133  if self.em_state > EMState.EM_FREE:
134  self.stop_light()
135  if self.em_state == EMState.EM_BUTTON:
136  self.pub_em_button_released.publish(Empty())
137  self.say(self.sound_em_button_released)
138  elif self.em_state == EMState.EM_BRAKE:
139  self.pub_brake_released.publish(Empty())
140  self.say(self.sound_em_brake_released)
141  elif self.em_state == EMState.EM_LASER:
142  self.pub_em_laser_released.publish(Empty())
143  self.say(self.sound_em_laser_released)
144  elif self.em_state == EMState.EM_WIRELESS:
145  self.pub_em_wireless_released.publish(Empty())
147  elif self.em_state == EMState.EM_FALL:
148  self.pub_em_fall_released.publish(Empty())
149  self.say(self.sound_em_fall_released)
150  elif self.em_state == EMState.EM_INTERNAL:
151  self.pub_em_internal_released.publish(Empty())
153  self.em_state = EMState.EM_FREE
154 
155  #determine error state
156  sound_output = ""
157  em_state = EMState.EM_UNKNOWN
158  for status in diagnostics_errors_detail:
159  if "Safety" in status.name:
160  for value in status.values:
161  if (value.key == "button_stop_ok"):
162  if (value.value == "False"):
163  if em_state <= EMState.EM_FREE or em_state > EMState.EM_BUTTON:
164  sound_output = self.sound_em_button_issued
165  em_state = EMState.EM_BUTTON
166  if (value.key == "brake_stop_ok"):
167  if (value.value == "False"):
168  if em_state <= EMState.EM_FREE or em_state > EMState.EM_BRAKE:
169  sound_output = self.sound_em_brake_issued
170  em_state = EMState.EM_BRAKE
171  if (value.key == "laser_stop_ok"):
172  if (value.value == "False"):
173  if em_state <= EMState.EM_FREE or em_state > EMState.EM_LASER:
174  sound_output = self.sound_em_laser_issued
175  em_state = EMState.EM_LASER
176  if (value.key == "wireless_stop_ok"):
177  if (value.value == "False"):
178  if em_state <= EMState.EM_FREE or em_state > EMState.EM_WIRELESS:
179  sound_output = self.sound_em_wireless_issued
180  em_state = EMState.EM_WIRELESS
181  if (value.key == "fall_sensor_front_ok"):
182  if (value.value == "False"):
183  if em_state <= EMState.EM_FREE or self.em_state > EMState.EM_FALL:
184  sound_output = self.sound_em_fall_issued
185  em_state = EMState.EM_FALL
186  if (value.key == "fall_sensor_left_ok"):
187  if (value.value == "False"):
188  if em_state <= EMState.EM_FREE or em_state > EMState.EM_FALL:
189  sound_output = self.sound_em_fall_issued
190  em_state = EMState.EM_FALL
191  if (value.key == "fall_sensor_right_ok"):
192  if (value.value == "False"):
193  if em_state <= EMState.EM_FREE or em_state > EMState.EM_FALL:
194  sound_output = self.sound_em_fall_issued
195  em_state = EMState.EM_FALL
196  if (value.key == "fall_sensors_released"):
197  if (value.value == "False"):
198  if em_state <= EMState.EM_FREE or em_state > EMState.EM_FALL:
199  sound_output = self.sound_em_fall_issued
200  em_state = EMState.EM_FALL
201  if (value.key == "efi_bus_front_io_error"):
202  if (value.value == "True"):
203  if em_state <= EMState.EM_FREE or em_state > EMState.EM_INTERNAL:
204  sound_output = self.sound_em_internal_issued
205  em_state = EMState.EM_INTERNAL
206  if (value.key == "efi_bus_left_io_error"):
207  if (value.value == "True"):
208  if em_state <= EMState.EM_FREE or em_state > EMState.EM_INTERNAL:
209  sound_output = self.sound_em_internal_issued
210  em_state = EMState.EM_INTERNAL
211  if (value.key == "efi_bus_right_io_error"):
212  if (value.value == "True"):
213  if em_state <= EMState.EM_FREE or em_state > EMState.EM_INTERNAL:
214  sound_output = self.sound_em_internal_issued
215  em_state = EMState.EM_INTERNAL
216 
217  rospy.logdebug("self.em_state: %d, em_state: %d"%(self.em_state, em_state))
218  if self.em_state != em_state and em_state > EMState.EM_FREE:
219  #emergency_stop_monitoring has higher priority
220  self.set_light(self.color_error)
221  self.say(sound_output)
222  self.em_state = em_state
223  rospy.logdebug("self.em_state: %d"%(self.em_state))
224 
225 
226  def diagnostics_callback(self, msg):
227  if self.em_state > EMState.EM_FREE:
228  #emergency_stop_monitoring has higher priority
229  return
230 
231  if self.diag_status != msg.level:
232  self.diag_status = msg.level
233  rospy.loginfo("Diagnostics change to "+ str(self.diag_status))
234 
235  if msg.level == DiagnosticStatus.OK:
236  self.stop_light()
237  self.motion_status = -1
238  else: # warning or error
239  self.set_light(self.color_warn)
240 
241 
242  def jointstate_callback(self, msg):
243  if self.em_state > EMState.EM_FREE:
244  #emergency_stop_monitoring has higher priority
245  return
246  if self.diag_status != DiagnosticStatus.OK:
247  #diagnostics_monitoring has higher priority
248  return
249 
250  threshold = 0.1
251  moving = 0
252  for v in msg.velocity:
253  if abs(v) > threshold:
254  moving = 1
255  break
256 
257  if self.motion_status != moving:
258  self.motion_status = moving
259  rospy.loginfo("Motion change to "+ str(self.motion_status))
260 
261  if moving == 0: # not moving
262  self.stop_light()
263  else: # moving
264  self.set_light(self.color_warn, True)
265 
266 
267  def emergency_stop_callback(self, msg):
268  if msg.emergency_state == EmergencyStopState.EMSTOP:
269  if not self.last_em_topic_state == msg.emergency_state:
270  if msg.emergency_button_stop:
271  self.em_state = EMState.EM_BUTTON
272  rospy.logwarn("Emergency stop button has been issued!")
273  elif msg.scanner_stop:
274  self.em_state = EMState.EM_LASER
275  rospy.logwarn("Scanner stop has been issued!")
276  else:
277  self.em_state = EMState.EM_UNKNOWN
278  self.set_light(self.color_error)
279  self.last_em_topic_state = msg.emergency_state
280 
281  if msg.emergency_state == EmergencyStopState.EMFREE:
282  if not self.last_em_topic_state == msg.emergency_state:
283  rospy.loginfo("Emergency stop released")
284  self.em_state = EMState.EM_FREE
285  self.stop_light()
286  self.last_em_topic_state = msg.emergency_state
287 
288 
289 
290  def set_light(self, color, flashing=False):
291  if self.enable_light:
292  for component in self.light_components:
293  error_code, color_rgba = sss.compose_color(component, color)
294 
295  action_server_name = component + "/set_light"
296  client = actionlib.SimpleActionClient(action_server_name, SetLightModeAction)
297  # trying to connect to server
298  rospy.logdebug("waiting for %s action server to start",action_server_name)
299  if not client.wait_for_server(rospy.Duration(5)):
300  # error: server did not respond
301  rospy.logerr("%s action server not ready within timeout, aborting...", action_server_name)
302  else:
303  rospy.logdebug("%s action server ready",action_server_name)
304 
305  # sending goal
306  mode = LightMode()
307  mode.priority = 10
308  mode.colors = []
309  mode.colors.append(color_rgba)
310  if flashing:
311  mode.mode = LightModes.FLASH #Flashing
312  mode.frequency = 2.0 #Hz
313  else:
314  mode.mode = LightModes.GLOW #Glow
315  mode.frequency = 10.0 #Hz
316 
317  goal = SetLightModeGoal()
318  goal.mode = mode
319  client.send_goal(goal)
320  client.wait_for_result()
321  result = client.get_result()
322  self.track_id_light = result.track_id
323 
324  self.color = color
325  def stop_light(self):
326  if self.enable_light:
327  if self.track_id_light is not None:
328  for component in self.light_components:
329  srv_server_name = component + "/stop_mode"
330  try:
331  rospy.wait_for_service(srv_server_name, timeout=2)
332  srv_proxy = rospy.ServiceProxy(srv_server_name, StopLightMode)
333  req = StopLightModeRequest()
334  req.track_id = self.track_id_light
335  srv_proxy(req)
336  except Exception as e:
337  rospy.logerr("%s service failed: %s",srv_server_name, e)
338 
339  def say(self, text):
340  if self.enable_sound and text:
341  for component in self.sound_components:
342  sss.say(component, [text])
343 
344 if __name__ == "__main__":
345  rospy.init_node("emergency_stop_monitor")
347  rospy.spin()
emergency_stop_monitor.emergency_stop_monitor.pub_em_internal_released
pub_em_internal_released
Definition: emergency_stop_monitor.py:114
msg
emergency_stop_monitor.emergency_stop_monitor.diagnostics_based
diagnostics_based
Definition: emergency_stop_monitor.py:50
emergency_stop_monitor.emergency_stop_monitor.__init__
def __init__(self)
Definition: emergency_stop_monitor.py:46
emergency_stop_monitor.emergency_stop_monitor.sound_em_laser_issued
sound_em_laser_issued
Definition: emergency_stop_monitor.py:78
emergency_stop_monitor.emergency_stop_monitor.color
color
Definition: emergency_stop_monitor.py:47
emergency_stop_monitor.emergency_stop_monitor.sound_em_wireless_released
sound_em_wireless_released
Definition: emergency_stop_monitor.py:79
emergency_stop_monitor.emergency_stop_monitor.jointstate_callback
def jointstate_callback(self, msg)
Motion Monitoring.
Definition: emergency_stop_monitor.py:242
emergency_stop_monitor.emergency_stop_monitor.motion_based
motion_based
Definition: emergency_stop_monitor.py:51
emergency_stop_monitor.emergency_stop_monitor.set_light
def set_light(self, color, flashing=False)
set light
Definition: emergency_stop_monitor.py:290
emergency_stop_monitor.emergency_stop_monitor.sound_em_internal_issued
sound_em_internal_issued
Definition: emergency_stop_monitor.py:84
emergency_stop_monitor.emergency_stop_monitor.motion_status
motion_status
Definition: emergency_stop_monitor.py:99
emergency_stop_monitor.emergency_stop_monitor.pub_brake_released
pub_brake_released
Definition: emergency_stop_monitor.py:110
emergency_stop_monitor.emergency_stop_monitor.sound_em_fall_issued
sound_em_fall_issued
Definition: emergency_stop_monitor.py:82
emergency_stop_monitor.emergency_stop_monitor.enable_light
enable_light
Definition: emergency_stop_monitor.py:49
emergency_stop_monitor.emergency_stop_monitor.sound_em_fall_released
sound_em_fall_released
Definition: emergency_stop_monitor.py:81
emergency_stop_monitor.emergency_stop_monitor.enable_sound
enable_sound
Definition: emergency_stop_monitor.py:48
emergency_stop_monitor.emergency_stop_monitor.track_id_light
track_id_light
Definition: emergency_stop_monitor.py:53
emergency_stop_monitor.emergency_stop_monitor.pub_em_button_released
pub_em_button_released
Definition: emergency_stop_monitor.py:109
emergency_stop_monitor.emergency_stop_monitor.last_diag
last_diag
Definition: emergency_stop_monitor.py:97
emergency_stop_monitor.emergency_stop_monitor.em_state
em_state
Definition: emergency_stop_monitor.py:86
emergency_stop_monitor.emergency_stop_monitor.color_warn
color_warn
Definition: emergency_stop_monitor.py:63
emergency_stop_monitor.emergency_stop_monitor.pub_em_laser_released
pub_em_laser_released
Definition: emergency_stop_monitor.py:111
actionlib::SimpleActionClient
simple_script_server
emergency_stop_monitor.emergency_stop_monitor.last_vel
last_vel
Definition: emergency_stop_monitor.py:102
emergency_stop_monitor.emergency_stop_monitor.sound_em_button_issued
sound_em_button_issued
Definition: emergency_stop_monitor.py:74
emergency_stop_monitor.emergency_stop_monitor.diagnostics_agg_callback
def diagnostics_agg_callback(self, msg)
Definition: emergency_stop_monitor.py:116
emergency_stop_monitor.emergency_stop_monitor.last_topic
last_topic
Definition: emergency_stop_monitor.py:107
emergency_stop_monitor.emergency_stop_monitor.sound_em_internal_released
sound_em_internal_released
Definition: emergency_stop_monitor.py:83
emergency_stop_monitor.emergency_stop_monitor.sound_components
sound_components
Definition: emergency_stop_monitor.py:71
emergency_stop_monitor.emergency_stop_monitor.stop_light
def stop_light(self)
Definition: emergency_stop_monitor.py:325
emergency_stop_monitor.emergency_stop_monitor.sound_em_brake_released
sound_em_brake_released
Definition: emergency_stop_monitor.py:75
emergency_stop_monitor.emergency_stop_monitor
Definition: emergency_stop_monitor.py:45
emergency_stop_monitor.emergency_stop_monitor.say
def say(self, text)
Definition: emergency_stop_monitor.py:339
emergency_stop_monitor.emergency_stop_monitor.color_off
color_off
Definition: emergency_stop_monitor.py:65
emergency_stop_monitor.emergency_stop_monitor.diag_status
diag_status
Definition: emergency_stop_monitor.py:90
emergency_stop_monitor.emergency_stop_monitor.last_em_topic_state
last_em_topic_state
Definition: emergency_stop_monitor.py:87
emergency_stop_monitor.emergency_stop_monitor.pub_em_fall_released
pub_em_fall_released
Definition: emergency_stop_monitor.py:113
emergency_stop_monitor.emergency_stop_monitor.color_error
color_error
Definition: emergency_stop_monitor.py:62
emergency_stop_monitor.emergency_stop_monitor.sound_em_brake_issued
sound_em_brake_issued
Definition: emergency_stop_monitor.py:76
emergency_stop_monitor.EMState
Definition: emergency_stop_monitor.py:34
emergency_stop_monitor.emergency_stop_monitor.diagnostics_callback
def diagnostics_callback(self, msg)
Diagnostics monitoring.
Definition: emergency_stop_monitor.py:226
emergency_stop_monitor.emergency_stop_monitor.color_ok
color_ok
Definition: emergency_stop_monitor.py:64
emergency_stop_monitor.emergency_stop_monitor.light_components
light_components
Definition: emergency_stop_monitor.py:59
emergency_stop_monitor.emergency_stop_monitor.sound_em_laser_released
sound_em_laser_released
Definition: emergency_stop_monitor.py:77
emergency_stop_monitor.emergency_stop_monitor.topic_based
topic_based
Definition: emergency_stop_monitor.py:52
emergency_stop_monitor.emergency_stop_monitor.pub_em_wireless_released
pub_em_wireless_released
Definition: emergency_stop_monitor.py:112
emergency_stop_monitor.emergency_stop_monitor.sound_em_wireless_issued
sound_em_wireless_issued
Definition: emergency_stop_monitor.py:80
emergency_stop_monitor.emergency_stop_monitor.sound_em_button_released
sound_em_button_released
Definition: emergency_stop_monitor.py:73
emergency_stop_monitor.emergency_stop_monitor.emergency_stop_callback
def emergency_stop_callback(self, msg)
Topic Monitoring.
Definition: emergency_stop_monitor.py:267


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