Skip to content

Commit dd52a02

Browse files
committed
Merge pull request #132 from personalrobotics/feature/PlanningExceptions
Added more fine-grained planning exceptions.
2 parents c7c8b5f + af57895 commit dd52a02

File tree

4 files changed

+75
-18
lines changed

4 files changed

+75
-18
lines changed

src/prpy/planning/base.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import openravepy
3535
from ..clone import Clone
3636
from ..util import CopyTrajectory, GetTrajectoryTags, SetTrajectoryTags
37+
from .exceptions import PlanningError, UnsupportedPlanningError
3738

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

@@ -47,14 +48,6 @@ class Tags(object):
4748
POSTPROCESS_TIME = 'postprocess_time'
4849
EXECUTION_TIME = 'execution_time'
4950

50-
class PlanningError(Exception):
51-
pass
52-
53-
54-
class UnsupportedPlanningError(PlanningError):
55-
pass
56-
57-
5851
class MetaPlanningError(PlanningError):
5952
def __init__(self, message, errors):
6053
PlanningError.__init__(self, message)

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/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)