Skip to content

Commit cdde97d

Browse files
committed
Merge branch 'master' of https://github.com/personalrobotics/prpy into bugfix/cloning_race
Conflicts: src/prpy/planning/base.py
2 parents dda5fa4 + dd52a02 commit cdde97d

File tree

8 files changed

+106
-25
lines changed

8 files changed

+106
-25
lines changed

CHANGELOG.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
Changelog for package prpy
33
^^^^^^^^^^^^^^^^^^^^^^^^^^
44

5+
1.1.0 (2015-06-01)
6+
------------------
7+
* Adding tags for capturing trajectory timing data
8+
* Update README.md
9+
Added enum34 dependency instructions into README
10+
* Contributors: Jennifer King, Michael Koval, Stefanos Nikolaidis
11+
512
1.0.0 (2015-05-01)
613
------------------
714
* Adding planner and planning_method and trajectory tag constants

package.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0"?>
22
<package>
33
<name>prpy</name>
4-
<version>1.0.0</version>
4+
<version>1.1.0</version>
55
<description>
66
Python utilities used by the Personal Robotics Laboratory.
77
</description>

src/prpy/base/robot.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@
3333
from .. import bind, named_config, planning, util
3434
from ..clone import Clone, Cloned
3535
from ..tsr.tsrlibrary import TSRLibrary
36-
from ..planning.base import Sequence
36+
from ..planning.base import Sequence, Tags
3737
from ..planning.ompl import OMPLSimplifier
3838
from ..planning.retimer import HauserParabolicSmoother, OpenRAVEAffineRetimer, ParabolicRetimer
3939
from ..planning.mac_smoother import MacSmoother
40+
from ..util import SetTrajectoryTags
4041

4142
logger = logging.getLogger('robot')
4243

@@ -377,6 +378,7 @@ def do_execute():
377378

378379
with Timer() as timer:
379380
traj = self.PostProcessPath(path, defer=False, **kwargs)
381+
SetTrajectoryTags(traj, {Tags.POSTPROCESS_TIME: timer.get_duration()}, append=True)
380382

381383
logger.info('Post-processing took %.3f seconds and produced a path'
382384
' with %d waypoints and a duration of %.3f seconds.',
@@ -385,7 +387,10 @@ def do_execute():
385387
traj.GetDuration()
386388
)
387389

388-
return self.ExecuteTrajectory(traj, defer=False, **kwargs)
390+
with Timer() as timer:
391+
exec_traj = self.ExecuteTrajectory(traj, defer=False, **kwargs)
392+
SetTrajectoryTags(exec_traj, {Tags.EXECUTION_TIME: timer.get_duration()}, append=True)
393+
return exec_traj
389394

390395
if defer is True:
391396
from trollius.executor import get_default_executor
@@ -541,7 +546,10 @@ def _PlanWrapper(self, planning_method, args, kw_args):
541546
config_spec = self.GetActiveConfigurationSpecification('linear')
542547

543548
# Call the planner.
544-
result = planning_method(self, *args, **kw_args)
549+
from ..util import Timer
550+
with Timer() as timer:
551+
result = planning_method(self, *args, **kw_args)
552+
SetTrajectoryTags(result, {Tags.PLAN_TIME: timer.get_duration()}, append=True)
545553

546554
def postprocess_trajectory(traj):
547555
# Strip inactive DOFs from the trajectory.

src/prpy/planning/base.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import openravepy
3636
from ..clone import Clone
3737
from ..util import CopyTrajectory, GetTrajectoryTags, SetTrajectoryTags
38+
from .exceptions import PlanningError, UnsupportedPlanningError
3839

3940
logger = logging.getLogger('planning')
4041

@@ -44,15 +45,9 @@ class Tags(object):
4445
CONSTRAINED = 'constrained'
4546
PLANNER = 'planner'
4647
METHOD = 'planning_method'
47-
48-
49-
class PlanningError(Exception):
50-
pass
51-
52-
53-
class UnsupportedPlanningError(PlanningError):
54-
pass
55-
48+
PLAN_TIME = 'planning_time'
49+
POSTPROCESS_TIME = 'postprocess_time'
50+
EXECUTION_TIME = 'execution_time'
5651

5752
class MetaPlanningError(PlanningError):
5853
def __init__(self, message, errors):

src/prpy/planning/exceptions.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
2+
class PlanningError(Exception):
3+
pass
4+
5+
6+
class UnsupportedPlanningError(PlanningError):
7+
pass
8+
9+
10+
class ConstraintViolationPlanningError(PlanningError):
11+
pass
12+
13+
14+
class CollisionPlanningError(PlanningError):
15+
def __init__(self, link1, link2, base_message='Detected collision'):
16+
self.link1 = link1
17+
self.link2 = link2
18+
19+
super(CollisionPlanningError, self).__init__(
20+
'{:s}: {:s} x {:s}.'.format(
21+
base_message,
22+
self._get_link_str(link1),
23+
self._get_link_str(link2)
24+
)
25+
)
26+
27+
@classmethod
28+
def FromReport(cls, report):
29+
return cls(report.plink1, report.plink2)
30+
31+
@staticmethod
32+
def _get_link_str(link):
33+
if link is not None:
34+
return '<{:s}, {:s}>'.format(
35+
link.GetParent().GetName(), link.GetName())
36+
else:
37+
return '<unknown>'
38+
39+
40+
class SelfCollisionPlanningError(CollisionPlanningError):
41+
pass
42+
43+
44+
class TimeoutPlanningError(PlanningError):
45+
def __init__(self, timelimit=None):
46+
if timelimit is not None:
47+
message = 'Exceeded {:.3f} s time limit.'.format(timelimit)
48+
else:
49+
message = 'Exceeded time limit.'
50+
51+
super(TimeoutPlanningError, self).__init__(message)

src/prpy/planning/retimer.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,13 +140,20 @@ def __init__(self, **kwargs):
140140

141141

142142
class HauserParabolicSmoother(OpenRAVERetimer):
143-
def __init__(self, **kwargs):
143+
def __init__(self, do_blend=True, do_shortcut=True, blend_radius=0.5,
144+
blend_iterations=4, **kwargs):
144145
super(HauserParabolicSmoother, self).__init__(
145146
'HauserParabolicSmoother', **kwargs)
146147

148+
self.default_options.update({
149+
'do_blend': int(do_blend),
150+
'do_shortcut': int(do_shortcut),
151+
'blend_radius': float(blend_radius),
152+
'blend_iterations': int(blend_iterations),
153+
})
147154

148-
class OpenRAVEAffineRetimer(BasePlanner):
149155

156+
class OpenRAVEAffineRetimer(BasePlanner):
150157
def __init__(self,):
151158
super(OpenRAVEAffineRetimer, self).__init__()
152159

src/prpy/planning/vectorfield.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -160,15 +160,19 @@ def TerminateMove():
160160
Succeed if distance moved is larger than max_distance.
161161
Cache and continue if distance moved is larger than distance.
162162
'''
163+
from .exceptions import ConstraintViolationPlanningError
164+
163165
Tnow = manip.GetEndEffectorTransform()
164166
error = util.GeodesicError(Tstart, Tnow)
165167
if numpy.fabs(error[3]) > angular_tolerance:
166-
raise PlanningError('Deviated from orientation constraint.')
168+
raise ConstraintViolationPlanningError(
169+
'Deviated from orientation constraint.')
167170
distance_moved = numpy.dot(error[0:3], direction)
168171
position_deviation = numpy.linalg.norm(error[0:3] -
169172
distance_moved*direction)
170173
if position_deviation > position_tolerance:
171-
raise PlanningError('Deviated from straight line constraint.')
174+
raise ConstraintViolationPlanningError(
175+
'Deviated from straight line constraint.')
172176

173177
if distance_moved > max_distance:
174178
return Status.TERMINATE
@@ -198,6 +202,12 @@ def FollowVectorField(self, robot, fn_vectorfield, fn_terminate,
198202
@param kw_args keyword arguments to be passed to fn_vectorfield
199203
@return traj
200204
"""
205+
from .exceptions import (
206+
CollisionPlanningError,
207+
SelfCollisionPlanningError,
208+
TimeoutPlanningError
209+
)
210+
201211
start_time = time.time()
202212

203213
try:
@@ -219,28 +229,30 @@ def FollowVectorField(self, robot, fn_vectorfield, fn_terminate,
219229
vlimits)
220230
dt_step *= dt_multiplier
221231
status = fn_terminate()
232+
report = openravepy.CollisionReport()
233+
222234
while status != Status.TERMINATE:
223235
# Check for a timeout.
224236
current_time = time.time()
225237
if (timelimit is not None and
226238
current_time - start_time > timelimit):
227-
raise PlanningError('Reached time limit.')
239+
raise TimeoutPlanningError(timelimit)
228240

229241
dqout = fn_vectorfield()
230242
numsteps = int(math.floor(max(
231243
abs(dqout*dt_step/robot.GetActiveDOFResolutions())
232244
)))
233245
if numsteps == 0:
234-
raise PlanningError('Step size too small, '
235-
'unable to progress')
246+
raise PlanningError('Step size too small,'
247+
' unable to progress')
236248
dt = dt_step/numsteps
237249

238250
for step in xrange(numsteps):
239251
# Check for collisions.
240-
if self.env.CheckCollision(robot):
241-
raise PlanningError('Encountered collision.')
242-
if robot.CheckSelfCollision():
243-
raise PlanningError('Encountered self-collision.')
252+
if self.env.CheckCollision(robot, report):
253+
raise CollisionPlanningError.FromReport(report)
254+
if robot.CheckSelfCollision(report):
255+
raise SelfCollisionPlanningError.FromReport(report)
244256

245257
status = fn_terminate()
246258
if status == Status.CACHE_AND_CONTINUE:

src/prpy/planning/workspace.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ def PlanWorkspacePath(self, robot, traj, timelimit=5.0,
152152
@param timelimit timeout in seconds
153153
@return qtraj configuration space path
154154
"""
155+
from .exceptions import TimeoutPlanningError
155156

156157
with robot:
157158
manip = robot.GetActiveManipulator()
@@ -179,7 +180,7 @@ def PlanWorkspacePath(self, robot, traj, timelimit=5.0,
179180
current_time = time.time()
180181
if (timelimit is not None and
181182
current_time - start_time > timelimit):
182-
raise PlanningError('Reached time limit.')
183+
raise TimeoutPlanningError(timelimit)
183184

184185
# Hypothesize new configuration as closest IK to current
185186
qcurr = robot.GetActiveDOFValues() # Configuration at t.

0 commit comments

Comments
 (0)