Skip to content

Commit efa120a

Browse files
committed
Merge branch 'master' of https://github.com/personalrobotics/prpy into feature/bodypoint_acceleration_helper_functions
Conflicts: src/prpy/util.py
2 parents 2b20e0e + 6debbfb commit efa120a

37 files changed

+1437
-1049
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
11
*.pyc
2+
3+
# Generated by nosetest
4+
*.noseids
5+
6+
# Generated by CBiRRT
7+
**/cmovetraj.txt

catkin.cmake

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,5 @@ catkin_package()
55
catkin_python_setup()
66

77
if (CATKIN_ENABLE_TESTING)
8-
catkin_add_nosetests(tests/test_PlanningPipeline.py)
9-
catkin_add_nosetests(tests/test_DistanceFieldManager.py)
8+
catkin_add_nosetests(tests)
109
endif()

src/prpy/base/manipulator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ def _PlanWrapper(self, planning_method, args, kw_args):
181181
traj = CopyTrajectory(cloned_traj, env=robot.GetEnv())
182182

183183
# Optionally execute the trajectory.
184-
if 'execute' not in kw_args or kw_args['execute']:
184+
if kw_args.get('execute', False):
185185
return self.GetRobot().ExecutePath(traj, **kw_args)
186186
else:
187187
return traj

src/prpy/base/mico.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,12 @@ def __init__(self, sim,
4545
with env:
4646
dof_indices = self.GetIndices()
4747
accel_limits = robot.GetDOFAccelerationLimits()
48-
accel_limits[dof_indices[0:3]] = 1.2
49-
accel_limits[dof_indices[3:6]] = 1.0
48+
accel_limits[dof_indices[0]] = 1.45
49+
accel_limits[dof_indices[1]] = 1.56
50+
accel_limits[dof_indices[2]] = 1.56
51+
accel_limits[dof_indices[3]] = 1.5
52+
accel_limits[dof_indices[4]] = 1.48
53+
accel_limits[dof_indices[5]] = 1.49
5054
robot.SetDOFAccelerationLimits(accel_limits)
5155

5256
# Load or_nlopt_ik as the IK solver. Unfortunately, IKFast doesn't work

src/prpy/base/robot.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,13 @@ def do_postprocess():
340340
cloned_robot, shortcut_path, defer=False,
341341
**smoothing_options)
342342

343-
return CopyTrajectory(traj, env=self.GetEnv())
343+
# Copy the trajectory into the output environment.
344+
output_traj = CopyTrajectory(traj, env=self.GetEnv())
345+
346+
# Copy meta-data from the path to the output trajectory.
347+
output_traj.SetDescription(path.GetDescription())
348+
349+
return output_traj
344350

345351
if defer is True:
346352
from trollius.executor import get_default_executor

src/prpy/base/wam.py

Lines changed: 140 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,17 @@
2828
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2929
# POSSIBILITY OF SUCH DAMAGE.
3030

31+
import logging
3132
import numpy
3233
import openravepy
34+
import warnings
3335
from manipulator import Manipulator
3436
from prpy.clone import Clone
3537
from .. import util
3638
from .. import exceptions
3739

40+
logger = logging.getLogger('wam')
41+
3842
class WAM(Manipulator):
3943
def __init__(self, sim, owd_namespace,
4044
iktype=openravepy.IkParameterization.Type.Transform6D):
@@ -55,7 +59,7 @@ def __init__(self, sim, owd_namespace,
5559
if sim:
5660
from prpy.simulation import ServoSimulator
5761
self.servo_simulator = ServoSimulator(
58-
self, rate=20, watchdog_timeout=0.1)
62+
self, rate=20, watchdog_timeout=0.1)
5963

6064
def CloneBindings(self, parent):
6165
Manipulator.CloneBindings(self, parent)
@@ -90,6 +94,30 @@ def SetStiffness(manipulator, stiffness):
9094
if not manipulator.simulated:
9195
manipulator.controller.SendCommand('SetStiffness {0:f}'.format(stiffness))
9296

97+
def SetTrajectoryExecutionOptions(self, traj, stop_on_stall=False,
98+
stop_on_ft=False, force_magnitude=None, force_direction=None,
99+
torque=None):
100+
"""Set OWD's trajectory execution options on trajectory.
101+
@param stop_on_stall aborts the trajectory if the arm stalls
102+
@param stop_on_ft aborts the trajectory if the force/torque
103+
sensor reports a force or torque that exceeds
104+
threshold specified by the force_magnitude,
105+
force_direction, and torque options
106+
@param force_magnitude force threshold value, in Newtons
107+
@param force_direction unit vector in the force/torque coordinate
108+
frame, which is int he same orientation as the
109+
hand frame.
110+
@param torque vector of the three torques
111+
"""
112+
util.SetTrajectoryTags(traj, {
113+
'owd_options': {
114+
'stop_on_stall': bool(stop_on_stall),
115+
'stop_on_ft': bool(stop_on_ft),
116+
'force_magnitude': float(force_magnitude),
117+
'force_direction': list(force_direction),
118+
'torque': list(torque),
119+
}}, append=True)
120+
93121
def Servo(manipulator, velocities):
94122
"""Servo with a vector of instantaneous joint velocities.
95123
@param velocities joint velocities, in radians per second
@@ -137,7 +165,7 @@ def ServoTo(manipulator, target, duration, timeStep=0.05, collisionChecking=True
137165
else:
138166
return False
139167

140-
def GetVelocityLimits(self, openrave=True, owd=True):
168+
def GetVelocityLimits(self, openrave=None, owd=None):
141169
"""Get the OpenRAVE and OWD joint velocity limits.
142170
This function checks both the OpenRAVE and OWD joint velocity limits.
143171
If they do not match, a warning is printed and the minimum value is
@@ -146,37 +174,13 @@ def GetVelocityLimits(self, openrave=True, owd=True):
146174
@param owd flag to set the OWD velocity limits
147175
@return list of velocity limits, in radians per second
148176
"""
149-
# Update the OpenRAVE limits.
150-
if openrave:
151-
or_velocity_limits = Manipulator.GetVelocityLimits(self)
152-
if self.simulated or not owd:
153-
return or_velocity_limits
154-
155-
# Update the OWD limits.
156-
if owd and not self.simulated:
157-
args = [ 'GetSpeed' ]
158-
args_str = ' '.join(args)
159-
owd_speed_limits_all = self.controller.SendCommand(args_str)
160-
#if we get nothing back, e.g. if the arm isn't running, return openrave lims
161-
if owd_speed_limits_all is None:
162-
return or_velocity_limits
163-
164-
owd_speed_limits = map(float, owd_speed_limits_all.split(','));
165-
#first 7 numbers are velocity limits
166-
owd_velocity_limits = numpy.array(owd_speed_limits[0:len(self.GetIndices())])
167-
168-
diff_arr = numpy.subtract(or_velocity_limits, owd_velocity_limits)
169-
max_diff = max(abs(diff_arr))
170-
171-
if max_diff > 0.01:
172-
# TODO: Change this to use the logging framework.
173-
print('GetVelocityLimits Error: openrave and owd limits very different')
174-
print('\tOpenrave limits:\t' + str(or_velocity_limits))
175-
print('\tOWD limits:\t\t' + str(owd_velocity_limits))
177+
if openrave is not None or owd is not None:
178+
warnings.warn(
179+
'The "openrave" and "owd" flags are deprecated in'
180+
' GetVelocityLimits and will be removed in a future version.',
181+
DeprecationWarning)
176182

177-
return numpy.minimum(or_velocity_limits, owd_velocity_limits)
178-
179-
return or_velocity_limits
183+
return Manipulator.GetVelocityLimits(self)
180184

181185
def SetVelocityLimits(self, velocity_limits, min_accel_time,
182186
openrave=True, owd=True):
@@ -218,106 +222,130 @@ def ClearTrajectoryStatus(manipulator):
218222
if not manipulator.simulated:
219223
manipulator.controller.SendCommand('ClearStatus')
220224

221-
def MoveUntilTouch(manipulator, direction, distance, max_distance=float('+inf'),
225+
def MoveUntilTouch(manipulator, direction, distance, max_distance=None,
222226
max_force=5.0, max_torque=None, ignore_collisions=None, **kw_args):
223227
"""Execute a straight move-until-touch action.
224228
This action stops when a sufficient force is is felt or the manipulator
225229
moves the maximum distance. The motion is considered successful if the
226230
end-effector moves at least distance. In simulation, a move-until-touch
227231
action proceeds until the end-effector collids with the environment.
232+
228233
@param direction unit vector for the direction of motion in the world frame
229234
@param distance minimum distance in meters
230235
@param max_distance maximum distance in meters
231236
@param max_force maximum force in Newtons
232237
@param max_torque maximum torque in Newton-Meters
233-
@param execute optionally execute the trajectory
234-
@param ignore_collisions collisions with these objects are ignored in simulation
238+
@param ignore_collisions collisions with these objects are ignored when planning the path, e.g. the object you think you will touch
235239
@param **kw_args planner parameters
236240
@return felt_force flag indicating whether we felt a force.
237241
"""
238-
# TODO: Is ignore_collisions a list of names or KinBody pointers?
242+
from contextlib import nested
243+
from openravepy import CollisionReport, KinBody, Robot, RaveCreateTrajectory
244+
from ..planning.exceptions import CollisionPlanningError
245+
246+
delta_t = 0.01
247+
248+
robot = manipulator.GetRobot()
249+
env = robot.GetEnv()
250+
dof_indices = manipulator.GetArmIndices()
251+
252+
direction = numpy.array(direction, dtype='float')
253+
254+
# Default argument values.
255+
if max_distance is None:
256+
max_distance = 1.
257+
warnings.warn(
258+
'MoveUntilTouch now requires the "max_distance" argument.'
259+
' This will be an error in the future.',
260+
DeprecationWarning)
261+
239262
if max_torque is None:
240-
max_torque = numpy.array([100.0, 100.0, 100.0 ])
241-
242-
ignore_col_obj_oldstate = []
263+
max_torque = numpy.array([100.0, 100.0, 100.0])
264+
243265
if ignore_collisions is None:
244266
ignore_collisions = []
245267

246-
for ignore_col_with in ignore_collisions:
247-
ignore_col_obj_oldstate.append(ignore_col_with.IsEnabled())
248-
ignore_col_with.Enable(False)
249-
250-
with manipulator.GetRobot().GetEnv():
251-
manipulator.GetRobot().GetController().SimulationStep(0)
252-
268+
with env:
253269
# Compute the expected force direction in the hand frame.
254-
direction = numpy.array(direction)
255270
hand_pose = manipulator.GetEndEffectorTransform()
256271
force_direction = numpy.dot(hand_pose[0:3, 0:3].T, -direction)
257272

258-
with manipulator.GetRobot():
259-
old_active_manipulator = manipulator.GetRobot().GetActiveManipulator()
273+
# Disable the KinBodies listed in ignore_collisions. We backup the
274+
# "enabled" state of all KinBodies so we can restore them later.
275+
body_savers = [
276+
body.CreateKinBodyStateSaver() for body in ignore_collisions]
277+
robot_saver = robot.CreateRobotStateSaver(
278+
Robot.SaveParameters.ActiveDOF
279+
| Robot.SaveParameters.ActiveManipulator
280+
| Robot.SaveParameters.LinkTransformation)
281+
282+
with robot_saver, nested(*body_savers) as f:
260283
manipulator.SetActive()
261-
traj = manipulator.PlanToEndEffectorOffset(direction, distance, max_distance=max_distance,
262-
execute=False, **kw_args)
263-
264-
collided_with_obj = False
265-
try:
266-
if not manipulator.simulated:
267-
manipulator.hand.TareForceTorqueSensor()
268-
#manipulator.GetRobot().ExecuteTrajectory(traj, execute=True, retime=True, blend=False)
269-
manipulator.GetRobot().ExecuteTrajectory(traj, execute=True, retime=True, blend=True, stop_on_ft=True,
270-
force_direction=force_direction, force_magnitude=max_force, torque=max_torque)
271-
for (ignore_col_with, oldstate) in zip(ignore_collisions, ignore_col_obj_oldstate):
272-
ignore_col_with.Enable(oldstate)
273-
else:
274-
traj = manipulator.GetRobot().BlendTrajectory(traj)
275-
traj = manipulator.GetRobot().RetimeTrajectory(traj, stop_on_ft=True, force_direction=force_direction,
276-
force_magnitude=max_force, torque=max_torque)
277-
traj_duration = traj.GetDuration()
278-
delta_t = 0.01
279-
280-
traj_config_spec = traj.GetConfigurationSpecification()
281-
traj_angle_group = traj_config_spec.GetGroupFromName('joint_values')
282-
path_config_spec = openravepy.ConfigurationSpecification()
283-
# path_config_spec.AddDeltaTimeGroup()
284-
path_config_spec.AddGroup(traj_angle_group.name, traj_angle_group.dof, '')
285-
# path_config_spec.AddDerivativeGroups(1, False);
286-
# path_config_spec.AddDerivativeGroups(2, False);
287-
# path_config_spec.AddGroup('owd_blend_radius', 1, 'next')
288-
path_config_spec.ResetGroupOffsets()
289-
290-
new_traj = openravepy.RaveCreateTrajectory(manipulator.GetRobot().GetEnv(), '')
291-
new_traj.Init(path_config_spec)
292-
293-
for (ignore_col_with, oldstate) in zip(ignore_collisions, ignore_col_obj_oldstate):
294-
ignore_col_with.Enable(oldstate)
295-
296-
with manipulator.GetRobot():
297-
manipulator.SetActive()
298-
waypoint_ind = 0
299-
for t in numpy.arange(0, traj_duration, delta_t):
300-
traj_sample = traj.Sample(t)
301-
302-
waypoint = traj_config_spec.ExtractJointValues(traj_sample, manipulator.GetRobot(), manipulator.GetArmIndices())
303-
manipulator.SetDOFValues(waypoint)
304-
#if manipulator.GetRobot().GetEnv().CheckCollision(manipulator.GetRobot()):
305-
for body in manipulator.GetRobot().GetEnv().GetBodies():
306-
if manipulator.GetRobot().GetEnv().CheckCollision(manipulator.GetRobot(), body):
307-
collided_with_obj = True
308-
break
309-
if collided_with_obj:
310-
break
311-
else:
312-
#waypoint = numpy.append(waypoint,t)
313-
new_traj.Insert(int(waypoint_ind), waypoint, path_config_spec)
314-
waypoint_ind += 1
315-
316-
#new_traj = manipulator.GetRobot().BlendTrajectory(new_traj)
317-
#new_traj = manipulator.GetRobot().RetimeTrajectory(new_traj)
318-
manipulator.GetRobot().ExecuteTrajectory(new_traj, execute = True, retime=True, blend=True)
319-
320-
return collided_with_obj
321-
# Trajectory is aborted by OWD because we felt a force.
322-
except exceptions.TrajectoryAborted:
323-
return True
284+
robot_cspec = robot.GetActiveConfigurationSpecification()
285+
286+
for body in ignore_collisions:
287+
body.Enable(False)
288+
289+
path = robot.PlanToEndEffectorOffset(direction=direction,
290+
distance=distance, max_distance=max_distance, **kw_args)
291+
292+
# Execute on the real robot by tagging the trajectory with options that
293+
# tell the controller to stop on force/torque input.
294+
if not manipulator.simulated:
295+
manipulator.SetTrajectoryExecutionOptions(path, stop_on_ft=True,
296+
force_direction=force_direction, force_magnitude=max_force,
297+
torque=max_torque)
298+
299+
manipulator.hand.TareForceTorqueSensor()
300+
301+
try:
302+
robot.ExecutePath(path)
303+
return False
304+
except exceptions.TrajectoryAborted as e:
305+
logger.warn('MoveUntilTouch aborted: %s', str(e))
306+
return True
307+
# Forward-simulate the motion until it hits an object.
308+
else:
309+
traj = robot.PostProcessPath(path)
310+
is_collision = False
311+
312+
traj_cspec = traj.GetConfigurationSpecification()
313+
new_traj = RaveCreateTrajectory(env, '')
314+
new_traj.Init(traj_cspec)
315+
316+
robot_saver = robot.CreateRobotStateSaver(
317+
Robot.SaveParameters.LinkTransformation)
318+
319+
with env, robot_saver:
320+
for t in numpy.arange(0, traj.GetDuration(), delta_t):
321+
waypoint = traj.Sample(t)
322+
323+
dof_values = robot_cspec.ExtractJointValues(
324+
waypoint, robot, dof_indices, 0)
325+
manipulator.SetDOFValues(dof_values)
326+
327+
# Terminate if we detect collision with the environment.
328+
report = CollisionReport()
329+
if env.CheckCollision(robot, report=report):
330+
logger.info('Terminated from collision: %s',
331+
str(CollisionPlanningError.FromReport(report)))
332+
is_collision = True
333+
break
334+
elif robot.CheckSelfCollision(report=report):
335+
logger.info('Terminated from self-collision: %s',
336+
str(CollisionPlanningError.FromReport(report)))
337+
is_collision = True
338+
break
339+
340+
# Build the output trajectory that stops in contact.
341+
if new_traj.GetNumWaypoints() == 0:
342+
traj_cspec.InsertDeltaTime(waypoint, 0.)
343+
else:
344+
traj_cspec.InsertDeltaTime(waypoint, delta_t)
345+
346+
new_traj.Insert(new_traj.GetNumWaypoints(), waypoint)
347+
348+
if new_traj.GetNumWaypoints() > 0:
349+
robot.ExecuteTrajectory(new_traj)
350+
351+
return is_collision

src/prpy/logger.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2929
# POSSIBILITY OF SUCH DAMAGE.
3030

31-
import collections, logging, sys
31+
import collections, logging, sys, warnings
3232

3333
class ColoredFormatter(logging.Formatter):
3434
def __init__(self, default):
@@ -80,6 +80,9 @@ def initialize_logging():
8080
spammy_logger = logging.getLogger(spammy_logger_name)
8181
spammy_logger.setLevel(logging.WARNING)
8282

83+
# Enable deprecation warnings, which are off by default in Python 2.7.
84+
warnings.simplefilter('default')
85+
8386
return base_logger
8487

8588
def remove_ros_logger():

0 commit comments

Comments
 (0)