28
28
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
29
# POSSIBILITY OF SUCH DAMAGE.
30
30
31
+ import logging
31
32
import numpy
32
33
import openravepy
34
+ import warnings
33
35
from manipulator import Manipulator
34
36
from prpy .clone import Clone
35
37
from .. import util
36
38
from .. import exceptions
37
39
40
+ logger = logging .getLogger ('wam' )
41
+
38
42
class WAM (Manipulator ):
39
43
def __init__ (self , sim , owd_namespace ,
40
44
iktype = openravepy .IkParameterization .Type .Transform6D ):
@@ -55,7 +59,7 @@ def __init__(self, sim, owd_namespace,
55
59
if sim :
56
60
from prpy .simulation import ServoSimulator
57
61
self .servo_simulator = ServoSimulator (
58
- self , rate = 20 , watchdog_timeout = 0.1 )
62
+ self , rate = 20 , watchdog_timeout = 0.1 )
59
63
60
64
def CloneBindings (self , parent ):
61
65
Manipulator .CloneBindings (self , parent )
@@ -90,6 +94,30 @@ def SetStiffness(manipulator, stiffness):
90
94
if not manipulator .simulated :
91
95
manipulator .controller .SendCommand ('SetStiffness {0:f}' .format (stiffness ))
92
96
97
+ def SetTrajectoryExecutionOptions (self , traj , stop_on_stall = False ,
98
+ stop_on_ft = False , force_magnitude = None , force_direction = None ,
99
+ torque = None ):
100
+ """Set OWD's trajectory execution options on trajectory.
101
+ @param stop_on_stall aborts the trajectory if the arm stalls
102
+ @param stop_on_ft aborts the trajectory if the force/torque
103
+ sensor reports a force or torque that exceeds
104
+ threshold specified by the force_magnitude,
105
+ force_direction, and torque options
106
+ @param force_magnitude force threshold value, in Newtons
107
+ @param force_direction unit vector in the force/torque coordinate
108
+ frame, which is int he same orientation as the
109
+ hand frame.
110
+ @param torque vector of the three torques
111
+ """
112
+ util .SetTrajectoryTags (traj , {
113
+ 'owd_options' : {
114
+ 'stop_on_stall' : bool (stop_on_stall ),
115
+ 'stop_on_ft' : bool (stop_on_ft ),
116
+ 'force_magnitude' : float (force_magnitude ),
117
+ 'force_direction' : list (force_direction ),
118
+ 'torque' : list (torque ),
119
+ }}, append = True )
120
+
93
121
def Servo (manipulator , velocities ):
94
122
"""Servo with a vector of instantaneous joint velocities.
95
123
@param velocities joint velocities, in radians per second
@@ -137,7 +165,7 @@ def ServoTo(manipulator, target, duration, timeStep=0.05, collisionChecking=True
137
165
else :
138
166
return False
139
167
140
- def GetVelocityLimits (self , openrave = True , owd = True ):
168
+ def GetVelocityLimits (self , openrave = None , owd = None ):
141
169
"""Get the OpenRAVE and OWD joint velocity limits.
142
170
This function checks both the OpenRAVE and OWD joint velocity limits.
143
171
If they do not match, a warning is printed and the minimum value is
@@ -146,37 +174,13 @@ def GetVelocityLimits(self, openrave=True, owd=True):
146
174
@param owd flag to set the OWD velocity limits
147
175
@return list of velocity limits, in radians per second
148
176
"""
149
- # Update the OpenRAVE limits.
150
- if openrave :
151
- or_velocity_limits = Manipulator .GetVelocityLimits (self )
152
- if self .simulated or not owd :
153
- return or_velocity_limits
154
-
155
- # Update the OWD limits.
156
- if owd and not self .simulated :
157
- args = [ 'GetSpeed' ]
158
- args_str = ' ' .join (args )
159
- owd_speed_limits_all = self .controller .SendCommand (args_str )
160
- #if we get nothing back, e.g. if the arm isn't running, return openrave lims
161
- if owd_speed_limits_all is None :
162
- return or_velocity_limits
163
-
164
- owd_speed_limits = map (float , owd_speed_limits_all .split (',' ));
165
- #first 7 numbers are velocity limits
166
- owd_velocity_limits = numpy .array (owd_speed_limits [0 :len (self .GetIndices ())])
167
-
168
- diff_arr = numpy .subtract (or_velocity_limits , owd_velocity_limits )
169
- max_diff = max (abs (diff_arr ))
170
-
171
- if max_diff > 0.01 :
172
- # TODO: Change this to use the logging framework.
173
- print ('GetVelocityLimits Error: openrave and owd limits very different' )
174
- print ('\t Openrave limits:\t ' + str (or_velocity_limits ))
175
- print ('\t OWD limits:\t \t ' + str (owd_velocity_limits ))
177
+ if openrave is not None or owd is not None :
178
+ warnings .warn (
179
+ 'The "openrave" and "owd" flags are deprecated in'
180
+ ' GetVelocityLimits and will be removed in a future version.' ,
181
+ DeprecationWarning )
176
182
177
- return numpy .minimum (or_velocity_limits , owd_velocity_limits )
178
-
179
- return or_velocity_limits
183
+ return Manipulator .GetVelocityLimits (self )
180
184
181
185
def SetVelocityLimits (self , velocity_limits , min_accel_time ,
182
186
openrave = True , owd = True ):
@@ -218,106 +222,130 @@ def ClearTrajectoryStatus(manipulator):
218
222
if not manipulator .simulated :
219
223
manipulator .controller .SendCommand ('ClearStatus' )
220
224
221
- def MoveUntilTouch (manipulator , direction , distance , max_distance = float ( '+inf' ) ,
225
+ def MoveUntilTouch (manipulator , direction , distance , max_distance = None ,
222
226
max_force = 5.0 , max_torque = None , ignore_collisions = None , ** kw_args ):
223
227
"""Execute a straight move-until-touch action.
224
228
This action stops when a sufficient force is is felt or the manipulator
225
229
moves the maximum distance. The motion is considered successful if the
226
230
end-effector moves at least distance. In simulation, a move-until-touch
227
231
action proceeds until the end-effector collids with the environment.
232
+
228
233
@param direction unit vector for the direction of motion in the world frame
229
234
@param distance minimum distance in meters
230
235
@param max_distance maximum distance in meters
231
236
@param max_force maximum force in Newtons
232
237
@param max_torque maximum torque in Newton-Meters
233
- @param execute optionally execute the trajectory
234
- @param ignore_collisions collisions with these objects are ignored in simulation
238
+ @param ignore_collisions collisions with these objects are ignored when planning the path, e.g. the object you think you will touch
235
239
@param **kw_args planner parameters
236
240
@return felt_force flag indicating whether we felt a force.
237
241
"""
238
- # TODO: Is ignore_collisions a list of names or KinBody pointers?
242
+ from contextlib import nested
243
+ from openravepy import CollisionReport , KinBody , Robot , RaveCreateTrajectory
244
+ from ..planning .exceptions import CollisionPlanningError
245
+
246
+ delta_t = 0.01
247
+
248
+ robot = manipulator .GetRobot ()
249
+ env = robot .GetEnv ()
250
+ dof_indices = manipulator .GetArmIndices ()
251
+
252
+ direction = numpy .array (direction , dtype = 'float' )
253
+
254
+ # Default argument values.
255
+ if max_distance is None :
256
+ max_distance = 1.
257
+ warnings .warn (
258
+ 'MoveUntilTouch now requires the "max_distance" argument.'
259
+ ' This will be an error in the future.' ,
260
+ DeprecationWarning )
261
+
239
262
if max_torque is None :
240
- max_torque = numpy .array ([100.0 , 100.0 , 100.0 ])
241
-
242
- ignore_col_obj_oldstate = []
263
+ max_torque = numpy .array ([100.0 , 100.0 , 100.0 ])
264
+
243
265
if ignore_collisions is None :
244
266
ignore_collisions = []
245
267
246
- for ignore_col_with in ignore_collisions :
247
- ignore_col_obj_oldstate .append (ignore_col_with .IsEnabled ())
248
- ignore_col_with .Enable (False )
249
-
250
- with manipulator .GetRobot ().GetEnv ():
251
- manipulator .GetRobot ().GetController ().SimulationStep (0 )
252
-
268
+ with env :
253
269
# Compute the expected force direction in the hand frame.
254
- direction = numpy .array (direction )
255
270
hand_pose = manipulator .GetEndEffectorTransform ()
256
271
force_direction = numpy .dot (hand_pose [0 :3 , 0 :3 ].T , - direction )
257
272
258
- with manipulator .GetRobot ():
259
- old_active_manipulator = manipulator .GetRobot ().GetActiveManipulator ()
273
+ # Disable the KinBodies listed in ignore_collisions. We backup the
274
+ # "enabled" state of all KinBodies so we can restore them later.
275
+ body_savers = [
276
+ body .CreateKinBodyStateSaver () for body in ignore_collisions ]
277
+ robot_saver = robot .CreateRobotStateSaver (
278
+ Robot .SaveParameters .ActiveDOF
279
+ | Robot .SaveParameters .ActiveManipulator
280
+ | Robot .SaveParameters .LinkTransformation )
281
+
282
+ with robot_saver , nested (* body_savers ) as f :
260
283
manipulator .SetActive ()
261
- traj = manipulator .PlanToEndEffectorOffset (direction , distance , max_distance = max_distance ,
262
- execute = False , ** kw_args )
263
-
264
- collided_with_obj = False
265
- try :
266
- if not manipulator .simulated :
267
- manipulator .hand .TareForceTorqueSensor ()
268
- #manipulator.GetRobot().ExecuteTrajectory(traj, execute=True, retime=True, blend=False)
269
- manipulator .GetRobot ().ExecuteTrajectory (traj , execute = True , retime = True , blend = True , stop_on_ft = True ,
270
- force_direction = force_direction , force_magnitude = max_force , torque = max_torque )
271
- for (ignore_col_with , oldstate ) in zip (ignore_collisions , ignore_col_obj_oldstate ):
272
- ignore_col_with .Enable (oldstate )
273
- else :
274
- traj = manipulator .GetRobot ().BlendTrajectory (traj )
275
- traj = manipulator .GetRobot ().RetimeTrajectory (traj , stop_on_ft = True , force_direction = force_direction ,
276
- force_magnitude = max_force , torque = max_torque )
277
- traj_duration = traj .GetDuration ()
278
- delta_t = 0.01
279
-
280
- traj_config_spec = traj .GetConfigurationSpecification ()
281
- traj_angle_group = traj_config_spec .GetGroupFromName ('joint_values' )
282
- path_config_spec = openravepy .ConfigurationSpecification ()
283
- # path_config_spec.AddDeltaTimeGroup()
284
- path_config_spec .AddGroup (traj_angle_group .name , traj_angle_group .dof , '' )
285
- # path_config_spec.AddDerivativeGroups(1, False);
286
- # path_config_spec.AddDerivativeGroups(2, False);
287
- # path_config_spec.AddGroup('owd_blend_radius', 1, 'next')
288
- path_config_spec .ResetGroupOffsets ()
289
-
290
- new_traj = openravepy .RaveCreateTrajectory (manipulator .GetRobot ().GetEnv (), '' )
291
- new_traj .Init (path_config_spec )
292
-
293
- for (ignore_col_with , oldstate ) in zip (ignore_collisions , ignore_col_obj_oldstate ):
294
- ignore_col_with .Enable (oldstate )
295
-
296
- with manipulator .GetRobot ():
297
- manipulator .SetActive ()
298
- waypoint_ind = 0
299
- for t in numpy .arange (0 , traj_duration , delta_t ):
300
- traj_sample = traj .Sample (t )
301
-
302
- waypoint = traj_config_spec .ExtractJointValues (traj_sample , manipulator .GetRobot (), manipulator .GetArmIndices ())
303
- manipulator .SetDOFValues (waypoint )
304
- #if manipulator.GetRobot().GetEnv().CheckCollision(manipulator.GetRobot()):
305
- for body in manipulator .GetRobot ().GetEnv ().GetBodies ():
306
- if manipulator .GetRobot ().GetEnv ().CheckCollision (manipulator .GetRobot (), body ):
307
- collided_with_obj = True
308
- break
309
- if collided_with_obj :
310
- break
311
- else :
312
- #waypoint = numpy.append(waypoint,t)
313
- new_traj .Insert (int (waypoint_ind ), waypoint , path_config_spec )
314
- waypoint_ind += 1
315
-
316
- #new_traj = manipulator.GetRobot().BlendTrajectory(new_traj)
317
- #new_traj = manipulator.GetRobot().RetimeTrajectory(new_traj)
318
- manipulator .GetRobot ().ExecuteTrajectory (new_traj , execute = True , retime = True , blend = True )
319
-
320
- return collided_with_obj
321
- # Trajectory is aborted by OWD because we felt a force.
322
- except exceptions .TrajectoryAborted :
323
- return True
284
+ robot_cspec = robot .GetActiveConfigurationSpecification ()
285
+
286
+ for body in ignore_collisions :
287
+ body .Enable (False )
288
+
289
+ path = robot .PlanToEndEffectorOffset (direction = direction ,
290
+ distance = distance , max_distance = max_distance , ** kw_args )
291
+
292
+ # Execute on the real robot by tagging the trajectory with options that
293
+ # tell the controller to stop on force/torque input.
294
+ if not manipulator .simulated :
295
+ manipulator .SetTrajectoryExecutionOptions (path , stop_on_ft = True ,
296
+ force_direction = force_direction , force_magnitude = max_force ,
297
+ torque = max_torque )
298
+
299
+ manipulator .hand .TareForceTorqueSensor ()
300
+
301
+ try :
302
+ robot .ExecutePath (path )
303
+ return False
304
+ except exceptions .TrajectoryAborted as e :
305
+ logger .warn ('MoveUntilTouch aborted: %s' , str (e ))
306
+ return True
307
+ # Forward-simulate the motion until it hits an object.
308
+ else :
309
+ traj = robot .PostProcessPath (path )
310
+ is_collision = False
311
+
312
+ traj_cspec = traj .GetConfigurationSpecification ()
313
+ new_traj = RaveCreateTrajectory (env , '' )
314
+ new_traj .Init (traj_cspec )
315
+
316
+ robot_saver = robot .CreateRobotStateSaver (
317
+ Robot .SaveParameters .LinkTransformation )
318
+
319
+ with env , robot_saver :
320
+ for t in numpy .arange (0 , traj .GetDuration (), delta_t ):
321
+ waypoint = traj .Sample (t )
322
+
323
+ dof_values = robot_cspec .ExtractJointValues (
324
+ waypoint , robot , dof_indices , 0 )
325
+ manipulator .SetDOFValues (dof_values )
326
+
327
+ # Terminate if we detect collision with the environment.
328
+ report = CollisionReport ()
329
+ if env .CheckCollision (robot , report = report ):
330
+ logger .info ('Terminated from collision: %s' ,
331
+ str (CollisionPlanningError .FromReport (report )))
332
+ is_collision = True
333
+ break
334
+ elif robot .CheckSelfCollision (report = report ):
335
+ logger .info ('Terminated from self-collision: %s' ,
336
+ str (CollisionPlanningError .FromReport (report )))
337
+ is_collision = True
338
+ break
339
+
340
+ # Build the output trajectory that stops in contact.
341
+ if new_traj .GetNumWaypoints () == 0 :
342
+ traj_cspec .InsertDeltaTime (waypoint , 0. )
343
+ else :
344
+ traj_cspec .InsertDeltaTime (waypoint , delta_t )
345
+
346
+ new_traj .Insert (new_traj .GetNumWaypoints (), waypoint )
347
+
348
+ if new_traj .GetNumWaypoints () > 0 :
349
+ robot .ExecuteTrajectory (new_traj )
350
+
351
+ return is_collision
0 commit comments