pr2_utils.py
Go to the documentation of this file.
00001 import roslib; roslib.load_manifest('rcommander')
00002 import rospy
00003 import actionlib
00004 import trajectory_msgs.msg as tm
00005 import numpy as np
00006 import functools as ft
00007 import sensor_msgs.msg as sm
00008 import std_msgs.msg as stdm
00009 import pr2_controllers_msgs.msg as pm
00010 import geometry_msgs.msg as gm
00011 import time
00012 
00013 #Test this
00014 def unwrap2(cpos, npos):
00015     two_pi = 2*np.pi
00016     nin = npos % two_pi
00017     n_multiples_2pi = np.floor(cpos/two_pi)
00018     return nin + n_multiples_2pi*two_pi
00019 
00020 
00021 ##
00022 # Takes a normal ROS callback channel and gives it an on demand query style
00023 # interface.
00024 class GenericListener:
00025     ##
00026     # Message has to have a header
00027     # @param node_name name of node (if haven't been inited)
00028     # @param message_type type of message to listen for
00029     # @param listen_channel ROS channel to listen
00030     # @param frequency the frequency to expect messages (used to print warning statements to console)
00031     # @param message_extractor function to preprocess the message into a desired format
00032     # @param queue_size ROS subscriber queue (None = infinite)
00033     def __init__(self, node_name, message_type, listen_channel,
00034                  frequency, message_extractor=None, queue_size=None):
00035         try:
00036             print node_name, ': inited node.'
00037             rospy.init_node(node_name, anonymous=True)
00038         except rospy.ROSException, e:
00039             pass
00040         self.last_msg_returned   = None   #Last message returned to callers from this class
00041         self.last_call_back      = None   #Local time of last received message
00042         self.delay_tolerance     = 1/frequency #in seconds
00043         self.reading             = {'message':None, 'msg_id':-1}
00044         self.curid               = 0
00045         self.message_extractor = message_extractor
00046 
00047         def callback(*msg):
00048             #If this is a tuple (using message filter)
00049             if 'header' in dir(msg):
00050                 if msg.__class__ == ().__class__:
00051                     msg_number = msg[0].header.seq
00052                 else:
00053                     msg_number = msg.header.seq
00054             else:
00055                 msg_number = self.curid
00056                 self.curid += 1
00057 
00058             #*msg makes everything a tuple.  If length is one, msg = (msg, )
00059             if len(msg) == 1:
00060                 msg = msg[0]
00061             
00062             self.reading  = {'message':msg, 'msg_id':msg_number}
00063 
00064             #Check for delayed messages
00065             self.last_call_back = time.time() #record when we have been called back last
00066 
00067         if message_type.__class__ == [].__class__:
00068             import message_filters
00069             subscribers = [message_filters.Subscriber(channel, mtype) for channel, mtype in zip(listen_channel, message_type)]
00070             queue_size = 10
00071             ts = message_filters.TimeSynchronizer(subscribers, queue_size)
00072             ts.registerCallback(callback)
00073         else:
00074             rospy.Subscriber(listen_channel, message_type, callback,
00075                              queue_size = queue_size)
00076 
00077         self.node_name = node_name
00078         #print node_name,': subscribed to', listen_channel
00079         rospy.loginfo('%s: subscribed to %s' % (node_name, listen_channel))
00080 
00081     def _check_for_delivery_hiccups(self):
00082         #If have received a message in the past
00083         if self.last_call_back != None:
00084             #Calculate how it has been
00085             time_diff = time.time() - self.last_call_back
00086             #If it has been longer than expected hz, complain
00087             if time_diff > self.delay_tolerance:
00088                 print self.node_name, ': have not heard back from publisher in', time_diff, 's'
00089 
00090     def _wait_for_first_read(self, quiet=False):
00091         if not quiet:
00092             rospy.loginfo('%s: waiting for reading ...' % self.node_name)
00093         while self.reading['message'] == None and not rospy.is_shutdown():
00094             time.sleep(0.1)
00095             #if not quiet:
00096             #    print self.node_name, ': waiting for reading ...'
00097 
00098     ## 
00099     # Supported use cases
00100     # rfid   - want to get a reading, can be stale, no duplication allowed (allow None),        query speed important
00101     # hokuyo - want to get a reading, can be stale, no duplication allowed (don't want a None), willing to wait for new data (default)
00102     # ft     - want to get a reading, can be stale, duplication allowed    (don't want a None), query speed important
00103     # NOT ALLOWED                                   duplication allowed,                        willing to wait for new data
00104     def read(self, allow_duplication=False, willing_to_wait=True, warn=False, quiet=True):
00105         if allow_duplication:
00106             if willing_to_wait:
00107                 raise RuntimeError('Invalid settings for read.')
00108             else: 
00109                 # ft - want to get a reading, can be stale, duplication allowed (but don't want a None), query speed important
00110                 #self._wait_for_first_read(quiet)
00111                 reading                = self.reading
00112                 self.last_msg_returned = reading['msg_id']
00113                 if self.message_extractor is not None:
00114                     return self.message_extractor(reading['message'])
00115                 else:
00116                     return reading['message']
00117         else:
00118             if willing_to_wait:
00119                 # hokuyo - want to get a reading, can be stale, no duplication allowed (don't want a None), willing to wait for new data (default)
00120                 self._wait_for_first_read(quiet)
00121                 while self.reading['msg_id'] == self.last_msg_returned and not rospy.is_shutdown():
00122                     if warn:
00123                         self._check_for_delivery_hiccups()
00124                     time.sleep(1/1000.0)
00125                 reading = self.reading
00126                 self.last_msg_returned = reading['msg_id']
00127                 if self.message_extractor is not None:
00128                     return self.message_extractor(reading['message'])
00129                 else:
00130                     return reading['message']
00131             else:
00132                 # rfid   - want to get a reading, can be stale, no duplication allowed (allow None),        query speed important
00133                 if self.last_msg_returned == self.reading['msg_id']:
00134                     return None
00135                 else:
00136                     reading = self.reading
00137                     self.last_msg_returned = reading['msg_id']
00138                     if self.message_extractor is not None:
00139                         return self.message_extractor(reading['message'])
00140                     else:
00141                         return reading['message']
00142 
00143 
00144 class Joint:
00145 
00146     def __init__(self, name, joint_provider):
00147         self.joint_provider = joint_provider
00148         self.joint_names = rospy.get_param('/%s/joints' % name)
00149         self.pub = rospy.Publisher('%s/command' % name, tm.JointTrajectory)
00150         self.names_index = None
00151         self.zeros = [0 for j in range(len(self.joint_names))]
00152 
00153     def pose(self, joint_states=None):
00154         if joint_states == None:
00155             joint_states = self.joint_provider()
00156 
00157         if self.names_index == None:
00158             self.names_index = {}
00159             for i, n in enumerate(joint_states.name):
00160                 self.names_index[n] = i
00161             self.joint_idx = [self.names_index[n] for n in self.joint_names]
00162 
00163         return (np.matrix(joint_states.position).T)[self.joint_idx, 0]
00164 
00165     def _create_trajectory(self, pos_mat, times, vel_mat=None):
00166         #Make JointTrajectoryPoints
00167         points = [tm.JointTrajectoryPoint() for i in range(pos_mat.shape[1])]
00168         for i in range(pos_mat.shape[1]):
00169             points[i].positions = pos_mat[:,i].A1.tolist()
00170             points[i].accelerations = self.zeros
00171             if vel_mat == None:
00172                 points[i].velocities = self.zeros
00173             else:
00174                 points[i].velocities = vel_mat[:,i].A1.tolist()
00175 
00176         for i in range(pos_mat.shape[1]):
00177             points[i].time_from_start = rospy.Duration(times[i])
00178 
00179         #Create JointTrajectory
00180         jt = tm.JointTrajectory()
00181         jt.joint_names = self.joint_names
00182         jt.points = points
00183         jt.header.stamp = rospy.get_rostime()
00184         return jt
00185 
00186     def set_poses(self, pos_mat, times):
00187         joint_trajectory = self._create_trajectory(pos_mat, times)
00188         self.pub.publish(joint_trajectory)
00189 
00190 
00191 class PR2Arm(Joint):
00192 
00193 
00194 
00195     def __init__(self, joint_provider, tf_listener, arm, use_kinematics=True):
00196         joint_controller_name = arm + '_arm_controller'
00197         cart_controller_name = arm + '_cart'
00198         Joint.__init__(self, joint_controller_name, joint_provider)
00199         self.arm = arm
00200         self.tf_listener = tf_listener
00201         self.client = actionlib.SimpleActionClient('/%s/joint_trajectory_action' % joint_controller_name, pm.JointTrajectoryAction)
00202         self.joint_controller_name = joint_controller_name
00203 
00204         self.cart_posure_pub = rospy.Publisher("/%s/command_posture" % cart_controller_name, stdm.Float64MultiArray).publish
00205         self.cart_pose_pub = rospy.Publisher("/%s/command_pose" % cart_controller_name, gm.PoseStamped).publish
00206         if arm == 'l':
00207             self.full_arm_name = 'left'
00208         else:
00209             self.full_arm_name = 'right'
00210 
00211         if use_kinematics:
00212             self.kinematics = pr2k.PR2ArmKinematics(self.full_arm_name, self.tf_listener)
00213         #self.ik_utilities = iku.IKUtilities(self.full_arm_name, self.tf_listener) 
00214 
00215         self.POSTURES = {
00216             'off':          np.matrix([]),
00217             'mantis':       np.matrix([0, 1, 0,  -1, 3.14, -1, 3.14]).T,
00218             'elbowupr':     np.matrix([-0.79,0,-1.6,  9999, 9999, 9999, 9999]).T,
00219             'elbowupl':     np.matrix([0.79,0,1.6 , 9999, 9999, 9999, 9999]).T,
00220             'old_elbowupr': np.matrix([-0.79,0,-1.6, -0.79,3.14, -0.79,5.49]).T,
00221             'old_elbowupl': np.matrix([0.79,0,1.6, -0.79,3.14, -0.79,5.49]).T,
00222             'elbowdownr':   np.matrix([-0.028262077316910873, 1.2946342642324222, -0.25785640577652386, -1.5498884526859626]).T, 
00223             'elbowdownl':   np.matrix([-0.0088195719039858515, 1.2834828245284853, 0.20338442004843196, -1.5565279256852611]).T
00224             }
00225 
00226     def set_posture(self, posture_mat):
00227         self.cart_posure_pub(stdm.Float64MultiArray(data=posture_mat.A1.tolist()))
00228 
00229     ##
00230     # Send a cartesian pose to *_cart controllers
00231     # @param trans len 3 list
00232     # @param rot len 3 list
00233     # @param frame string
00234     # @param msg_time float
00235     def set_cart_pose(self, trans, rot, frame, msg_time):
00236         ps = gm.PoseStamped()
00237         for i, field in enumerate(['x', 'y', 'z']):
00238             exec('ps.pose.position.%s = trans[%d]' % (field, i))
00239         for i, field in enumerate(['x', 'y', 'z', 'w']):
00240             exec('ps.pose.orientation.%s = rot[%d]' % (field, i))
00241         ps.header.frame_id = frame
00242         ps.header.stamp = rospy.Time(msg_time)
00243         self.cart_pose_pub(ps)
00244 
00245     ##
00246     # @param pos_mat column matrix of poses
00247     # @param times array of times
00248     def set_poses(self, pos_mat, times, vel_mat=None, block=True):
00249         p = self.pose()
00250         for i in range(pos_mat.shape[1]):
00251             pos_mat[4,i] = unwrap2(p[4,0], pos_mat[4,i])
00252             pos_mat[6,i] = unwrap2(p[6,0], pos_mat[6,i])
00253             p = pos_mat[:,i]
00254 
00255         joint_traj = Joint._create_trajectory(self, pos_mat, times, vel_mat)
00256 
00257         #Create goal msg
00258         joint_traj.header.stamp = rospy.get_rostime() + rospy.Duration(1.)
00259         g = pm.JointTrajectoryGoal()
00260         g.trajectory = joint_traj
00261         self.client.send_goal(g)
00262         if block:
00263             return self.client.wait_for_result()
00264         return self.client.get_state()
00265 
00266     def stop_trajectory_execution(self):
00267         self.client.cancel_all_goals()
00268 
00269     def has_active_goal(self):
00270         s = self.client.get_state()
00271         if s == amsg.GoalStatus.ACTIVE or s == amsg.GoalStatus.PENDING:
00272             return True
00273         else:
00274             return False
00275 
00276     def set_poses_monitored(self, pos_mat, times, vel_mat=None, block=True, time_look_ahead=.050):
00277         joint_traj = Joint._create_trajectory(self, pos_mat, times, vel_mat)
00278 
00279         #Create goal msg
00280         joint_traj.header.stamp = rospy.get_rostime() + rospy.Duration(1.)
00281         g = pm.JointTrajectoryGoal()
00282         g.trajectory = joint_traj
00283         self.client.send_goal(g)
00284         if block:
00285             return self.client.wait_for_result()
00286         return self.client.get_state()
00287 
00288     def set_pose(self, pos, nsecs=5., block=True):
00289         for i in range(2):
00290             cpos = self.pose()
00291         pos[4,0] = unwrap(cpos[4,0], pos[4,0])
00292         pos[6,0] = unwrap(cpos[6,0], pos[6,0])
00293         self.set_poses(np.column_stack([pos]), np.array([nsecs]), block=block)
00294         #self.set_poses(np.column_stack([cpos, pos]), np.array([min_time, min_time+nsecs]), block=block)
00295 
00296     def pose_cartesian(self, frame='base_link'):
00297         gripper_tool_frame = self.arm + '_gripper_tool_frame'
00298         return tfu.transform(frame, gripper_tool_frame, self.tf_listener)
00299 
00300     def pose_cartesian_tf(self, frame='base_link'):
00301         p, r = tfu.matrix_as_tf(self.pose_cartesian(frame))
00302         return np.matrix(p).T, np.matrix(r).T
00303 
00304 
00305 class PR2Torso(Joint):
00306 
00307     def __init__(self, joint_provider):
00308         Joint.__init__(self, 'torso_controller', joint_provider)
00309         self.torso = actionlib.SimpleActionClient('torso_controller/position_joint_action', pm.SingleJointPositionAction)
00310         rospy.loginfo('waiting for torso_controller')
00311         self.torso.wait_for_server()
00312 
00313     def set_pose(self, p, block=True):
00314         self.torso.send_goal(pm.SingleJointPositionGoal(position = p))
00315         if block:
00316             self.torso.wait_for_result()
00317         return self.torso.get_state()
00318 
00319 
00320 class PR2:
00321 
00322     def __init__(self, tf_listener):
00323         jl = GenericListener('joint_state_listener', sm.JointState, 'joint_states', 100)
00324         joint_provider = ft.partial(jl.read, allow_duplication=False, willing_to_wait=True, warn=False, quiet=True)
00325 
00326         self.left = PR2Arm(joint_provider, tf_listener, 'l', use_kinematics=False)
00327         self.right = PR2Arm(joint_provider, tf_listener, 'r', use_kinematics=False)
00328         self.torso = PR2Torso(joint_provider)


rcommander
Author(s): Hai Nguyen (haidai@gmail.com)
autogenerated on Thu Nov 28 2013 11:46:34