Skip to content

Commit 5d391c1

Browse files
author
David Butterworth
committed
Modify SnapPlanner to use new method to get sample points for collision-checking, also wrap lines to PEP-8.
1 parent 725ba24 commit 5d391c1

File tree

1 file changed

+77
-92
lines changed

1 file changed

+77
-92
lines changed

src/prpy/planning/snap.py

Lines changed: 77 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,25 @@
2929
# POSSIBILITY OF SUCH DAMAGE.
3030
import numpy
3131
import openravepy
32-
from ..util import SetTrajectoryTags
33-
from base import BasePlanner, PlanningError, PlanningMethod, Tags
32+
from prpy.util import SetTrajectoryTags
33+
from prpy.planning.base import BasePlanner
34+
from prpy.planning.base import PlanningError
35+
from prpy.planning.base import PlanningMethod
36+
from prpy.planning.base import Tags
3437

3538

3639
class SnapPlanner(BasePlanner):
3740
"""Planner that checks the straight-line trajectory to the goal.
3841
3942
SnapPlanner is a utility planner class that collision checks the
40-
straight-line trajectory to the goal. If that trajectory is invalid, i.e..
41-
due to an environment or self collision, the planner immediately returns
42-
failure by raising a PlanningError. Collision checking is performed using
43-
the standard CheckPathAllConstraints method.
44-
45-
SnapPlanner is intended to be used only as a "short circuit" to speed up
46-
planning between nearby configurations. This planner is most commonly used
47-
as the first item in a Sequence meta-planner to avoid calling a motion
48-
planner when the trivial solution is valid.
43+
straight-line trajectory to the goal. If that trajectory is invalid,
44+
e.g. due to an environment or self collision, the planner
45+
immediately returns failure by raising a PlanningError.
46+
47+
SnapPlanner is intended to be used only as a "short circuit" to
48+
speed-up planning between nearby configurations. This planner is
49+
most commonly used as the first item in a Sequence meta-planner to
50+
avoid calling a motion planner when the trivial solution is valid.
4951
"""
5052
def __init__(self):
5153
super(SnapPlanner, self).__init__()
@@ -56,34 +58,35 @@ def __str__(self):
5658
@PlanningMethod
5759
def PlanToConfiguration(self, robot, goal, **kw_args):
5860
"""
59-
Attempt to plan a straight line trajectory from the robot's current
60-
configuration to the goal configuration. This will fail if the
61-
straight-line path is not collision free.
61+
Attempt to plan a straight line trajectory from the robot's
62+
current configuration to the goal configuration. This will
63+
fail if the straight-line path is not collision free.
6264
6365
@param robot
6466
@param goal desired configuration
6567
@return traj
6668
"""
69+
6770
return self._Snap(robot, goal, **kw_args)
6871

6972
@PlanningMethod
7073
def PlanToEndEffectorPose(self, robot, goal_pose, **kw_args):
7174
"""
72-
Attempt to plan a straight line trajectory from the robot's current
73-
configuration to a desired end-effector pose. This happens by finding
74-
the closest IK solution to the robot's current configuration and
75-
attempts to snap there (using PlanToConfiguration) if possible. In the
76-
case of a redundant manipulator, no attempt is made to check other IK
77-
solutions.
75+
Attempt to plan a straight line trajectory from the robot's
76+
current configuration to a desired end-effector pose. This
77+
happens by finding the closest IK solution to the robot's
78+
current configuration and attempts to snap there
79+
(using PlanToConfiguration) if possible.
80+
In the case of a redundant manipulator, no attempt is
81+
made to check other IK solutions.
7882
7983
@param robot
8084
@param goal_pose desired end-effector pose
8185
@return traj
8286
"""
83-
84-
from .exceptions import CollisionPlanningError,SelfCollisionPlanningError
85-
from openravepy import CollisionReport
86-
87+
from prpy.planning.exceptions import CollisionPlanningError
88+
from prpy.planning.exceptions import SelfCollisionPlanningError
89+
8790
ikp = openravepy.IkParameterizationType
8891
ikfo = openravepy.IkFilterOptions
8992

@@ -99,17 +102,16 @@ def PlanToEndEffectorPose(self, robot, goal_pose, **kw_args):
99102

100103
if ik_solution is None:
101104
# FindIKSolutions is slower than FindIKSolution,
102-
# so call this only to identify and raise error when there is no solution
105+
# so call this only to identify and raise error when
106+
# there is no solution
103107
ik_solutions = manipulator.FindIKSolutions(
104-
ik_param,
105-
ikfo.IgnoreSelfCollisions,
106-
ikreturn=False,
107-
releasegil=True
108-
)
109-
108+
ik_param,
109+
ikfo.IgnoreSelfCollisions,
110+
ikreturn=False,
111+
releasegil=True)
110112
for q in ik_solutions:
111113
robot.SetActiveDOFValues(q)
112-
report = CollisionReport()
114+
report = openravepy.CollisionReport()
113115
if self.env.CheckCollision(robot, report=report):
114116
raise CollisionPlanningError.FromReport(report)
115117
elif robot.CheckSelfCollision(report=report):
@@ -120,81 +122,64 @@ def PlanToEndEffectorPose(self, robot, goal_pose, **kw_args):
120122
return self._Snap(robot, ik_solution, **kw_args)
121123

122124
def _Snap(self, robot, goal, **kw_args):
123-
from .exceptions import CollisionPlanningError,SelfCollisionPlanningError,JointLimitError
124-
from openravepy import CollisionReport
125-
126-
Closed = openravepy.Interval.Closed
127-
128-
start = robot.GetActiveDOFValues()
129-
active_indices = robot.GetActiveDOFIndices()
130-
131-
# Use the CheckPathAllConstraints helper function to collision check
132-
# the straight-line trajectory. We pass dummy values for dq0, dq1,
133-
# and timeelapsed since this is a purely geometric check.
134-
params = openravepy.Planner.PlannerParameters()
135-
params.SetRobotActiveJoints(robot)
136-
params.SetGoalConfig(goal)
137-
check = params.CheckPathAllConstraints(start, goal, [], [], 0., Closed,
138-
options = 15, returnconfigurations = True)
139-
140-
# If valid, above function returns (0,None, None, 0)
141-
# if not, it returns (1, invalid_config ,[], time_when_invalid),
142-
# in which case we identify and raise appropriate error.
143-
if check[0] != 0:
144-
q = check[1]
145-
146-
# Check for joint limit violation
147-
q_limit_min, q_limit_max = robot.GetActiveDOFLimits()
148-
149-
lower_position_violations = (q < q_limit_min)
150-
if lower_position_violations.any():
151-
index = lower_position_violations.nonzero()[0][0]
152-
raise JointLimitError(robot,
153-
dof_index=active_indices[index],
154-
dof_value=q[index],
155-
dof_limit=q_limit_min[index],
156-
description='position')
157-
158-
upper_position_violations = (q> q_limit_max)
159-
if upper_position_violations.any():
160-
index = upper_position_violations.nonzero()[0][0]
161-
raise JointLimitError(robot,
162-
dof_index=active_indices[index],
163-
dof_value=q[index],
164-
dof_limit=q_limit_max[index],
165-
description='position')
166-
167-
# Check for collision
168-
robot.SetActiveDOFValues(q)
169-
report = CollisionReport()
170-
if self.env.CheckCollision(robot, report=report):
171-
raise CollisionPlanningError.FromReport(report)
172-
elif robot.CheckSelfCollision(report=report):
173-
raise SelfCollisionPlanningError.FromReport(report)
174-
175-
raise PlanningError('Straight line trajectory is not valid.' )
176-
177-
# Create a two-point trajectory that starts at our current
178-
# configuration and takes us to the goal.
125+
from prpy.util import CheckJointLimits
126+
from prpy.util import GetLinearCollisionCheckPts
127+
from prpy.planning.exceptions import CollisionPlanningError
128+
from prpy.planning.exceptions import SelfCollisionPlanningError
129+
130+
# Create a two-point trajectory between the
131+
# current configuration and the goal.
132+
# (a straight line in joint space)
179133
traj = openravepy.RaveCreateTrajectory(self.env, '')
180134
cspec = robot.GetActiveConfigurationSpecification('linear')
181135
active_indices = robot.GetActiveDOFIndices()
182136

137+
# Check the start position is within joint limits,
138+
# this can throw a JointLimitError
139+
start = robot.GetActiveDOFValues()
140+
CheckJointLimits(robot, start)
141+
142+
# Add the start waypoint
183143
start_waypoint = numpy.zeros(cspec.GetDOF())
184144
cspec.InsertJointValues(start_waypoint, start, robot,
185145
active_indices, False)
186-
187146
traj.Init(cspec)
188147
traj.Insert(0, start_waypoint.ravel())
189148

190-
# Make the trajectory end at the goal configuration, as long as it
191-
# was not identical to the start configuration.
149+
# Make the trajectory end at the goal configuration, as
150+
# long as it is not in collision and is not identical to
151+
# the start configuration.
152+
CheckJointLimits(robot, goal)
192153
if not numpy.allclose(start, goal):
193154
goal_waypoint = numpy.zeros(cspec.GetDOF())
194155
cspec.InsertJointValues(goal_waypoint, goal, robot,
195156
active_indices, False)
196157
traj.Insert(1, goal_waypoint.ravel())
197158

198-
# Tag the return trajectory as smooth (in joint space) and return it.
159+
# Get joint configurations to check
160+
# Note: this returns a python generator, and if the
161+
# trajectory only has one waypoint then only the
162+
# start configuration will be collisioned checked.
163+
#
164+
# sampling_order: 'linear' or 'van_der_corput'
165+
checks = GetLinearCollisionCheckPts(robot, \
166+
traj, \
167+
norm_order=2, \
168+
sampling_order='van_der_corput')
169+
170+
# Run constraint checks at DOF resolution:
171+
for t, q in checks:
172+
# Set the joint positions
173+
# Note: the planner is using a cloned 'robot' object
174+
robot.SetActiveDOFValues(q)
175+
176+
# Check for collisions
177+
report = openravepy.CollisionReport()
178+
if self.env.CheckCollision(robot, report=report):
179+
raise CollisionPlanningError.FromReport(report)
180+
elif robot.CheckSelfCollision(report=report):
181+
raise SelfCollisionPlanningError.FromReport(report)
182+
183+
# Tag the return trajectory as smooth (in joint space).
199184
SetTrajectoryTags(traj, {Tags.SMOOTH: True}, append=True)
200185
return traj

0 commit comments

Comments
 (0)