Skip to content

Commit 8951ec9

Browse files
author
DavidB-CMU
committed
Improvements to PlanWorkspacePath in vectorfield.py
1 parent 129f7e4 commit 8951ec9

File tree

1 file changed

+65
-30
lines changed

1 file changed

+65
-30
lines changed

src/prpy/planning/vectorfield.py

Lines changed: 65 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
# Copyright (c) 2015, Carnegie Mellon University
44
# All rights reserved.
55
# Authors: Siddhartha Srinivasa <siddh@cs.cmu.edu>
6+
# Authors: Michael Koval <mkoval@cs.cmu.edu>
7+
# Authors: David Butterworth <dbworth@cmu.edu>
68
#
79
# Redistribution and use in source and binary forms, with or without
810
# modification, are permitted provided that the following conditions are met:
@@ -79,9 +81,13 @@ def __init__(self):
7981
def __str__(self):
8082
return 'VectorFieldPlanner'
8183

84+
85+
8286
@PlanningMethod
8387
def PlanToEndEffectorPose(self, robot, goal_pose, timelimit=5.0,
84-
pose_error_tol=0.01, **kw_args):
88+
pose_error_tol=0.01,
89+
integration_interval = 10.0,
90+
**kw_args):
8591
"""
8692
Plan to an end effector pose by following a geodesic loss function
8793
in SE(3) via an optimized Jacobian.
@@ -90,6 +96,7 @@ def PlanToEndEffectorPose(self, robot, goal_pose, timelimit=5.0,
9096
@param goal_pose desired end-effector pose
9197
@param timelimit time limit before giving up
9298
@param pose_error_tol in meters
99+
@param integration_interval The time interval to integrate over
93100
@return traj
94101
"""
95102
manip = robot.GetActiveManipulator()
@@ -122,7 +129,6 @@ def CloseEnough():
122129
return Status.TERMINATE
123130
return Status.CONTINUE
124131

125-
integration_interval = 10.0
126132
traj = self.FollowVectorField(robot, vf_geodesic, CloseEnough,
127133
integration_interval,
128134
timelimit,
@@ -138,6 +144,7 @@ def PlanToEndEffectorOffset(self, robot, direction, distance,
138144
max_distance=None, timelimit=5.0,
139145
position_tolerance=0.01,
140146
angular_tolerance=0.15,
147+
integration_interval = 10.0,
141148
**kw_args):
142149
"""
143150
Plan to a desired end-effector offset with move-hand-straight
@@ -150,6 +157,7 @@ def PlanToEndEffectorOffset(self, robot, direction, distance,
150157
@param timelimit timeout in seconds
151158
@param position_tolerance constraint tolerance in meters
152159
@param angular_tolerance constraint tolerance in radians
160+
@param integration_interval The time interval to integrate over
153161
@return traj
154162
"""
155163
if distance < 0:
@@ -219,7 +227,6 @@ def TerminateMove():
219227

220228
return Status.CONTINUE
221229

222-
integration_interval = 10.0
223230
return self.FollowVectorField(robot, vf_straightline, TerminateMove,
224231
integration_interval,
225232
timelimit,
@@ -231,9 +238,10 @@ def PlanWorkspacePath(self, robot, traj,
231238
timelimit=5.0,
232239
position_tolerance=0.01,
233240
angular_tolerance=0.15,
234-
goal_pose_tol=0.01,
241+
t_step = 0.001,
235242
Kp_ff=None,
236243
Kp_e=None,
244+
integration_interval = 10.0,
237245
**kw_args):
238246
"""
239247
Plan a configuration space path given a workspace path.
@@ -246,7 +254,9 @@ def PlanWorkspacePath(self, robot, traj,
246254
@param float timelimit: Max planning time (seconds).
247255
@param float position_tolerance: Constraint tolerance (meters).
248256
@param float angular_tolerance: Constraint tolerance (radians).
249-
@param float goal_pose_tol: Goal tolerance (meters).
257+
@param float t_step: Time step to find vector tanget to current
258+
position on the trajectory, using finite
259+
differences.
250260
@param numpy.array Kp_ff: Feed-forward gain.
251261
A 1x6 vector, where first 3 elements
252262
affect the translational velocity,
@@ -257,37 +267,33 @@ def PlanWorkspacePath(self, robot, traj,
257267
affect the translational velocity,
258268
the last 3 elements affect the
259269
rotational velocity.
270+
@param integration_interval The time interval to integrate over.
260271
261272
@return openravepy.Trajectory qtraj: Configuration space path.
262273
"""
263274

264-
if not util.IsTrajectoryTypeIkParameterization(traj):
275+
if not util.IsTrajectoryTypeIkParameterizationTransform6D(traj):
265276
raise ValueError("Trajectory is not a workspace trajectory, it "
266277
"must have configuration specification of "
267278
"openravepy.IkParameterizationType.Transform6D")
268279

269-
#if IsTimedTrajectory(traj):
270-
# raise ValueError("PlanWorkspacePath expected an un-timed "
271-
# "trajectory.")
280+
if util.IsTimedTrajectory(traj):
281+
raise ValueError("PlanWorkspacePath expected an un-timed "
282+
"trajectory.")
272283

273284
if position_tolerance < 0.0:
274285
raise ValueError('Position tolerance must be non-negative.')
275286
elif angular_tolerance < 0.0:
276287
raise ValueError('Angular tolerance must be non-negative.')
277-
elif goal_pose_tol < 0.0:
278-
raise ValueError('Goal-pose tolerance must be non-negative.')
279288

280-
#
281-
#
282-
# ADD ComputeGeodesicUnitTiming()
283-
#
284-
#
289+
# Time the trajectory based on its distance
290+
traj = util.ComputeGeodesicUnitTiming(traj, env=None, alpha=1.0)
285291

286292
# Set the default gains
287293
if Kp_ff == None:
288-
Kp_ff = numpy.array([1.0,1.0,1.0,1.0,1.0,1.0])
294+
Kp_ff = 0.4*numpy.array([1.0,1.0,1.0,1.0,1.0,1.0])
289295
if Kp_e == None:
290-
Kp_e = numpy.array([1.0,1.0,1.0,1.0,1.0,1.0])
296+
Kp_e = 1.0*numpy.array([1.0,1.0,1.0,1.0,1.0,1.0])
291297

292298
manip = robot.GetActiveManipulator()
293299
Tstart = manip.GetEndEffectorTransform()
@@ -306,19 +312,31 @@ def vf_path():
306312
# the the closest point
307313
(_,t,_) = util.GetMinDistanceBetweenTransformAndWorkspaceTraj(
308314
T_ee_actual,
309-
traj)
315+
traj,
316+
0.0005)
310317
# Get the desired end-effector transform from
311318
# the goal trajectory
312-
t_step = 0.2
313319
desired_T_ee = openravepy.matrixFromPose(traj.Sample(t)[0:7])
320+
321+
# Get the next end-effector transform, using finite-differences
314322
pose_ee_next = traj.Sample(t+t_step)[0:7]
315323
desired_T_ee_next = openravepy.matrixFromPose(pose_ee_next)
316324

325+
# Get the translation tangent to current position
326+
tangent_vec = desired_T_ee_next[0:3,3] - desired_T_ee[0:3,3]
327+
# Get the translational error
328+
position_error_vec = desired_T_ee[0:3,3] - T_ee_actual[0:3,3]
329+
# Get the translational error perpendicular to the path
330+
tangent_trans_error = position_error_vec - \
331+
numpy.dot(position_error_vec, util.NormalizeVector(tangent_vec))
332+
tangent_trans_error = numpy.nan_to_num(tangent_trans_error)
333+
317334
# The twist between the actual end-effector position and
318335
# where it should be on the goal trajectory
319336
# (the error term)
320337
twist_perpendicular = util.GeodesicTwist(T_ee_actual,
321338
desired_T_ee)
339+
twist_perpendicular[0:3] = tangent_trans_error
322340

323341
# The twist tangent to where the end-effector should be
324342
# on the goal trajectory
@@ -355,16 +373,31 @@ def TerminateMove():
355373
# the the closest point
356374
(_,t,_) = util.GetMinDistanceBetweenTransformAndWorkspaceTraj(
357375
T_ee_curr,
358-
traj)
376+
traj,
377+
0.0005)
359378
# Get the desired end-effector transform from
360379
# the goal trajectory
361-
T_ee_desired = openravepy.matrixFromPose(traj.Sample(t)[0:7])
380+
desired_T_ee = openravepy.matrixFromPose(traj.Sample(t)[0:7])
381+
382+
# Get the position vector tangent to the trajectory,
383+
# using finite-differences
384+
pose_ee_next = traj.Sample(t+t_step)[0:7]
385+
desired_T_ee_next = openravepy.matrixFromPose(pose_ee_next)
386+
tangent_vec = desired_T_ee_next[0:3,3] - desired_T_ee[0:3,3]
362387

363388
# Calculate error between current end-effector pose
364389
# and where we should be on the goal trajectory
365-
geodesic_error = util.GeodesicError(T_ee_desired, T_ee_curr)
390+
geodesic_error = util.GeodesicError(desired_T_ee, T_ee_curr)
366391
orientation_error = geodesic_error[3]
367-
position_error = geodesic_error[0:3]
392+
position_error_vec = geodesic_error[0:3]
393+
394+
# Use only the translation error that is perpendicular
395+
# to our current position
396+
tangent_trans_error = position_error_vec - \
397+
numpy.dot(position_error_vec, util.NormalizeVector(tangent_vec))
398+
tangent_trans_error = numpy.nan_to_num(tangent_trans_error)
399+
400+
position_error = tangent_trans_error
368401

369402
if numpy.fabs(orientation_error) > angular_tolerance:
370403
raise ConstraintViolationPlanningError(
@@ -376,14 +409,15 @@ def TerminateMove():
376409
'Deviated from straight line constraint.')
377410

378411
# Check if we have reached the end of the goal trajectory
379-
dist_to_goal = util.GetGeodesicDistanceBetweenTransforms(T_ee_curr,
380-
T_ee_goal)
381-
if numpy.fabs(dist_to_goal) <= goal_pose_tol:
412+
error_to_goal = util.GeodesicError(T_ee_curr, T_ee_goal)
413+
goal_orientation_error = error_to_goal[3] # radians
414+
goal_position_error = error_to_goal[0:3] # x,y,z
415+
if ((numpy.fabs(goal_orientation_error) < angular_tolerance) and
416+
(numpy.linalg.norm(goal_position_error) < position_tolerance)):
382417
return Status.CACHE_AND_TERMINATE
383418

384419
return Status.CONTINUE
385420

386-
integration_interval = 10.0
387421
return self.FollowVectorField(robot, vf_path, TerminateMove,
388422
integration_interval,
389423
timelimit, **kw_args)
@@ -458,8 +492,9 @@ def fn_status_callback(t, q):
458492
configuration. This is called multiple times at DOF
459493
resolution in order to check along the entire length of the
460494
trajectory.
461-
Note: Currently this is called after each integration time
462-
step, which means we are doing more checks than required.
495+
Note: This is called by fn_callback, which is currently
496+
called after each integration time step, which means we are
497+
doing more checks than required.
463498
"""
464499
if time.time() - time_start >= timelimit:
465500
raise TimeLimitError()

0 commit comments

Comments
 (0)