Skip to content

Commit f1c2e3e

Browse files
committed
Added proper checking for trajectory timing and length.
This adds several checks to the ExecuteTrajectory function: 1) there must be at least one waypoint. 2) the first waypoint must match the robot's current config (within joint DOF resolutions) 3) if there is only one waypoint, succeed after the first two checks. 4) if there are multiple waypoints, the duration must be nonzero.
1 parent b063607 commit f1c2e3e

File tree

2 files changed

+64
-9
lines changed

2 files changed

+64
-9
lines changed

src/prpy/base/robot.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@
2929
# POSSIBILITY OF SUCH DAMAGE.
3030

3131
import functools, logging, openravepy, numpy
32-
import prpy.util
33-
from .. import bind, named_config, planning, util
32+
from .. import bind, named_config, exceptions, util
3433
from ..clone import Clone, Cloned
3534
from ..tsr.tsrlibrary import TSRLibrary
3635
from ..planning.base import Sequence, Tags
@@ -281,7 +280,7 @@ def do_postprocess():
281280
# Extract active DOFs from teh trajectory and set them as active.
282281
dof_indices, _ = cspec.ExtractUsedIndices(self)
283282

284-
if prpy.util.HasAffineDOFs(cspec):
283+
if util.HasAffineDOFs(cspec):
285284
affine_dofs = (DOFAffine.X | DOFAffine.Y | DOFAffine.RotationAxis)
286285

287286
# Bug in OpenRAVE ExtractUsedIndices function makes
@@ -438,18 +437,33 @@ def ExecuteTrajectory(self, traj, defer=False, timeout=None, period=0.01, **kwar
438437
@param period poll rate, in seconds, for checking trajectory status
439438
@return trajectory executed on the robot
440439
"""
440+
# Don't execute trajectories that don't have at least one waypoint.
441+
if traj.GetNumWaypoints() <= 0:
442+
raise ValueError('Trajectory must contain at least one waypoint.')
443+
444+
# Check that the current configuration of the robot matches the
445+
# initial configuration specified by the trajectory.
446+
if not util.IsAtTrajectoryStart(self, traj):
447+
raise exceptions.TrajectoryAborted(
448+
'Trajectory started from different configuration than robot.')
449+
450+
# If there was only one waypoint, at this point we are done!
451+
if traj.GetNumWaypoints() == 1:
452+
return traj
441453

442-
# TODO: Verify that the trajectory is timed.
443-
# TODO: Check if this trajectory contains the base.
454+
# Verify that the trajectory is timed.
455+
if traj.GetDuration() <= 0.0:
456+
raise ValueError('Attempted to execute untimed trajectory.')
444457

458+
# TODO: Check if this trajectory contains the base.
445459
needs_base = util.HasAffineDOFs(traj.GetConfigurationSpecification())
446460

447461
self.GetController().SetPath(traj)
448462

449463
active_manipulators = self.GetTrajectoryManipulators(traj)
450464
active_controllers = [
451-
active_manipulator.controller \
452-
for active_manipulator in active_manipulators \
465+
active_manipulator.controller
466+
for active_manipulator in active_manipulators
453467
if hasattr(active_manipulator, 'controller')
454468
]
455469

@@ -485,8 +499,8 @@ def do_poll():
485499
util.WaitForControllers(active_controllers, timeout=timeout)
486500
return traj
487501
else:
488-
raise ValueError('Received unexpected value "{:s}" for defer.'.format(str(defer)))
489-
502+
raise ValueError('Received unexpected value "{:s}" for defer.'
503+
.format(str(defer)))
490504

491505
def ViolatesVelocityLimits(self, traj):
492506
"""

src/prpy/util.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,3 +693,44 @@ def FindCatkinResource(package, relative_path):
693693
else:
694694
raise IOError('Loading resource "{:s}" failed.'.format(
695695
relative_path))
696+
697+
698+
def IsAtTrajectoryStart(robot, trajectory):
699+
"""
700+
Check if robot's active DOFs match the start configuration of a trajectory.
701+
702+
Examines the current active DOF values of the specified robot and compares
703+
these values to the first waypoint of the specified trajectory. If every
704+
DOF value differs by less than the DOF resolution of the specified
705+
joint/axis, then the function returns True. Otherwise, it returns False.
706+
707+
@param robot: the robot whose active DOFs will be checked
708+
@param trajectory: the trajectory whose start configuration will be checked
709+
@returns: True if the robot's active DOFs match the given trajectory
710+
False if one or more active DOFs differ by DOF resolution
711+
"""
712+
# Get current active configuration of robot.
713+
dof_indices = robot.GetActiveDOFIndices()
714+
dof_values = robot.GetActiveDOFValues()
715+
dof_resolutions = robot.GetActiveDOFResolutions()
716+
717+
# Get starting configuration from trajectory.
718+
cspec = trajectory.GetConfigurationSpecification()
719+
start_values = cspec.ExtractJointValues(
720+
trajectory.GetWaypoint(0), robot, dof_indices)
721+
722+
# Check deviation in each DOF, using OpenRAVE's SubtractValue function.
723+
for i, dof_index in enumerate(dof_indices):
724+
725+
# Look up the Joint and Axis of the DOF from the robot.
726+
joint = robot.GetJointFromDOFIndex(dof_index)
727+
axis = dof_index - joint.GetDOFIndex()
728+
729+
# If any joint deviated too much, return False.
730+
delta_value = abs(joint.SubtractValue(
731+
start_values[i], dof_values[i], axis))
732+
if delta_value > dof_resolutions[i]:
733+
return False
734+
735+
# If all joints matched, return True.
736+
return True

0 commit comments

Comments
 (0)