35
35
from ..tsr .tsrlibrary import TSRLibrary
36
36
from ..planning .base import Sequence
37
37
from ..planning .ompl import OMPLSimplifier
38
- from ..planning .retimer import HauserParabolicSmoother , ParabolicRetimer
38
+ from ..planning .retimer import HauserParabolicSmoother , OpenRAVEAffineRetimer , ParabolicRetimer
39
39
from ..planning .mac_smoother import MacSmoother
40
40
41
41
logger = logging .getLogger ('robot' )
@@ -73,6 +73,7 @@ def __init__(self, robot_name=None):
73
73
HauserParabolicSmoother (),
74
74
self .retimer
75
75
)
76
+ self .affine_retimer = OpenRAVEAffineRetimer ()
76
77
77
78
def __dir__ (self ):
78
79
# We have to manually perform a lookup in InstanceDeduplicator because
@@ -186,45 +187,51 @@ def GetTrajectoryManipulators(self, traj):
186
187
def PostProcessPath (self , path , defer = False , executor = None ,
187
188
constrained = None , smooth = None , default_timelimit = 0.5 ,
188
189
shortcut_options = None , smoothing_options = None ,
189
- retiming_options = None , ** kwargs ):
190
+ retiming_options = None , affine_retiming_options = None ,
191
+ ** kwargs ):
190
192
""" Post-process a geometric path to prepare it for execution.
191
193
192
194
This method post-processes a geometric path by (optionally) optimizing
193
- it and timing it. Three different post-processing pipelines are used:
194
-
195
- 1. For constrained trajectories, we do not modify the geometric path
196
- and retime the path to be time-optimal. This trajectory must stop
197
- at every waypoint. The only exception is for...
198
- 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
199
204
curve through the waypoints (not implemented). If this curve is
200
205
not collision free, then we fall back on...
201
- 3 . By default, we run a smoother that jointly times and smooths the
202
- path. This algorithm can change the geometric path to optimize
203
- 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.
204
209
205
- 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
206
211
or smooth=True. By default, the case is inferred by the tag(s) attached
207
212
to the trajectory: (1) is triggered by the CONSTRAINED tag and (2) is
208
213
tiggered by the SMOOTH tag.
209
214
210
215
Options an be passed to each post-processing routine using the
211
- shortcut-options, smoothing_options, and retiming_options **kwargs
212
- dictionaries. If no "timelimit" is specified in any of these
213
- 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.
214
219
215
220
@param path un-timed OpenRAVE trajectory
216
221
@param defer return immediately with a future trajectory
217
222
@param executor executor to use when defer = True
218
223
@param constrained the path is constrained; do not change it
219
224
@param smooth the path is smooth; attempt to execute it directly
220
225
@param default_timelimit timelimit for all operations, if not set
221
- @param shortcut_options kwargs to ShortcutPath for shortcutting
222
- @param smoothing_options kwargs to RetimeTrajectory for smoothing
223
- @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
224
230
@return trajectory ready for execution
225
231
"""
226
232
from ..planning .base import Tags
227
233
from ..util import GetTrajectoryTags , CopyTrajectory
234
+ from openravepy import DOFAffine
228
235
229
236
# Default parameters.
230
237
if shortcut_options is None :
@@ -233,10 +240,13 @@ def PostProcessPath(self, path, defer=False, executor=None,
233
240
smoothing_options = dict ()
234
241
if retiming_options is None :
235
242
retiming_options = dict ()
243
+ if affine_retiming_options is None :
244
+ affine_retimer_options = dict ()
236
245
237
246
shortcut_options .setdefault ('timelimit' , default_timelimit )
238
247
smoothing_options .setdefault ('timelimit' , default_timelimit )
239
248
retiming_options .setdefault ('timelimit' , default_timelimit )
249
+ affine_retimer_options .setdefault ('timelimit' , default_timelimit )
240
250
241
251
# Read default parameters from the trajectory's tags.
242
252
tags = GetTrajectoryTags (path )
@@ -259,51 +269,75 @@ def do_postprocess():
259
269
# in the trajectory as active.
260
270
env = path .GetEnv ()
261
271
cspec = path .GetConfigurationSpecification ()
272
+
262
273
used_bodies = cspec .ExtractUsedBodies (env )
263
274
if self not in used_bodies :
264
275
raise ValueError (
265
276
'Robot "{:s}" is not in the trajectory.' .format (
266
277
self .GetName ()))
267
278
279
+ # Extract active DOFs from teh trajectory and set them as active.
268
280
dof_indices , _ = cspec .ExtractUsedIndices (self )
269
- cloned_robot .SetActiveDOFs (dof_indices )
270
- logger .debug (
271
- 'Setting robot "%s" DOFs %s as active for post-processing.' ,
272
- cloned_robot .GetName (), list (dof_indices ))
273
-
274
- # TODO: Handle a affine DOF trajectories for the base.
275
281
276
- # Directly compute a timing of smooth trajectories.
277
- if smooth :
282
+ if prpy .util .HasAffineDOFs (cspec ):
283
+ affine_dofs = (DOFAffine .X | DOFAffine .Y | DOFAffine .RotationAxis )
284
+
285
+ # Bug in OpenRAVE ExtractUsedIndices function makes
286
+ # dof_indices = affine_dofs. Temporary workaround for that bug.
287
+ dof_indices = []
278
288
logger .warning (
279
- 'Post-processing smooth paths is not supported.'
280
- ' Using the default post-processing logic; this may'
281
- ' significantly change the geometric path.'
289
+ 'Trajectory contains affine DOFs. Any regular DOFs'
290
+ ' will be ignored.'
282
291
)
292
+ else :
293
+ affine_dofs = 0
294
+
295
+ cloned_robot .SetActiveDOFs (dof_indices , affine_dofs )
296
+ logger .debug (
297
+ 'Setting robot "%s" DOFs %s (affine? %d) as active for'
298
+ ' post-processing.' ,
299
+ cloned_robot .GetName (), list (dof_indices ), affine_dofs
300
+ )
283
301
284
- # The trajectory is constrained. Retime it without changing the
285
- # geometric path.
286
- if constrained :
287
- logger . debug ( 'Retiming a constrained path. The output'
288
- ' trajectory will stop at every waypoint.' )
289
- traj = self .retimer .RetimeTrajectory (
290
- cloned_robot , path , defer = False , ** retiming_options )
302
+ if len ( dof_indices ) and affine_dofs :
303
+ raise ValueError (
304
+ 'Trajectory contains both affine and regular DOFs.' )
305
+ # Special case for timing affine-only trajectories.
306
+ elif affine_dofs :
307
+ traj = self .affine_retimer .RetimeTrajectory (
308
+ cloned_robot , path , defer = False , ** affine_retimer_options )
291
309
else :
292
- # The trajectory is not constrained, so we can shortcut it
293
- # before execution.
294
- if self .simplifier is not None :
295
- logger .debug ('Shortcutting an unconstrained path.' )
296
- shortcut_path = self .simplifier .ShortcutPath (
297
- cloned_robot , path , defer = False , ** shortcut_options )
310
+ # Directly compute a timing of smooth trajectories.
311
+ if smooth :
312
+ logger .warning (
313
+ 'Post-processing smooth paths is not supported.'
314
+ ' Using the default post-processing logic; this may'
315
+ ' significantly change the geometric path.'
316
+ )
317
+
318
+ # The trajectory is constrained. Retime it without changing the
319
+ # geometric path.
320
+ if constrained :
321
+ logger .debug ('Retiming a constrained path. The output'
322
+ ' trajectory will stop at every waypoint.' )
323
+ traj = self .retimer .RetimeTrajectory (
324
+ cloned_robot , path , defer = False , ** retiming_options )
325
+ # The trajectory is not constrained, so we can shortcut it
326
+ # before execution.
298
327
else :
299
- logger .debug ('Skipping shortcutting; no simplifier'
300
- ' available.' )
301
- shortcut_path = path
302
-
303
- logger .debug ('Smoothing an unconstrained path.' )
304
- traj = self .smoother .RetimeTrajectory (
305
- cloned_robot , shortcut_path , defer = False ,
306
- ** smoothing_options )
328
+ if self .simplifier is not None :
329
+ logger .debug ('Shortcutting an unconstrained path.' )
330
+ shortcut_path = self .simplifier .ShortcutPath (
331
+ cloned_robot , path , defer = False , ** shortcut_options )
332
+ else :
333
+ logger .debug ('Skipping shortcutting; no simplifier'
334
+ ' available.' )
335
+ shortcut_path = path
336
+
337
+ logger .debug ('Smoothing an unconstrained path.' )
338
+ traj = self .smoother .RetimeTrajectory (
339
+ cloned_robot , shortcut_path , defer = False ,
340
+ ** smoothing_options )
307
341
308
342
return CopyTrajectory (traj , env = self .GetEnv ())
309
343
0 commit comments