@@ -187,45 +187,51 @@ def GetTrajectoryManipulators(self, traj):
187
187
def PostProcessPath (self , path , defer = False , executor = None ,
188
188
constrained = None , smooth = None , default_timelimit = 0.5 ,
189
189
shortcut_options = None , smoothing_options = None ,
190
- retiming_options = None , ** kwargs ):
190
+ retiming_options = None , affine_retiming_options = None ,
191
+ ** kwargs ):
191
192
""" Post-process a geometric path to prepare it for execution.
192
193
193
194
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
200
204
curve through the waypoints (not implemented). If this curve is
201
205
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.
205
209
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
207
211
or smooth=True. By default, the case is inferred by the tag(s) attached
208
212
to the trajectory: (1) is triggered by the CONSTRAINED tag and (2) is
209
213
tiggered by the SMOOTH tag.
210
214
211
215
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.
215
219
216
220
@param path un-timed OpenRAVE trajectory
217
221
@param defer return immediately with a future trajectory
218
222
@param executor executor to use when defer = True
219
223
@param constrained the path is constrained; do not change it
220
224
@param smooth the path is smooth; attempt to execute it directly
221
225
@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
225
230
@return trajectory ready for execution
226
231
"""
227
232
from ..planning .base import Tags
228
233
from ..util import GetTrajectoryTags , CopyTrajectory
234
+ from openravepy import DOFAffine
229
235
230
236
# Default parameters.
231
237
if shortcut_options is None :
@@ -234,10 +240,13 @@ def PostProcessPath(self, path, defer=False, executor=None,
234
240
smoothing_options = dict ()
235
241
if retiming_options is None :
236
242
retiming_options = dict ()
243
+ if affine_retiming_options is None :
244
+ affine_retimer_options = dict ()
237
245
238
246
shortcut_options .setdefault ('timelimit' , default_timelimit )
239
247
smoothing_options .setdefault ('timelimit' , default_timelimit )
240
248
retiming_options .setdefault ('timelimit' , default_timelimit )
249
+ affine_retiming_options .setdefault ('timelimit' , default_timelimit )
241
250
242
251
# Read default parameters from the trajectory's tags.
243
252
tags = GetTrajectoryTags (path )
@@ -267,65 +276,60 @@ def do_postprocess():
267
276
'Robot "{:s}" is not in the trajectory.' .format (
268
277
self .GetName ()))
269
278
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 )
272
281
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 )
283
284
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
297
286
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 )
309
301
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
+ )
320
309
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.
324
319
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 )
329
333
330
334
return CopyTrajectory (traj , env = self .GetEnv ())
331
335
0 commit comments