sr_ur_arm_unlock.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # Copyright 2020, 2021 Shadow Robot Company Ltd.
3 #
4 # This program is free software: you can redistribute it and/or modify it
5 # under the terms of the GNU General Public License as published by the Free
6 # Software Foundation version 2 of the License.
7 #
8 # This program is distributed in the hope that it will be useful, but WITHOUT
9 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 # more details.
12 #
13 # You should have received a copy of the GNU General Public License along
14 # with this program. If not, see <http://www.gnu.org/licenses/>.
15 
16 import rospy
17 from std_msgs.msg import Bool
18 from ur_dashboard_msgs.srv import GetSafetyMode, GetProgramState, GetRobotMode, Load, IsProgramRunning
19 from ur_dashboard_msgs.msg import SafetyMode, ProgramState, RobotMode
20 from std_srvs.srv import Trigger
21 
22 
23 class RobotSafetyMonitor(object):
24  def __init__(self, name):
25  topic_string = '/' + name + '_sr_ur_robot_hw/safety_mode'
26  self.estop_pressed = False
27  self._subscriber = rospy.Subscriber(topic_string, SafetyMode,
29 
30  def press_estop(self):
31  self.estop_pressed = True
32 
33  def release_estop(self):
34  self.estop_pressed = False
35 
36  def _safety_mode_callback(self, message):
37  self.mode = message.mode
38  if message.mode == SafetyMode.ROBOT_EMERGENCY_STOP:
39  self.press_estop()
40 
41 
42 class SrUrUnlock(object):
43  def __init__(self):
44  self._external_control_program_name = rospy.get_param("~urcap_program_name", "external_ctrl.urp")
45  self._arms = []
46  if rospy.has_param('ra_sr_ur_robot_hw'):
47  self._arms.append('ra')
48  if rospy.has_param('la_sr_ur_robot_hw'):
49  self._arms.append('la')
50  if 0 == len(self._arms):
51  rospy.logerr("No arms detected, shutting down %s", rospy.get_name())
52  rospy.signal_shutdown("No arms detected")
53  rospy.Subscriber("/sr_arm/release_or_brake", Bool, self.release_or_brake_arm_cb)
56 
58  for arm in self._arms:
59  robot_safety_monitor = RobotSafetyMonitor(arm)
60  self._robot_state_monitors[arm] = robot_safety_monitor
61 
62  def release_or_brake_arm_cb(self, message):
63  if not message.data:
64  return
65 
66  if self.check_arms_needs_starting():
67  self.release_arm()
68  return
69 
70  self.brake_arm()
71 
72  def call_arm_service(self, side, service_name, service_type, dashboard=True, service_data=""):
73  if dashboard:
74  service_string = "/" + side + "_sr_ur_robot_hw/dashboard/" + service_name
75  else:
76  service_string = "/" + side + "_sr_ur_robot_hw/" + service_name
77  try:
78  service_call = rospy.ServiceProxy(service_string, service_type)
79  if "" == service_data:
80  response = service_call()
81  else:
82  response = service_call(service_data)
83  return response
84  except rospy.ServiceException as e:
85  rospy.logerr("Service call to '%s' failed for arm %s. %s", service_name, side, e)
86  raise
87 
88  def startup_arms(self):
89  if self.is_robot_in_mode('robot', RobotMode.RUNNING):
90  return
91  for arm in self._arms:
92  self.call_arm_service(arm, "power_on", Trigger)
93  self.wait_for_mode('robot', RobotMode.IDLE)
94  for arm in self._arms:
95  self.call_arm_service(arm, "brake_release", Trigger)
96  self.wait_for_mode('robot', RobotMode.RUNNING)
97 
98  def wait_for_mode(self, mode_type, mode, timeout=15):
99  now = rospy.rostime.Time().now().secs
100  while not self.is_robot_in_mode(mode_type, mode):
101  if rospy.rostime.Time().now().secs > now + timeout:
102  return False
103  return True
104 
105  def is_robot_in_mode(self, mode_type, mode):
106  if mode_type == 'robot':
107  arms_ready = [mode == self.call_arm_service(arm, "get_robot_mode",
108  GetRobotMode).robot_mode.mode for arm in self._arms]
109  elif mode_type == 'safety':
110  arms_ready = [mode == self.call_arm_service(arm, "get_safety_mode",
111  GetSafetyMode).safety_mode.mode for arm in self._arms]
112  return all(arms_ready)
113 
115  for arm in self._arms:
116  safety_mode = self.call_arm_service(arm, "get_safety_mode", GetSafetyMode)
117  if self._robot_state_monitors[arm].estop_pressed:
118  if SafetyMode.ROBOT_EMERGENCY_STOP == safety_mode.safety_mode.mode:
119  while SafetyMode.ROBOT_EMERGENCY_STOP == \
120  self.call_arm_service(arm, "get_safety_mode", GetSafetyMode).safety_mode.mode:
121  rospy.logwarn("Emergency stop button is still pressed for arm %s, please release", arm)
122  rospy.sleep(0.01)
123  rospy.loginfo("Past E-stop detected on arm %s, power-cycling that arm...", arm)
124  self._robot_state_monitors[arm].release_estop()
125  self.call_arm_service(arm, "power_off", Trigger)
126  rospy.sleep(0.1)
127 
129  for arm in self._arms:
130  safety_mode = self.call_arm_service(arm, "get_safety_mode", GetSafetyMode)
131  if SafetyMode.PROTECTIVE_STOP == safety_mode.safety_mode.mode:
132  rospy.loginfo("Protective stop detected on: %s. Unlocking...", arm)
133  while SafetyMode.PROTECTIVE_STOP == \
134  self.call_arm_service(arm, "get_safety_mode", GetSafetyMode).safety_mode.mode:
135  self.call_arm_service(arm, "unlock_protective_stop", Trigger)
136  rospy.sleep(0.01)
137 
139  fault = False
140  for arm in self._arms:
141  safety_mode = self.call_arm_service(arm, "get_safety_mode", GetSafetyMode)
142  if (SafetyMode.FAULT == safety_mode.safety_mode.mode or
143  SafetyMode.VIOLATION == safety_mode.safety_mode.mode):
144  fault = True
145  if SafetyMode.FAULT == safety_mode.safety_mode.mode:
146  rospy.loginfo("Fault detected on: %s. This can be caused by using the external e-stop.\
147  Have you released it?", arm)
148  self.call_arm_service(arm, "restart_safety", Trigger)
149  return fault
150 
152  for arm in self._arms:
153  robot_mode = self.call_arm_service(arm, "get_robot_mode", GetRobotMode)
154  safety_mode = self.call_arm_service(arm, "get_safety_mode", GetSafetyMode)
155  program_running = self.call_arm_service(arm, "program_running", IsProgramRunning)
156  if (RobotMode.IDLE == robot_mode.robot_mode.mode or RobotMode.POWER_OFF == robot_mode.robot_mode.mode or
157  SafetyMode.PROTECTIVE_STOP == safety_mode.safety_mode.mode or
158  not program_running.program_running):
159  rospy.loginfo("Starting arm: %s", arm)
160  return True
161  return False
162 
163  def clear_arms_popups(self):
164  for arm in self._arms:
165  self.call_arm_service(arm, "close_safety_popup", Trigger)
166  for arm in self._arms:
167  self.call_arm_service(arm, "close_popup", Trigger)
168 
170  sleep_time = False
171  for arm in self._arms:
172  try:
173  headless_mode = rospy.get_param("/" + arm + "_sr_ur_robot_hw/headless_mode")
174  except KeyError:
175  headless_mode = False
176  if not headless_mode:
177  play_msg = self.call_arm_service(arm, "program_state", GetProgramState)
178  if "null" == play_msg.program_name:
179  rospy.loginfo("Not in headless mode. Loading program: %s for arm: %s",
181  resp = self.call_arm_service(arm, "load_program", Load,
182  service_data=self._external_control_program_name)
183  rospy.loginfo("%s", resp)
184  sleep_time = True
185  return sleep_time
186 
188  sleep_time = False
189  for arm in self._arms:
190  try:
191  headless_mode = rospy.get_param("/" + arm + "_sr_ur_robot_hw/headless_mode")
192  except KeyError:
193  headless_mode = False
194  if not headless_mode:
195  play_msg = self.call_arm_service(arm, "program_state", GetProgramState)
196  if ProgramState.STOPPED == play_msg.state.state or ProgramState.PAUSED == play_msg.state.state:
197  rospy.loginfo("Not in headless mode. Starting program: %s for arm: %s",
198  play_msg.program_name, arm)
199  self.call_arm_service(arm, "play", Trigger)
200  sleep_time = True
201  else:
202  rospy.loginfo("Headless mode active, resending robot program to arm: %s", arm)
203  self.call_arm_service(arm, "resend_robot_program", Trigger, dashboard=False)
204  self.call_arm_service(arm, "resend_robot_program", Trigger, dashboard=False)
205  sleep_time = True
206  return sleep_time
207 
208  def release_arm(self):
209  try:
210  rospy.loginfo("Unlock arm(s) signal received. Checking arms.")
211  rospy.loginfo("Checking e-stops ...")
212  self.check_arms_e_stops()
213  rospy.loginfo("Checking protective stops ...")
215  rospy.loginfo("Checking for faults ...")
216  if self.unlock_arms_if_fault():
217  rospy.loginfo("Resetting robot safety, please wait approximately 15 seconds...")
218  self.wait_for_mode('safety', SafetyMode.NORMAL, timeout=15)
219  rospy.loginfo("Checking protective stops again ...")
221  rospy.loginfo("Closing popups ...")
222  self.clear_arms_popups()
223  rospy.loginfo("Checking robot mode ...")
224  if self.check_arms_needs_starting():
225  self.startup_arms()
226  rospy.loginfo("Checking if program is loaded ...")
228  rospy.loginfo("Checking if program is running ...")
230  except rospy.ServiceException as e:
231  for arm in self._arms:
232  rospy.logerr("Arm checking/restarting failed for arm: %s. %s", arm, e)
233 
234  def brake_arm(self):
235  rospy.loginfo("Brake arm signal received.")
236  for arm in self._arms:
237  try:
238  self.call_arm_service(arm, "power_off", Trigger)
239  except rospy.ServiceException as e:
240  rospy.logerr("Arm braking failed for arm: %s. %s", arm, e)
def call_arm_service(self, side, service_name, service_type, dashboard=True, service_data="")
def wait_for_mode(self, mode_type, mode, timeout=15)


sr_robot_launch
Author(s): Kirsty Ellis
autogenerated on Mon Feb 28 2022 23:52:26