@@ -96,7 +96,8 @@ def PlanToEndEffectorPose(self, robot, goal_pose, timelimit=5.0,
96
96
97
97
def vf_geodesic ():
98
98
"""
99
- Function defining a joint-space vector field.
99
+ Define a joint-space vector field, that moves along the
100
+ geodesic (shortest path) from the start pose to the goal pose.
100
101
"""
101
102
twist = util .GeodesicTwist (manip .GetEndEffectorTransform (),
102
103
goal_pose )
@@ -109,9 +110,10 @@ def vf_geodesic():
109
110
110
111
def CloseEnough ():
111
112
"""
112
- Function defining the termination condition.
113
-
114
- Succeed if end-effector pose is close to the goal pose.
113
+ The termination condition.
114
+ At each integration step, the geodesic error between the
115
+ start and goal poses is compared. If within threshold,
116
+ the integration will terminate.
115
117
"""
116
118
pose_error = util .GetGeodesicDistanceBetweenTransforms (
117
119
manip .GetEndEffectorTransform (),
@@ -120,9 +122,9 @@ def CloseEnough():
120
122
return Status .TERMINATE
121
123
return Status .CONTINUE
122
124
123
- integration_timelimit = 10.0
125
+ integration_interval = 10.0
124
126
traj = self .FollowVectorField (robot , vf_geodesic , CloseEnough ,
125
- integration_timelimit ,
127
+ integration_interval ,
126
128
timelimit ,
127
129
** kw_args )
128
130
@@ -163,7 +165,7 @@ def PlanToEndEffectorOffset(self, robot, direction, distance,
163
165
164
166
# Normalize the direction vector.
165
167
direction = numpy .array (direction , dtype = 'float' )
166
- direction /= numpy . linalg . norm (direction )
168
+ direction = util . NormalizeVector (direction )
167
169
168
170
manip = robot .GetActiveManipulator ()
169
171
Tstart = manip .GetEndEffectorTransform ()
@@ -217,9 +219,9 @@ def TerminateMove():
217
219
218
220
return Status .CONTINUE
219
221
220
- integration_timelimit = 10.0
222
+ integration_interval = 10.0
221
223
return self .FollowVectorField (robot , vf_straightline , TerminateMove ,
222
- integration_timelimit ,
224
+ integration_interval ,
223
225
timelimit ,
224
226
** kw_args )
225
227
@@ -230,6 +232,8 @@ def PlanWorkspacePath(self, robot, traj,
230
232
position_tolerance = 0.01 ,
231
233
angular_tolerance = 0.15 ,
232
234
goal_pose_tol = 0.01 ,
235
+ Kp_ff = None ,
236
+ Kp_e = None ,
233
237
** kw_args ):
234
238
"""
235
239
Plan a configuration space path given a workspace path.
@@ -243,13 +247,47 @@ def PlanWorkspacePath(self, robot, traj,
243
247
@param float position_tolerance: Constraint tolerance (meters).
244
248
@param float angular_tolerance: Constraint tolerance (radians).
245
249
@param float goal_pose_tol: Goal tolerance (meters).
250
+ @param numpy.array Kp_ff: Feed-forward gain.
251
+ A 1x6 vector, where first 3 elements
252
+ affect the translational velocity,
253
+ the last 3 elements affect the
254
+ rotational velocity.
255
+ @param numpy.array Kp_e: Error gain.
256
+ A 1x6 vector, where first 3 elements
257
+ affect the translational velocity,
258
+ the last 3 elements affect the
259
+ rotational velocity.
246
260
247
261
@return openravepy.Trajectory qtraj: Configuration space path.
248
262
"""
263
+
264
+ if not util .IsTrajectoryTypeIkParameterization (traj ):
265
+ raise ValueError ("Trajectory is not a workspace trajectory, it "
266
+ "must have configuration specification of "
267
+ "openravepy.IkParameterizationType.Transform6D" )
268
+
269
+ #if IsTimedTrajectory(traj):
270
+ # raise ValueError("PlanWorkspacePath expected an un-timed "
271
+ # "trajectory.")
272
+
249
273
if position_tolerance < 0.0 :
250
274
raise ValueError ('Position tolerance must be non-negative.' )
251
275
elif angular_tolerance < 0.0 :
252
276
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.' )
279
+
280
+ #
281
+ #
282
+ # ADD ComputeGeodesicUnitTiming()
283
+ #
284
+ #
285
+
286
+ # Set the default gains
287
+ if Kp_ff == None :
288
+ Kp_ff = numpy .array ([1.0 ,1.0 ,1.0 ,1.0 ,1.0 ,1.0 ])
289
+ if Kp_e == None :
290
+ Kp_e = numpy .array ([1.0 ,1.0 ,1.0 ,1.0 ,1.0 ,1.0 ])
253
291
254
292
manip = robot .GetActiveManipulator ()
255
293
Tstart = manip .GetEndEffectorTransform ()
@@ -266,7 +304,7 @@ def vf_path():
266
304
267
305
# Find where we are on the goal trajectory by finding
268
306
# the the closest point
269
- (_ ,t ) = util .GetMinDistanceBetweenTransformAndWorkspaceTraj (
307
+ (_ ,t , _ ) = util .GetMinDistanceBetweenTransformAndWorkspaceTraj (
270
308
T_ee_actual ,
271
309
traj )
272
310
# Get the desired end-effector transform from
@@ -278,27 +316,23 @@ def vf_path():
278
316
279
317
# The twist between the actual end-effector position and
280
318
# where it should be on the goal trajectory
319
+ # (the error term)
281
320
twist_perpendicular = util .GeodesicTwist (T_ee_actual ,
282
321
desired_T_ee )
283
- direction_perpendicular = desired_T_ee [0 :3 ,3 ] - T_ee_actual [0 :3 ,3 ]
284
322
285
323
# The twist tangent to where the end-effector should be
286
324
# on the goal trajectory
325
+ # (the feed-forward term)
287
326
twist_parallel = util .GeodesicTwist (desired_T_ee ,
288
327
desired_T_ee_next )
289
- direction_parallel = desired_T_ee_next [0 :3 ,3 ] - desired_T_ee [0 :3 ,3 ]
290
-
291
- twist = 0.0 * twist_perpendicular + 1.0 * twist_parallel
292
328
293
- K_p = 0.5
294
- direction = (1.0 - K_p )* direction_perpendicular + \
295
- K_p * direction_parallel
296
- # Normalize the direction vector
297
- direction = numpy .array (direction , dtype = 'float' )
298
- direction /= numpy .linalg .norm (direction )
329
+ # Normalize the translational and angular velocity of
330
+ # the feed-forward twist
331
+ twist_parallel [0 :3 ] = util .NormalizeVector (twist_parallel [0 :3 ])
332
+ twist_parallel [3 :6 ] = util .NormalizeVector (twist_parallel [3 :6 ])
299
333
300
- # Modify the twist
301
- twist [ 0 : 3 ] = direction
334
+ # Apply gains
335
+ twist = Kp_e * twist_perpendicular + Kp_ff * twist_parallel
302
336
303
337
# Calculate joint velocities using an optimized jacobian
304
338
dqout , _ = util .ComputeJointVelocityFromTwist (robot , twist ,
@@ -319,7 +353,7 @@ def TerminateMove():
319
353
320
354
# Find where we are on the goal trajectory by finding
321
355
# the the closest point
322
- (_ , t ) = util .GetMinDistanceBetweenTransformAndWorkspaceTraj (
356
+ (_ ,t , _ ) = util .GetMinDistanceBetweenTransformAndWorkspaceTraj (
323
357
T_ee_curr ,
324
358
traj )
325
359
# Get the desired end-effector transform from
@@ -349,15 +383,15 @@ def TerminateMove():
349
383
350
384
return Status .CONTINUE
351
385
352
- integration_timelimit = 10.0
386
+ integration_interval = 10.0
353
387
return self .FollowVectorField (robot , vf_path , TerminateMove ,
354
- integration_timelimit ,
388
+ integration_interval ,
355
389
timelimit , ** kw_args )
356
390
357
391
358
392
@PlanningMethod
359
393
def FollowVectorField (self , robot , fn_vectorfield , fn_terminate ,
360
- integration_timelimit = 10. ,
394
+ integration_time_interval = 10.0 ,
361
395
timelimit = 5.0 ,
362
396
** kw_args ):
363
397
"""
@@ -366,8 +400,8 @@ def FollowVectorField(self, robot, fn_vectorfield, fn_terminate,
366
400
@param robot
367
401
@param fn_vectorfield a vectorfield of joint velocities
368
402
@param fn_terminate custom termination condition
369
- @param integration_timelimit The initial time step to be taken
370
- by the integrator .
403
+ @param integration_time_interval The time interval to integrate
404
+ over .
371
405
@param timelimit time limit before giving up
372
406
@param kw_args keyword arguments to be passed to fn_vectorfield
373
407
@return traj
@@ -420,7 +454,12 @@ def fn_wrapper(t, q):
420
454
421
455
def fn_status_callback (t , q ):
422
456
"""
423
- This is called for each collision check.
457
+ Check joint-limits and collisions for a specific joint
458
+ configuration. This is called multiple times at DOF
459
+ resolution in order to check along the entire length of the
460
+ trajectory.
461
+ Note: Currently this is called after each integration time
462
+ step, which means we are doing more checks than required.
424
463
"""
425
464
if time .time () - time_start >= timelimit :
426
465
raise TimeLimitError ()
@@ -496,7 +535,7 @@ def fn_callback(t, q):
496
535
integrator .set_solout (fn_callback )
497
536
# Initial conditions
498
537
integrator .set_initial_value (y = robot .GetActiveDOFValues (), t = 0. )
499
- integrator .integrate (t = integration_timelimit )
538
+ integrator .integrate (t = integration_time_interval )
500
539
501
540
t_cache = nonlocals ['t_cache' ]
502
541
exception = nonlocals ['exception' ]
0 commit comments