@@ -269,6 +269,8 @@ def do_postprocess():
269
269
'Setting robot "%s" DOFs %s as active for post-processing.' ,
270
270
cloned_robot .GetName (), list (dof_indices ))
271
271
272
+ # TODO: Handle a affine DOF trajectories for the base.
273
+
272
274
# Directly compute a timing of smooth trajectories.
273
275
if smooth :
274
276
logger .warning (
@@ -309,51 +311,74 @@ def do_postprocess():
309
311
else :
310
312
return do_postprocess ()
311
313
312
- def ExecutePath (self , path , simplify = True , smooth = True , defer = False ,
313
- timeout = 1. , ** kwargs ):
314
-
315
- logger .debug ('Begin ExecutePath' )
316
-
317
- def do_execute (path , simplify , smooth , timeout , ** kwargs ):
318
-
319
- with Clone (self .GetEnv ()) as cloned_env :
320
- traj_dofs = util .GetTrajectoryIndices (path )
321
- cloned_env .Cloned (self ).SetActiveDOFs (traj_dofs )
322
- cloned_robot = cloned_env .Cloned (self )
314
+ def ExecutePath (self , path , defer = False , executor = None , ** kwargs ):
315
+ """ Post-process and execute an un-timed path.
323
316
324
- if simplify :
325
- path = self .simplifier .ShortcutPath (cloned_robot , path , defer = False ,
326
- timeout = timeout , ** kwargs )
317
+ This method calls PostProcessPath, then passes the result to
318
+ ExecuteTrajectory. Any extra **kwargs are forwarded to both of these
319
+ methods. This function returns the timed trajectory that was executed
320
+ on the robot.
327
321
328
- retimer = self .smoother if smooth else self .retimer
329
- cloned_timed_traj = retimer .RetimeTrajectory (cloned_robot , path , defer = False , ** kwargs )
322
+ @param path OpenRAVE trajectory representing an un-timed path
323
+ @param defer execute asynchronously and return a future
324
+ @param executor if defer = True, which executor to use
325
+ @param **kwargs forwarded to PostProcessPath and ExecuteTrajectory
326
+ @return timed trajectory executed on the robot
327
+ """
330
328
331
- # Copy the trajectory back to the original environment.
332
- from .. util import CopyTrajectory
333
- timed_traj = CopyTrajectory ( cloned_timed_traj , env = self . GetEnv () )
329
+ def do_execute ():
330
+ logger . debug ( 'Post-processing path to compute a timed trajectory.' )
331
+ traj = self . PostProcessPath ( path , defer = False , ** kwargs )
334
332
335
- return self .ExecuteTrajectory (timed_traj , defer = False , ** kwargs )
333
+ logger .debug ('Executing timed trajectory.' )
334
+ return self .ExecuteTrajectory (traj , defer = False , ** kwargs )
336
335
337
336
if defer :
338
337
from trollius .executor import get_default_executor
339
338
from trollius .futures import wrap_future
340
339
341
- executor = kwargs .get ('executor' ) or get_default_executor ()
342
- return wrap_future (
343
- executor .submit (do_execute ,
344
- path , simplify = simplify , smooth = smooth , timeout = timeout ,
345
- ** kwargs
346
- )
347
- )
340
+ if executor is None :
341
+ executor = get_default_executor ()
342
+
343
+ return wrap_future (executor .submit (do_execute ))
348
344
else :
349
- return do_execute (path , simplify = simplify , smooth = smooth ,
350
- timeout = timeout , ** kwargs )
345
+ return do_execute ()
346
+
347
+ def ExecuteTrajectory (self , traj , defer = False , timeout = None , period = 0.01 ):
348
+ """ Executes a time trajectory on the robot.
349
+
350
+ This function directly executes a timed OpenRAVE trajectory on the
351
+ robot. If you have a geometric path, such as those returned by a
352
+ geometric motion planner, you should first time the path using
353
+ PostProcessPath. Alternatively, you could use the ExecutePath helper
354
+ function to time and execute the path in one function call.
355
+
356
+ If timeout = None (the default), this function does not return until
357
+ execution has finished. Termination occurs if the trajectory is
358
+ successfully executed or if a fault occurs (in this case, an exception
359
+ will be raised). If timeout is a float (including timeout = 0), this
360
+ function will return None once the timeout has ellapsed, even if the
361
+ trajectory is still being executed.
362
+
363
+ NOTE: We suggest that you either use timeout=None or defer=True. If
364
+ trajectory execution times out, there is no way to tell whether
365
+ execution was successful or not. Other values of timeout are only
366
+ supported for legacy reasons.
367
+
368
+ This function returns the trajectory that was actually executed on the
369
+ robot, including controller error. If this is not available, the input
370
+ trajectory will be returned instead.
371
+
372
+ @param traj timed OpenRAVE trajectory to be executed
373
+ @param defer execute asynchronously and return a trajectory Future
374
+ @param timeout maximum time to wait for execution to finish
375
+ @param period poll rate, in seconds, for checking trajectory status
376
+ @return trajectory executed on the robot
377
+ """
351
378
352
- def ExecuteTrajectory (self , traj , defer = False , timeout = None , period = 0.01 , ** kw_args ):
353
379
# TODO: Verify that the trajectory is timed.
354
380
# TODO: Check if this trajectory contains the base.
355
381
356
- logger .debug ('Begin ExecuteTrajectory' )
357
382
needs_base = util .HasAffineDOFs (traj .GetConfigurationSpecification ())
358
383
359
384
self .GetController ().SetPath (traj )
@@ -366,8 +391,13 @@ def ExecuteTrajectory(self, traj, defer=False, timeout=None, period=0.01, **kw_a
366
391
]
367
392
368
393
if needs_base :
369
- if hasattr (self , 'base' ) and hasattr (self .base , 'controller' ):
394
+ if (hasattr (self , 'base' ) and hasattr (self .base , 'controller' )
395
+ and self .base .controller is not None ):
370
396
active_controllers .append (self .base .controller )
397
+ else :
398
+ logger .warning (
399
+ 'Trajectory includes the base, but no base controller is'
400
+ ' available. Is self.base.controller set?' )
371
401
372
402
if defer :
373
403
import time
0 commit comments