1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 import errno
29 import re
30 import sys
31
32 from threading import Lock
33
34 import rospy
35
36 from std_msgs.msg import (
37 Bool,
38 Empty,
39 )
40
41 import baxter_dataflow
42
43 from baxter_core_msgs.msg import (
44 AssemblyState,
45 )
46 from baxter_interface import settings
47
48
50 """
51 Class RobotEnable - simple control/status wrapper around robot state
52
53 enable() - enable all joints
54 disable() - disable all joints
55 reset() - reset all joints, reset all jrcp faults, disable the robot
56 stop() - stop the robot, similar to hitting the e-stop button
57 """
58
59 param_lock = Lock()
60
62 """
63 Version checking capable constructor.
64
65 @type versioned: bool
66 @param versioned: True to check robot software version
67 compatibility on initialization. False (default) to ignore.
68
69 The compatibility of robot versions to SDK (baxter_interface)
70 versions is defined in the L{baxter_interface.VERSIONS_SDK2ROBOT}.
71
72 By default, the class does not check, but all examples do. The
73 example behavior can be overridden by changing the value of
74 L{baxter_interface.CHECK_VERSION} to False.
75 """
76 self._state = None
77 state_topic = 'robot/state'
78 self._state_sub = rospy.Subscriber(state_topic,
79 AssemblyState,
80 self._state_callback
81 )
82 if versioned and not self.version_check():
83 sys.exit(1)
84
85 baxter_dataflow.wait_for(
86 lambda: not self._state is None,
87 timeout=2.0,
88 timeout_msg=("Failed to get robot state on %s" %
89 (state_topic,)),
90 )
91
94
96
97 pub = rospy.Publisher('robot/set_super_enable', Bool,
98 queue_size=10)
99
100 baxter_dataflow.wait_for(
101 test=lambda: self._state.enabled == status,
102 timeout=2.0 if status else 5.0,
103 timeout_msg=("Failed to %sable robot" %
104 ('en' if status else 'dis',)),
105 body=lambda: pub.publish(status),
106 )
107 rospy.loginfo("Robot %s", ('Enabled' if status else 'Disabled'))
108
110 """
111 Returns the last known robot state.
112 """
113 return self._state
114
116 """
117 Enable all joints
118 """
119 if self._state.stopped:
120 rospy.loginfo("Robot Stopped: Attempting Reset...")
121 self.reset()
122 self._toggle_enabled(True)
123
129
131 """
132 Reset all joints. Trigger JRCP hardware to reset all faults. Disable
133 the robot.
134 """
135 error_estop = """\
136 E-Stop is ASSERTED. Disengage E-Stop and then reset the robot.
137 """
138 error_nonfatal = """Non-fatal Robot Error on reset.
139 Robot reset cleared stopped state and robot can be enabled, but a non-fatal
140 error persists. Check diagnostics or rethink.log for more info.
141 """
142 error_env = """Failed to reset robot.
143 Please verify that the ROS_IP or ROS_HOSTNAME environment variables are set
144 and resolvable. For more information please visit:
145 http://sdk.rethinkrobotics.com/wiki/RSDK_Shell#Initialize
146 """
147 is_reset = lambda: (self._state.enabled == False and
148 self._state.stopped == False and
149 self._state.error == False and
150 self._state.estop_button == 0 and
151 self._state.estop_source == 0)
152 pub = rospy.Publisher('robot/set_super_reset', Empty, queue_size=10)
153
154 if (self._state.stopped and
155 self._state.estop_button == AssemblyState.ESTOP_BUTTON_PRESSED):
156 rospy.logfatal(error_estop)
157 raise IOError(errno.EREMOTEIO, "Failed to Reset: E-Stop Engaged")
158
159 rospy.loginfo("Resetting robot...")
160 try:
161 baxter_dataflow.wait_for(
162 test=is_reset,
163 timeout=3.0,
164 timeout_msg=error_env,
165 body=pub.publish
166 )
167 except OSError, e:
168 if e.errno == errno.ETIMEDOUT:
169 if self._state.error == True and self._state.stopped == False:
170 rospy.logwarn(error_nonfatal)
171 return False
172 raise
173
175 """
176 Simulate an e-stop button being pressed. Robot must be reset to clear
177 the stopped state.
178 """
179 pub = rospy.Publisher('robot/set_super_stop', Empty, queue_size=10)
180 baxter_dataflow.wait_for(
181 test=lambda: self._state.stopped == True,
182 timeout=3.0,
183 timeout_msg="Failed to stop the robot",
184 body=pub.publish,
185 )
186
188 """
189 Verifies the version of the software running on the robot is
190 compatible with this local version of the Baxter RSDK.
191
192 Currently uses the variables in baxter_interface.settings and
193 can be overridden for all default examples by setting CHECK_VERSION
194 to False.
195 """
196 param_name = "rethink/software_version"
197 sdk_version = settings.SDK_VERSION
198
199
200 with self.__class__.param_lock:
201 robot_version = rospy.get_param(param_name, None)
202 if not robot_version:
203 rospy.logwarn("RobotEnable: Failed to retrieve robot version "
204 "from rosparam: %s\n"
205 "Verify robot state and connectivity "
206 "(i.e. ROS_MASTER_URI)", param_name)
207 return False
208 else:
209
210 pattern = ("^([0-9]+)\.([0-9]+)\.([0-9]+)")
211 match = re.search(pattern, robot_version)
212 if not match:
213 rospy.logwarn("RobotEnable: Invalid robot version: %s",
214 robot_version)
215 return False
216 robot_version = match.string[match.start(1):match.end(3)]
217 if robot_version not in settings.VERSIONS_SDK2ROBOT[sdk_version]:
218 errstr_version = """RobotEnable: Software Version Mismatch.
219 Robot Software version (%s) does not match local SDK version (%s). Please
220 Update your Robot Software. \
221 See: http://sdk.rethinkrobotics.com/wiki/Software_Update"""
222 rospy.logerr(errstr_version, robot_version, sdk_version)
223 return False
224 return True
225