Skip to content

Commit aea70d9

Browse files
Merge remote-tracking branch 'origin/release-1.2.0'
2 parents 198bb49 + fb84083 commit aea70d9

File tree

9 files changed

+85
-33
lines changed

9 files changed

+85
-33
lines changed

CHANGELOG.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
1.2.0 (2015-12-21)
2+
---------------------------------
3+
- Added an optional parameter to Limb interface's move_to_joint_positions() to allow it to be aborted by test function
4+
Thanks to Yoan Mollard (ymollard) for submitting this pull request!
5+
- Added a wait for the endpoint_state messages to be received before exiting Limb init
6+
- Fixed a bug in the JTAS that would cause the robot to jump back into the last commanded pose when the
7+
robot is Disabled/Re-enabled
8+
- Fixed a bug that would cause the Limb's on_joint_states method to fail if extra <side> joints are added to the
9+
robot's /robot/joint_states
10+
- Due to baxter_core_msgs change, updated EndEffectorProperties CUSTOM_GRIPPER to PASSIVE_GRIPPER
11+
- Due to baxter_core_msgs change, updated head interface's speed range from [0, 100] to [0, 1.0]
12+
- Due to baxter_core_msgs change, updated Navigator interface to use update Nav topics and lights msg field
13+
114
1.1.1 (2015-5-15)
215
---------------------------------
316
- Fixed a bug that caused the JTAS to error with a path of one or two points is supplied as a trajectory

package.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0"?>
22
<package>
33
<name>baxter_interface</name>
4-
<version>1.1.1</version>
4+
<version>1.2.0</version>
55
<description>
66
Convenient python interface classes for control
77
of the Baxter Research Robot from Rethink Robotics.

src/baxter_interface/gripper.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def _on_gripper_prop(self, properties):
149149
self.on_type_changed({
150150
EndEffectorProperties.SUCTION_CUP_GRIPPER: 'suction',
151151
EndEffectorProperties.ELECTRIC_GRIPPER: 'electric',
152-
EndEffectorProperties.CUSTOM_GRIPPER: 'custom',
152+
EndEffectorProperties.PASSIVE_GRIPPER: 'custom',
153153
}.get(properties.ui_type, None))
154154

155155
def _inc_cmd_sequence(self):
@@ -380,7 +380,7 @@ def reset_custom_properties(self, timeout=2.0):
380380
@rtype: bool
381381
"""
382382
default_id = 131073
383-
default_ui_type = EndEffectorProperties.CUSTOM_GRIPPER
383+
default_ui_type = EndEffectorProperties.PASSIVE_GRIPPER
384384
default_manufacturer = 'Rethink Research Robot'
385385
default_product = 'SDK End Effector'
386386
# Create default properties message
@@ -953,7 +953,7 @@ def type(self):
953953
return {
954954
EndEffectorProperties.SUCTION_CUP_GRIPPER: 'suction',
955955
EndEffectorProperties.ELECTRIC_GRIPPER: 'electric',
956-
EndEffectorProperties.CUSTOM_GRIPPER: 'custom',
956+
EndEffectorProperties.PASSIVE_GRIPPER: 'custom',
957957
}.get(self._prop.ui_type, None)
958958

959959
def hardware_id(self):

src/baxter_interface/head.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def __init__(self):
8181

8282
def _on_head_state(self, msg):
8383
self._state['pan'] = msg.pan
84-
self._state['panning'] = msg.isPanning
84+
self._state['panning'] = msg.isTurning
8585
self._state['nodding'] = msg.isNodding
8686

8787
def pan(self):
@@ -111,20 +111,32 @@ def panning(self):
111111
"""
112112
return self._state['panning']
113113

114-
def set_pan(self, angle, speed=100, timeout=10.0):
114+
def set_pan(self, angle, speed=1.0, timeout=10.0, scale_speed=False):
115115
"""
116116
Pan at the given speed to the desired angle.
117117
118118
@type angle: float
119119
@param angle: Desired pan angle in radians.
120120
@type speed: int
121-
@param speed: Desired speed to pan at, range is 0-100 [100]
121+
@param speed: Desired speed to pan at, range is 0-1.0 [1.0]
122122
@type timeout: float
123123
@param timeout: Seconds to wait for the head to pan to the
124124
specified angle. If 0, just command once and
125125
return. [10]
126+
@param scale_speed: Scale speed to pan at by a factor of 100,
127+
to use legacy range between 0-100 [100]
126128
"""
127-
msg = HeadPanCommand(angle, speed)
129+
if scale_speed:
130+
cmd_speed = speed / 100.0;
131+
else:
132+
cmd_speed = speed
133+
if (cmd_speed < HeadPanCommand.MIN_SPEED_RATIO or
134+
cmd_speed > HeadPanCommand.MAX_SPEED_RATIO):
135+
rospy.logerr(("Commanded Speed, ({0}), outside of valid range"
136+
" [{1}, {2}]").format(cmd_speed,
137+
HeadPanCommand.MIN_SPEED_RATIO,
138+
HeadPanCommand.MAX_SPEED_RATIO))
139+
msg = HeadPanCommand(angle, cmd_speed, True)
128140
self._pub_pan.publish(msg)
129141

130142
if not timeout == 0:

src/baxter_interface/limb.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,14 @@ def __init__(self, limb):
119119
"from %s") % (self.name.capitalize(), joint_state_topic)
120120
baxter_dataflow.wait_for(lambda: len(self._joint_angle.keys()) > 0,
121121
timeout_msg=err_msg)
122+
err_msg = ("%s limb init failed to get current endpoint_state "
123+
"from %s") % (self.name.capitalize(), ns + 'endpoint_state')
124+
baxter_dataflow.wait_for(lambda: len(self._cartesian_pose.keys()) > 0,
125+
timeout_msg=err_msg)
122126

123127
def _on_joint_states(self, msg):
124128
for idx, name in enumerate(msg.name):
125-
if self.name in name:
129+
if name in self._joint_names[self.name]:
126130
self._joint_angle[name] = msg.position[idx]
127131
self._joint_velocity[name] = msg.velocity[idx]
128132
self._joint_effort[name] = msg.effort[idx]
@@ -399,7 +403,8 @@ def move_to_neutral(self, timeout=15.0):
399403
return self.move_to_joint_positions(angles, timeout)
400404

401405
def move_to_joint_positions(self, positions, timeout=15.0,
402-
threshold=settings.JOINT_ANGLE_TOLERANCE):
406+
threshold=settings.JOINT_ANGLE_TOLERANCE,
407+
test=None):
403408
"""
404409
(Blocking) Commands the limb to the provided positions.
405410
@@ -414,6 +419,7 @@ def move_to_joint_positions(self, positions, timeout=15.0,
414419
@type threshold: float
415420
@param threshold: position threshold in radians across each joint when
416421
move is considered successful [0.008726646]
422+
@param test: optional function returning True if motion must be aborted
417423
"""
418424
cmd = self.joint_angles()
419425

@@ -433,7 +439,8 @@ def joint_diff():
433439

434440
self.set_joint_positions(filtered_cmd())
435441
baxter_dataflow.wait_for(
436-
lambda: (all(diff() < threshold for diff in diffs)),
442+
test=lambda: callable(test) and test() == True or \
443+
(all(diff() < threshold for diff in diffs)),
437444
timeout=timeout,
438445
timeout_msg=("%s limb failed to reach commanded joint positions" %
439446
(self.name.capitalize(),)),

src/baxter_interface/navigator.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@
3030
import baxter_dataflow
3131

3232
from baxter_core_msgs.msg import (
33-
ITBState,
33+
NavigatorState,
3434
)
35+
3536
from baxter_interface import (
3637
digital_io,
3738
)
3839

39-
4040
class Navigator(object):
4141
"""
4242
Interface class for a Navigator on the Baxter robot.
@@ -82,17 +82,19 @@ def __init__(self, location):
8282
self.button2_changed = baxter_dataflow.Signal()
8383
self.wheel_changed = baxter_dataflow.Signal()
8484

85-
nav_state_topic = 'robot/itb/%s_itb/state' % (self._id,)
85+
nav_state_topic = 'robot/navigators/{0}_navigator/state'.format(self._id)
8686
self._state_sub = rospy.Subscriber(
8787
nav_state_topic,
88-
ITBState,
88+
NavigatorState,
8989
self._on_state)
9090

9191
self._inner_led = digital_io.DigitalIO(
92-
'%s_itb_light_inner' % (self._id,))
92+
'%s_inner_light' % (self._id,))
93+
self._inner_led_idx = 0
9394

9495
self._outer_led = digital_io.DigitalIO(
95-
'%s_itb_light_outer' % (self._id,))
96+
'%s_outer_light' % (self._id,))
97+
self._outer_led_idx = 1
9698

9799
init_err_msg = ("Navigator init failed to get current state from %s" %
98100
(nav_state_topic,))
@@ -132,7 +134,7 @@ def inner_led(self):
132134
"""
133135
Current state of the inner LED
134136
"""
135-
return self._state.innerLight
137+
return self._state.lights[self._inner_led_idx]
136138

137139
@inner_led.setter
138140
def inner_led(self, enable):
@@ -149,7 +151,7 @@ def outer_led(self):
149151
"""
150152
Current state of the outer LED.
151153
"""
152-
return self._state.outerLight
154+
return self._state.lights[self._outer_led_idx]
153155

154156
@outer_led.setter
155157
def outer_led(self, enable):
@@ -164,7 +166,14 @@ def outer_led(self, enable):
164166
def _on_state(self, msg):
165167
if not self._state:
166168
self._state = msg
167-
169+
try:
170+
self._inner_led_idx = self._state.light_names.index("inner")
171+
except:
172+
pass
173+
try:
174+
self._outer_led_idx = self._state.light_names.index("outer")
175+
except:
176+
pass
168177
if self._state == msg:
169178
return
170179

src/baxter_interface/settings.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@
2929
HEAD_PAN_ANGLE_TOLERANCE = 0.1396263401
3030

3131
## Versioning
32-
SDK_VERSION = '1.1.1'
32+
SDK_VERSION = '1.2.0'
3333
CHECK_VERSION = True
3434
# Version Compatibility Maps - {current: compatible}
35-
VERSIONS_SDK2ROBOT = {'1.1.1': ['1.1.1', '1.1.0']}
36-
VERSIONS_SDK2GRIPPER = {'1.1.1':
35+
VERSIONS_SDK2ROBOT = {'1.2.0': ['1.2.0']}
36+
VERSIONS_SDK2GRIPPER = {'1.2.0':
3737
{
3838
'warn': '2014/5/20 00:00:00', # Version 1.0.0
3939
'fail': '2013/10/15 00:00:00', # Version 0.6.2
4040
}
41-
}
41+
}

src/head_action/head_action.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@
4141
)
4242

4343
import baxter_interface
44+
from baxter_core_msgs.msg import (
45+
HeadPanCommand,
46+
)
47+
4448

4549
class HeadActionServer(object):
4650
def __init__(self, reconfig_server):
@@ -85,8 +89,8 @@ def _on_head_action(self, goal):
8589
position = goal.position
8690
velocity = goal.max_velocity
8791
# Apply max velocity if specified < 0
88-
if velocity < 0.0:
89-
velocity = 100.0
92+
if velocity < HeadPanCommand.MIN_SPEED_RATIO:
93+
velocity = HeadPanCommand.MAX_SPEED_RATIO
9094

9195
# Pull parameters that will define the head actuation
9296
self._get_head_parameters()

src/joint_trajectory_action/joint_trajectory_action.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ def __init__(self, limb, reconfig_server, rate=100.0,
7070
auto_start=False)
7171
self._action_name = rospy.get_name()
7272
self._limb = baxter_interface.Limb(limb)
73+
self._enable = baxter_interface.RobotEnable()
7374
self._name = limb
7475
self._cuff = baxter_interface.DigitalIO('%s_lower_cuff' % (limb,))
7576
self._cuff.state_changed.connect(self._cuff_cb)
@@ -120,6 +121,9 @@ def __init__(self, limb, reconfig_server, rate=100.0,
120121
tcp_nodelay=True,
121122
queue_size=1)
122123

124+
def robot_is_enabled(self):
125+
return self._enable.state().enabled
126+
123127
def clean_shutdown(self):
124128
self._alive = False
125129
self._limb.exit_control_mode()
@@ -225,7 +229,8 @@ def _command_stop(self, joint_names, joint_angles, start_time, dimensions_dict):
225229
if self._mode == 'velocity':
226230
velocities = [0.0] * len(joint_names)
227231
cmd = dict(zip(joint_names, velocities))
228-
while (not self._server.is_new_goal_available() and self._alive):
232+
while (not self._server.is_new_goal_available() and self._alive
233+
and self.robot_is_enabled()):
229234
self._limb.set_joint_velocities(cmd)
230235
if self._cuff_state:
231236
self._limb.exit_control_mode()
@@ -240,7 +245,8 @@ def _command_stop(self, joint_names, joint_angles, start_time, dimensions_dict):
240245
pnt.velocities = [0.0] * len(joint_names)
241246
if dimensions_dict['accelerations']:
242247
pnt.accelerations = [0.0] * len(joint_names)
243-
while (not self._server.is_new_goal_available() and self._alive):
248+
while (not self._server.is_new_goal_available() and self._alive
249+
and self.robot_is_enabled()):
244250
self._limb.set_joint_positions(joint_angles, raw=raw_pos_mode)
245251
# zero inverse dynamics feedforward command
246252
if self._mode == 'position_w_id':
@@ -253,16 +259,16 @@ def _command_stop(self, joint_names, joint_angles, start_time, dimensions_dict):
253259
rospy.sleep(1.0 / self._control_rate)
254260

255261
def _command_joints(self, joint_names, point, start_time, dimensions_dict):
256-
if self._server.is_preempt_requested():
262+
if self._server.is_preempt_requested() or not self.robot_is_enabled():
257263
rospy.loginfo("%s: Trajectory Preempted" % (self._action_name,))
258264
self._server.set_preempted()
259265
self._command_stop(joint_names, self._limb.joint_angles(), start_time, dimensions_dict)
260266
return False
261267
velocities = []
262268
deltas = self._get_current_error(joint_names, point.positions)
263269
for delta in deltas:
264-
if (math.fabs(delta[1]) >= self._path_thresh[delta[0]]
265-
and self._path_thresh[delta[0]] >= 0.0):
270+
if ((math.fabs(delta[1]) >= self._path_thresh[delta[0]]
271+
and self._path_thresh[delta[0]] >= 0.0)) or not self.robot_is_enabled():
266272
rospy.logerr("%s: Exceeded Error Threshold on %s: %s" %
267273
(self._action_name, delta[0], str(delta[1]),))
268274
self._result.error_code = self._result.PATH_TOLERANCE_VIOLATED
@@ -406,7 +412,8 @@ def _on_trajectory_action(self, goal):
406412
# Keep track of current indices for spline segment generation
407413
now_from_start = rospy.get_time() - start_time
408414
end_time = trajectory_points[-1].time_from_start.to_sec()
409-
while (now_from_start < end_time and not rospy.is_shutdown()):
415+
while (now_from_start < end_time and not rospy.is_shutdown() and
416+
self.robot_is_enabled()):
410417
#Acquire Mutex
411418
now = rospy.get_time()
412419
now_from_start = now - start_time
@@ -451,7 +458,7 @@ def check_goal_state():
451458
return True
452459

453460
while (now_from_start < (last_time + self._goal_time)
454-
and not rospy.is_shutdown()):
461+
and not rospy.is_shutdown() and self.robot_is_enabled()):
455462
if not self._command_joints(joint_names, last, start_time, dimensions_dict):
456463
return
457464
now_from_start = rospy.get_time() - start_time

0 commit comments

Comments
 (0)