Skip to content

Commit 3274ff2

Browse files
committed
Merge branch 'master' into bugfix/issue153
2 parents 0341a99 + 62fca02 commit 3274ff2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+2383
-1035
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/barretthand.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,6 @@ def TareForceTorqueSensor(hand):
239239
"""
240240
if not hand.ft_simulated:
241241
hand.ft_sensor.SendCommand('Tare')
242-
# TODO: Do we still need to wait this long?
243-
time.sleep(2)
244242

245243
def _GetJointFromName(self, name):
246244
robot = self.manipulator.GetRobot()

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: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ def __dir__(self):
8888
method_names.update(self.planner.get_planning_method_names())
8989
if hasattr(self, 'actions') and self.actions is not None:
9090
method_names.update(self.actions.get_actions())
91+
if hasattr(self, 'detector') and self.detector is not None:
92+
method_names.update(self.detector.get_perception_method_names())
9193

9294
return list(method_names)
9395

@@ -113,6 +115,14 @@ def wrapper_method(*args, **kw_args):
113115
def wrapper_method(*args, **kw_args):
114116
return delegate_method(self, *args, **kw_args)
115117
return wrapper_method
118+
elif (hasattr(self, 'detector') and self.detector is not None
119+
and self.detector.has_perception_method(name)):
120+
121+
delegate_method = getattr(self.detector, name)
122+
@functools.wraps(delegate_method)
123+
def wrapper_method(*args, **kw_args):
124+
return delegate_method(self, *args, **kw_args)
125+
return wrapper_method
116126

117127
raise AttributeError('{0:s} is missing method "{1:s}".'.format(repr(self), name))
118128

@@ -205,8 +215,8 @@ def PostProcessPath(self, path, defer=False, executor=None,
205215
curve through the waypoints (not implemented). If this curve is
206216
not collision free, then we fall back on...
207217
4. By default, we run a smoother that jointly times and smooths the
208-
path via self.smoother. This algorithm can change the geometric path to
209-
optimize runtime.
218+
path via self.smoother. This algorithm can change the geometric path
219+
to optimize runtime.
210220
211221
The behavior in (2) and (3) can be forced by passing constrained=True
212222
or smooth=True. By default, the case is inferred by the tag(s) attached
@@ -411,8 +421,8 @@ def do_execute():
411421
else:
412422
raise ValueError('Received unexpected value "{:s}" for defer.'.format(str(defer)))
413423

414-
415-
def ExecuteTrajectory(self, traj, defer=False, timeout=None, period=0.01, **kwargs):
424+
def ExecuteTrajectory(self, traj, defer=False, timeout=None, period=0.01,
425+
**kwargs):
416426
""" Executes a time trajectory on the robot.
417427
418428
This function directly executes a timed OpenRAVE trajectory on the
@@ -457,7 +467,7 @@ def ExecuteTrajectory(self, traj, defer=False, timeout=None, period=0.01, **kwar
457467
# Check that the current configuration of the robot matches the
458468
# initial configuration specified by the trajectory.
459469
if not util.IsAtTrajectoryStart(self, traj):
460-
raise exceptions.TrajectoryAborted(
470+
raise exceptions.TrajectoryNotExecutable(
461471
'Trajectory started from different configuration than robot.')
462472

463473
# If there was only one waypoint, at this point we are done!

src/prpy/base/wam.py

Lines changed: 100 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ def ServoTo(manipulator, target, duration, timeStep=0.05, collisionChecking=True
157157

158158
if not inCollision:
159159
for i in range(1,steps):
160+
import time
160161
manipulator.Servo(velocities)
161162
time.sleep(timeStep)
162163
manipulator.Servo([0] * len(manipulator.GetArmIndices()))
@@ -223,7 +224,8 @@ def ClearTrajectoryStatus(manipulator):
223224
manipulator.controller.SendCommand('ClearStatus')
224225

225226
def MoveUntilTouch(manipulator, direction, distance, max_distance=None,
226-
max_force=5.0, max_torque=None, ignore_collisions=None, **kw_args):
227+
max_force=5.0, max_torque=None, ignore_collisions=None,
228+
velocity_limit_scale=0.25, **kw_args):
227229
"""Execute a straight move-until-touch action.
228230
This action stops when a sufficient force is is felt or the manipulator
229231
moves the maximum distance. The motion is considered successful if the
@@ -235,100 +237,123 @@ def MoveUntilTouch(manipulator, direction, distance, max_distance=None,
235237
@param max_distance maximum distance in meters
236238
@param max_force maximum force in Newtons
237239
@param max_torque maximum torque in Newton-Meters
238-
@param ignore_collisions collisions with these objects are ignored when planning the path, e.g. the object you think you will touch
240+
@param ignore_collisions collisions with these objects are ignored when
241+
planning the path, e.g. the object you think you will touch
242+
@param velocity_limit_scale A multiplier to use to scale velocity limits
243+
when executing MoveUntilTouch ( < 1 in most cases).
239244
@param **kw_args planner parameters
240245
@return felt_force flag indicating whether we felt a force.
241246
"""
247+
from contextlib import nested
248+
from openravepy import CollisionReport, KinBody, Robot, RaveCreateTrajectory
249+
from ..planning.exceptions import CollisionPlanningError
242250

251+
delta_t = 0.01
252+
253+
robot = manipulator.GetRobot()
254+
env = robot.GetEnv()
255+
dof_indices = manipulator.GetArmIndices()
256+
257+
direction = numpy.array(direction, dtype='float')
258+
259+
# Default argument values.
243260
if max_distance is None:
244261
max_distance = 1.
245262
warnings.warn(
246263
'MoveUntilTouch now requires the "max_distance" argument.'
247264
' This will be an error in the future.',
248265
DeprecationWarning)
249266

250-
# TODO: Is ignore_collisions a list of names or KinBody pointers?
251267
if max_torque is None:
252-
max_torque = numpy.array([100.0, 100.0, 100.0 ])
253-
254-
ignore_col_obj_oldstate = []
268+
max_torque = numpy.array([100.0, 100.0, 100.0])
269+
255270
if ignore_collisions is None:
256271
ignore_collisions = []
257272

258-
for ignore_col_with in ignore_collisions:
259-
ignore_col_obj_oldstate.append(ignore_col_with.IsEnabled())
260-
ignore_col_with.Enable(False)
261-
262-
with manipulator.GetRobot().GetEnv():
263-
manipulator.GetRobot().GetController().SimulationStep(0)
264-
273+
with env:
265274
# Compute the expected force direction in the hand frame.
266-
direction = numpy.array(direction)
267275
hand_pose = manipulator.GetEndEffectorTransform()
268276
force_direction = numpy.dot(hand_pose[0:3, 0:3].T, -direction)
269277

270-
with manipulator.GetRobot():
271-
old_active_manipulator = manipulator.GetRobot().GetActiveManipulator()
272-
manipulator.SetActive()
273-
traj = manipulator.PlanToEndEffectorOffset(direction, distance, max_distance=max_distance,
274-
execute=False, **kw_args)
278+
# Disable the KinBodies listed in ignore_collisions. We backup the
279+
# "enabled" state of all KinBodies so we can restore them later.
280+
body_savers = [
281+
body.CreateKinBodyStateSaver() for body in ignore_collisions]
282+
robot_saver = robot.CreateRobotStateSaver(
283+
Robot.SaveParameters.ActiveDOF
284+
| Robot.SaveParameters.ActiveManipulator
285+
| Robot.SaveParameters.LinkTransformation)
275286

276-
collided_with_obj = False
277-
try:
278-
if not manipulator.simulated:
279-
manipulator.SetTrajectoryExecutionOptions(traj, stop_on_ft=True,
280-
force_direction=force_direction, force_magnitude=max_force,
281-
torque=max_torque)
287+
with robot_saver, nested(*body_savers) as f:
288+
manipulator.SetActive()
289+
robot_cspec = robot.GetActiveConfigurationSpecification()
282290

283-
manipulator.hand.TareForceTorqueSensor()
284-
manipulator.GetRobot().ExecutePath(traj)
291+
for body in ignore_collisions:
292+
body.Enable(False)
285293

286-
for (ignore_col_with, oldstate) in zip(ignore_collisions, ignore_col_obj_oldstate):
287-
ignore_col_with.Enable(oldstate)
288-
else:
294+
path = robot.PlanToEndEffectorOffset(direction=direction,
295+
distance=distance, max_distance=max_distance, **kw_args)
289296

290-
traj = manipulator.GetRobot().PostProcessPath(traj)
291-
292-
traj_duration = traj.GetDuration()
293-
delta_t = 0.01
294-
295-
traj_config_spec = traj.GetConfigurationSpecification()
296-
new_traj = openravepy.RaveCreateTrajectory(manipulator.GetRobot().GetEnv(), '')
297-
new_traj.Init(traj_config_spec)
298-
299-
for (ignore_col_with, oldstate) in zip(ignore_collisions, ignore_col_obj_oldstate):
300-
ignore_col_with.Enable(oldstate)
301-
302-
with manipulator.GetRobot():
303-
manipulator.SetActive()
304-
waypoint_ind = 0
305-
for t in numpy.arange(0, traj_duration, delta_t):
306-
traj_sample = traj.Sample(t)
307-
308-
waypoint = traj_config_spec.ExtractJointValues(traj_sample, manipulator.GetRobot(), manipulator.GetArmIndices())
309-
manipulator.SetDOFValues(waypoint)
310-
311-
# Check collision with each body on the robot
312-
for body in manipulator.GetRobot().GetEnv().GetBodies():
313-
if manipulator.GetRobot().GetEnv().CheckCollision(manipulator.GetRobot(), body):
314-
collided_with_obj = True
315-
break
316-
if collided_with_obj:
317-
break
318-
else:
319-
#set timing on new sampled waypoint
320-
if waypoint_ind == 0:
321-
traj_config_spec.InsertDeltaTime(traj_sample, 0.)
322-
else:
323-
traj_config_spec.InsertDeltaTime(traj_sample, delta_t)
324-
325-
new_traj.Insert(int(waypoint_ind), traj_sample)
326-
waypoint_ind += 1
327-
328-
329-
manipulator.GetRobot().ExecuteTrajectory(new_traj)
330-
331-
return collided_with_obj
332-
# Trajectory is aborted by OWD because we felt a force.
333-
except exceptions.TrajectoryAborted:
334-
return True
297+
# Execute on the real robot by tagging the trajectory with options that
298+
# tell the controller to stop on force/torque input.
299+
if not manipulator.simulated:
300+
manipulator.SetTrajectoryExecutionOptions(path, stop_on_ft=True,
301+
force_direction=force_direction, force_magnitude=max_force,
302+
torque=max_torque)
303+
304+
manipulator.hand.TareForceTorqueSensor()
305+
306+
try:
307+
with robot.CreateRobotStateSaver(Robot.SaveParameters.JointMaxVelocityAndAcceleration):
308+
vl = robot.GetDOFVelocityLimits()
309+
manipulator.SetVelocityLimits(velocity_limit_scale*vl, 0.5)
310+
robot.ExecutePath(path)
311+
return False
312+
except exceptions.TrajectoryAborted as e:
313+
logger.warn('MoveUntilTouch aborted: %s', str(e))
314+
return True
315+
# Forward-simulate the motion until it hits an object.
316+
else:
317+
traj = robot.PostProcessPath(path)
318+
is_collision = False
319+
320+
traj_cspec = traj.GetConfigurationSpecification()
321+
new_traj = RaveCreateTrajectory(env, '')
322+
new_traj.Init(traj_cspec)
323+
324+
robot_saver = robot.CreateRobotStateSaver(
325+
Robot.SaveParameters.LinkTransformation)
326+
327+
with env, robot_saver:
328+
for t in numpy.arange(0, traj.GetDuration(), delta_t):
329+
waypoint = traj.Sample(t)
330+
331+
dof_values = robot_cspec.ExtractJointValues(
332+
waypoint, robot, dof_indices, 0)
333+
manipulator.SetDOFValues(dof_values)
334+
335+
# Terminate if we detect collision with the environment.
336+
report = CollisionReport()
337+
if env.CheckCollision(robot, report=report):
338+
logger.info('Terminated from collision: %s',
339+
str(CollisionPlanningError.FromReport(report)))
340+
is_collision = True
341+
break
342+
elif robot.CheckSelfCollision(report=report):
343+
logger.info('Terminated from self-collision: %s',
344+
str(CollisionPlanningError.FromReport(report)))
345+
is_collision = True
346+
break
347+
348+
# Build the output trajectory that stops in contact.
349+
if new_traj.GetNumWaypoints() == 0:
350+
traj_cspec.InsertDeltaTime(waypoint, 0.)
351+
else:
352+
traj_cspec.InsertDeltaTime(waypoint, delta_t)
353+
354+
new_traj.Insert(new_traj.GetNumWaypoints(), waypoint)
355+
356+
if new_traj.GetNumWaypoints() > 0:
357+
robot.ExecuteTrajectory(new_traj)
358+
359+
return is_collision

src/prpy/exceptions.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,50 @@ class PrPyException(Exception):
33
Generic PrPy exception.
44
"""
55

6-
class TrajectoryAborted(PrPyException):
6+
7+
class TrajectoryException(PrPyException):
8+
"""
9+
Trajectory failed to execute.
10+
"""
11+
12+
13+
class TrajectoryNotExecutable(TrajectoryException):
14+
"""
15+
Trajectory could not begin execution.
16+
17+
This exception typically indicates that some precondition of trajectory
18+
execution was violated, such as the robot starting at a different
19+
configuration, the trajectory not being in the correct format.
20+
21+
This exception indicates that the trajectory was not even attempted due to
22+
one of these conditions.
23+
"""
24+
25+
26+
class TrajectoryAborted(TrajectoryException):
727
"""
828
Trajectory was aborted.
929
"""
1030

11-
class TrajectoryStalled(PrPyException):
31+
32+
class TrajectoryStalled(TrajectoryException):
1233
"""
1334
Trajectory stalled.
1435
"""
1536

37+
1638
class SynchronizationException(PrPyException):
1739
"""
1840
Controller synchronization failed.
1941
"""
2042

43+
2144
class SerializationException(PrPyException):
2245
"""
2346
Serialization failed.
2447
"""
2548

49+
2650
class UnsupportedTypeSerializationException(SerializationException):
2751
"""
2852
Serialization failed due to an unknown type.
@@ -35,6 +59,7 @@ def __init__(self, value):
3559
'Serializing type "{:s}.{:s}" is not supported.'.format(
3660
self.type.__module__, self.type.__name__))
3761

62+
3863
class UnsupportedTypeDeserializationException(SerializationException):
3964
"""
4065
Deserialization failed due to an unknown type.

0 commit comments

Comments
 (0)