Skip to content

Commit 56d9c79

Browse files
author
Michael Koval
committed
Simplified logic in PostProcessPath.
1 parent 8478bd2 commit 56d9c79

File tree

1 file changed

+74
-70
lines changed

1 file changed

+74
-70
lines changed

src/prpy/base/robot.py

Lines changed: 74 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -187,45 +187,51 @@ def GetTrajectoryManipulators(self, traj):
187187
def PostProcessPath(self, path, defer=False, executor=None,
188188
constrained=None, smooth=None, default_timelimit=0.5,
189189
shortcut_options=None, smoothing_options=None,
190-
retiming_options=None, **kwargs):
190+
retiming_options=None, affine_retiming_options=None,
191+
**kwargs):
191192
""" Post-process a geometric path to prepare it for execution.
192193
193194
This method post-processes a geometric path by (optionally) optimizing
194-
it and timing it. Three different post-processing pipelines are used:
195-
196-
1. For constrained trajectories, we do not modify the geometric path
197-
and retime the path to be time-optimal. This trajectory must stop
198-
at every waypoint. The only exception is for...
199-
2. For smooth trajectories, we attempt to fit a time-optimal smooth
195+
it and timing it. Four different post-processing pipelines are used:
196+
197+
1. For base trajectories (i..e affine DOFs), we time the trajectory
198+
using self.affine_retimer. This function does not currently support
199+
trajectories that contain both regular and affine DOFs.
200+
2. For constrained trajectories, we do not modify the geometric path
201+
and retime the path to be time-optimal via self.retimer. This
202+
trajectory must stop at every waypoint. The only exception is for...
203+
3. For smooth trajectories, we attempt to fit a time-optimal smooth
200204
curve through the waypoints (not implemented). If this curve is
201205
not collision free, then we fall back on...
202-
3. By default, we run a smoother that jointly times and smooths the
203-
path. This algorithm can change the geometric path to optimize
204-
runtime.
206+
4. By default, we run a smoother that jointly times and smooths the
207+
path via self.smoother. This algorithm can change the geometric path to
208+
optimize runtime.
205209
206-
The behavior in (1) and (2) can be forced by passing constrained=True
210+
The behavior in (2) and (3) can be forced by passing constrained=True
207211
or smooth=True. By default, the case is inferred by the tag(s) attached
208212
to the trajectory: (1) is triggered by the CONSTRAINED tag and (2) is
209213
tiggered by the SMOOTH tag.
210214
211215
Options an be passed to each post-processing routine using the
212-
shortcut-options, smoothing_options, and retiming_options **kwargs
213-
dictionaries. If no "timelimit" is specified in any of these
214-
dictionaries, it defaults to default_timelimit seconds.
216+
affine_retiming_options, shortcut_options, smoothing_options, and
217+
retiming_options **kwargs dictionaries. If no "timelimit" is specified
218+
in any of these dictionaries, it defaults to default_timelimit seconds.
215219
216220
@param path un-timed OpenRAVE trajectory
217221
@param defer return immediately with a future trajectory
218222
@param executor executor to use when defer = True
219223
@param constrained the path is constrained; do not change it
220224
@param smooth the path is smooth; attempt to execute it directly
221225
@param default_timelimit timelimit for all operations, if not set
222-
@param shortcut_options kwargs to ShortcutPath for shortcutting
223-
@param smoothing_options kwargs to RetimeTrajectory for smoothing
224-
@param retiming_options kwargs to RetimeTrajectory for timing
226+
@param shortcut_options kwargs to self.simplifier
227+
@param smoothing_options kwargs to self.smoother
228+
@param retiming_options kwargs to self.retimer
229+
@param affine_retiming_options kwargs to self.affine_retimer
225230
@return trajectory ready for execution
226231
"""
227232
from ..planning.base import Tags
228233
from ..util import GetTrajectoryTags, CopyTrajectory
234+
from openravepy import DOFAffine
229235

230236
# Default parameters.
231237
if shortcut_options is None:
@@ -234,10 +240,13 @@ def PostProcessPath(self, path, defer=False, executor=None,
234240
smoothing_options = dict()
235241
if retiming_options is None:
236242
retiming_options = dict()
243+
if affine_retiming_options is None:
244+
affine_retimer_options = dict()
237245

238246
shortcut_options.setdefault('timelimit', default_timelimit)
239247
smoothing_options.setdefault('timelimit', default_timelimit)
240248
retiming_options.setdefault('timelimit', default_timelimit)
249+
affine_retiming_options.setdefault('timelimit', default_timelimit)
241250

242251
# Read default parameters from the trajectory's tags.
243252
tags = GetTrajectoryTags(path)
@@ -267,65 +276,60 @@ def do_postprocess():
267276
'Robot "{:s}" is not in the trajectory.'.format(
268277
self.GetName()))
269278

270-
# Check for affine dofs in the path
271-
has_affine_dofs = prpy.util.HasAffineDOFs(cspec)
279+
# Extract active DOFs from teh trajectory and set them as active.
280+
dof_indices, _ = cspec.ExtractUsedIndices(self)
272281

273-
if has_affine_dofs:
274-
cloned_robot.SetActiveDOFs(
275-
[],
276-
affine=(openravepy.DOFAffine.X |
277-
openravepy.DOFAffine.Y |
278-
openravepy.DOFAffine.RotationAxis)
279-
)
280-
logger.debug(
281-
' Setting robot "%s" affine DOFs as active for post-processing.',
282-
cloned_robot.GetName())
282+
if prpy.util.HasAffineDOFs(cspec):
283+
affine_dofs = (DOFAffine.X | DOFAffine.Y | DOFAffine.RotationAxis)
283284
else:
284-
dof_indices, _ = cspec.ExtractUsedIndices(self)
285-
cloned_robot.SetActiveDOFs(dof_indices)
286-
logger.debug(
287-
'Setting robot "%s" DOFs %s as active for post-processing.',
288-
cloned_robot.GetName(), list(dof_indices))
289-
290-
# Directly compute a timing of smooth trajectories.
291-
if smooth:
292-
logger.warning(
293-
'Post-processing smooth paths is not supported.'
294-
' Using the default post-processing logic; this may'
295-
' significantly change the geometric path.'
296-
)
285+
affine_dofs = 0
297286

298-
# The trajectory is constrained. Retime it without changing the
299-
# geometric path.
300-
if constrained:
301-
logger.debug('Retiming a constrained path. The output'
302-
' trajectory will stop at every waypoint.')
303-
if has_affine_dofs:
304-
retimer = self.affine_retimer
305-
else:
306-
retimer = self.retimer
307-
traj = retimer.RetimeTrajectory(
308-
cloned_robot, path, defer=False, **retiming_options)
287+
cloned_robot.SetActiveDOFs(dof_indices, affine_dofs)
288+
logger.debug(
289+
'Setting robot "%s" DOFs %s (affine? %d) as active for'
290+
' post-processing.',
291+
cloned_robot.GetName(), list(dof_indices), has_affine_dofs
292+
)
293+
294+
if dof_indices and affine_dofs:
295+
raise ValueError(
296+
'Trajectory contains both affine and regular DOFs.')
297+
# Special case for timing affine-only trajectories.
298+
elif affine_dofs:
299+
traj = self.affine_retimer.RetimeTrajectory(
300+
cloned_robot, path, defer=False, **affine_retimer_options)
309301
else:
310-
# The trajectory is not constrained, so we can shortcut it
311-
# before execution.
312-
if self.simplifier is not None:
313-
logger.debug('Shortcutting an unconstrained path.')
314-
shortcut_path = self.simplifier.ShortcutPath(
315-
cloned_robot, path, defer=False, **shortcut_options)
316-
else:
317-
logger.debug('Skipping shortcutting; no simplifier'
318-
' available.')
319-
shortcut_path = path
302+
# Directly compute a timing of smooth trajectories.
303+
if smooth:
304+
logger.warning(
305+
'Post-processing smooth paths is not supported.'
306+
' Using the default post-processing logic; this may'
307+
' significantly change the geometric path.'
308+
)
320309

321-
logger.debug('Smoothing an unconstrained path.')
322-
if has_affine_dofs:
323-
smoother = self.affine_retimer
310+
# The trajectory is constrained. Retime it without changing the
311+
# geometric path.
312+
if constrained:
313+
logger.debug('Retiming a constrained path. The output'
314+
' trajectory will stop at every waypoint.')
315+
traj = self.retimer.RetimeTrajectory(
316+
cloned_robot, path, defer=False, **retiming_options)
317+
# The trajectory is not constrained, so we can shortcut it
318+
# before execution.
324319
else:
325-
smoother = self.smoother
326-
traj = smoother.RetimeTrajectory(
327-
cloned_robot, shortcut_path, defer=False,
328-
**smoothing_options)
320+
if self.simplifier is not None:
321+
logger.debug('Shortcutting an unconstrained path.')
322+
shortcut_path = self.simplifier.ShortcutPath(
323+
cloned_robot, path, defer=False, **shortcut_options)
324+
else:
325+
logger.debug('Skipping shortcutting; no simplifier'
326+
' available.')
327+
shortcut_path = path
328+
329+
logger.debug('Smoothing an unconstrained path.')
330+
traj = self.smoother.RetimeTrajectory(
331+
cloned_robot, shortcut_path, defer=False,
332+
**smoothing_options)
329333

330334
return CopyTrajectory(traj, env=self.GetEnv())
331335

0 commit comments

Comments
 (0)