Skip to content

Commit 2234aff

Browse files
committed
Adding support for execution of base trajectories
1 parent bef787a commit 2234aff

File tree

3 files changed

+97
-8
lines changed

3 files changed

+97
-8
lines changed

src/prpy/base/mobilebase.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import copy, functools, numpy, openravepy
3232
from .. import bind
3333
from prpy.clone import Clone
34+
from ..planning.retimer import OpenRAVEAffineRetimer
3435

3536
def create_affine_trajectory(robot, poses):
3637
doft = openravepy.DOFAffine.X | openravepy.DOFAffine.Y | openravepy.DOFAffine.RotationAxis
@@ -50,6 +51,8 @@ def __init__(self, sim, robot):
5051
self.simulated = sim
5152
self.robot = robot
5253

54+
self.retimer = OpenRAVEAffineRetimer()
55+
5356
def __dir__(self):
5457
# Add planning methods to the tab-completion list.
5558
method_names = set(self.__dict__.keys())
@@ -167,6 +170,41 @@ def _BasePlanWrapper(self, planning_method, args, kw_args):
167170

168171
# Optionally execute the trajectory.
169172
if 'execute' not in kw_args or kw_args['execute']:
170-
return robot.ExecuteTrajectory(traj, **kw_args)
173+
return self.ExecuteBasePath(traj, **kw_args)
171174
else:
172175
return traj
176+
177+
def ExecuteBasePath(self, path, defer=False, **kwargs):
178+
179+
def do_execute(path, **kwargs):
180+
robot = self.robot
181+
with Clone(robot.GetEnv()) as cloned_env:
182+
183+
cloned_robot = cloned_env.Cloned(robot)
184+
cloned_robot.SetActiveDOFs(
185+
[],
186+
affine=(openravepy.DOFAffine.X |
187+
openravepy.DOFAffine.Y |
188+
openravepy.DOFAffine.RotationAxis)
189+
)
190+
191+
cloned_timed_traj = self.retimer.RetimeTrajectory(cloned_robot, path, defer=False, **kwargs)
192+
193+
# Copy the trajectory back to the original environment.
194+
from ..util import CopyTrajectory
195+
timed_traj = CopyTrajectory(cloned_timed_traj, env=robot.GetEnv())
196+
197+
return robot.ExecuteTrajectory(timed_traj, defer=False, **kwargs)
198+
199+
if defer:
200+
from trollius.executor import get_default_executor
201+
from trollius.futures import wrap_future
202+
203+
executor = kwargs.get('executor') or get_default_executor()
204+
return wrap_future(
205+
executor.submit(do_execute,
206+
path, **kwargs
207+
)
208+
)
209+
else:
210+
return do_execute(path, **kwargs)

src/prpy/base/robot.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ def ExecutePath(self, path, simplify=True, smooth=True, defer=False,
166166
def do_execute(path, simplify, smooth, timeout, **kwargs):
167167

168168
with Clone(self.GetEnv()) as cloned_env:
169-
traj_dofs = prpy.util.GetTrajectoryIndices(path)
169+
traj_dofs = util.GetTrajectoryIndices(path)
170170
cloned_env.Cloned(self).SetActiveDOFs(traj_dofs)
171171
cloned_robot = cloned_env.Cloned(self)
172172

@@ -203,7 +203,7 @@ def ExecuteTrajectory(self, traj, defer=False, timeout=None, period=0.01, **kw_a
203203
# TODO: Check if this trajectory contains the base.
204204

205205
logger.debug('Begin ExecuteTrajectory')
206-
needs_base = False
206+
needs_base = util.HasAffineDOFs(traj.GetConfigurationSpecification())
207207

208208
self.GetController().SetPath(traj)
209209

@@ -238,9 +238,7 @@ def do_poll():
238238

239239
return trollius.async(do_poll())
240240
else:
241-
import prpy.viz
242-
with prpy.viz.RenderTrajectory(self, traj):
243-
util.WaitForControllers(active_controllers, timeout=timeout)
241+
util.WaitForControllers(active_controllers, timeout=timeout)
244242

245243
return traj
246244

src/prpy/planning/retimer.py

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

3131
import logging, numpy, openravepy, os, tempfile
32-
from ..util import CopyTrajectory, SimplifyTrajectory
33-
from base import BasePlanner, PlanningError, PlanningMethod
32+
from ..util import CopyTrajectory, SimplifyTrajectory, HasAffineDOFs
33+
from base import BasePlanner, PlanningError, PlanningMethod, UnsupportedPlanningError
3434
from openravepy import PlannerStatus
3535

3636

@@ -44,6 +44,9 @@ def RetimeTrajectory(self, robot, path, **kw_args):
4444
RetimeTrajectory = openravepy.planningutils.RetimeTrajectory
4545

4646
cspec = path.GetConfigurationSpecification()
47+
if HasAffineDOFs(cspec):
48+
raise UnsupportedPlanningError('OpenRAVERetimer does not support paths with affine DOFs')
49+
4750
"""
4851
group = cspec.GetGroupFromName('joint_values')
4952
if group.interpolation != 'linear':
@@ -83,3 +86,53 @@ def __init__(self):
8386
class ParabolicSmoother(OpenRAVERetimer):
8487
def __init__(self):
8588
super(ParabolicSmoother, self).__init__('HauserParabolicSmoother')
89+
90+
class OpenRAVEAffineRetimer(BasePlanner):
91+
92+
def __init__(self,):
93+
super(OpenRAVEAffineRetimer, self).__init__()
94+
95+
@PlanningMethod
96+
def RetimeTrajectory(self, robot, path, **kw_args):
97+
98+
RetimeTrajectory = openravepy.planningutils.RetimeAffineTrajectory
99+
100+
cspec = path.GetConfigurationSpecification()
101+
102+
# Check for anything other than affine dofs in the traj
103+
# TODO: Better way to do this?
104+
affine_groups = ['affine_transform',
105+
'affine_velocities',
106+
'affine_accelerations']
107+
108+
for group in cspec.GetGroups():
109+
found = False
110+
for group_name in affine_groups:
111+
if group_name in group.name: # group.name contains more stuff than just the name
112+
found = True
113+
break
114+
115+
if not found:
116+
raise UnsupportedPlanningError('OpenRAVEAffineRetimer only supports untimed paths with affine DOFs. Found group: %s' % group.name)
117+
118+
119+
120+
# Copy the input trajectory into the planning environment. This is
121+
# necessary for two reasons: (1) the input trajectory may be in another
122+
# environment and/or (2) the retimer modifies the trajectory in-place.
123+
output_traj = CopyTrajectory(path, env=self.env)
124+
125+
# Compute the timing. This happens in-place.
126+
max_velocities = [robot.GetAffineTranslationMaxVels()[0],
127+
robot.GetAffineTranslationMaxVels()[1],
128+
robot.GetAffineRotationAxisMaxVels()[2]]
129+
max_accelerations = [3.*v for v in max_velocities]
130+
status = RetimeTrajectory(output_traj, max_velocities, max_accelerations,
131+
False)
132+
133+
if status not in [ PlannerStatus.HasSolution,
134+
PlannerStatus.InterruptedWithSolution ]:
135+
raise PlanningError('Retimer returned with status {0:s}.'.format(
136+
str(status)))
137+
138+
return output_traj

0 commit comments

Comments
 (0)