ptp_arm_action_server.py
Go to the documentation of this file.
00001 #! /usr/bin/python
00002 import roslib; roslib.load_manifest('ptp_arm_action')
00003 import rospy
00004 import actionlib
00005 
00006 import geometry_msgs.msg as gm
00007 import ptp_arm_action.msg as ptp
00008 
00009 from object_manipulator.convert_functions import *
00010 from math import sqrt, pi, fabs
00011 import tf_utils as tfu
00012 import numpy as np
00013 #import scipy
00014 import math
00015 import tf.transformations as tr
00016 import tf
00017 from pycontroller_manager.pycontroller_manager import ControllerManager
00018 import object_manipulator.convert_functions as cf
00019 
00020 ##
00021 # Measures the distance between two pose stamps, independently factors out
00022 # distance in rotation and distance in translation. Converts both poses into
00023 # the same coordinate frame before comparison.
00024 def pose_distance(ps_a, ps_b, tflistener):
00025     #put both into the same frame
00026     ps_a_fb = change_pose_stamped_frame(tflistener, ps_a, ps_b.header.frame_id)
00027     g_T_a = pose_to_mat(ps_a_fb.pose)
00028     g_T_b = pose_to_mat(ps_b.pose)
00029 
00030     a_T_b = g_T_a**-1 * g_T_b
00031 
00032     desired_trans = a_T_b[0:3, 3].copy()
00033     a_T_b[0:3, 3] = 0
00034     desired_angle, desired_axis, _ = tf.transformations.rotation_from_matrix(a_T_b)
00035     return desired_trans, desired_angle, desired_axis
00036 
00037 def tf_as_matrix(tup):
00038     return np.matrix(tr.translation_matrix(tup[0])) * np.matrix(tr.quaternion_matrix(tup[1])) 
00039 
00040 
00041 class PTPArmActionServer:
00042 
00043     def __init__(self, name, arm):
00044         if arm == 'left':
00045             self.controller = 'l_cart'
00046             #self.joint_controller = 'l_arm_controller'
00047             self.controller_frame = rospy.get_param('/l_cart/tip_name')
00048             #self.tool_frame = rospy.get_param('/l_cart/tip_name')
00049             self.tool_frame = 'l_gripper_tool_frame'
00050         elif arm == 'right':
00051             self.controller = 'r_cart'
00052             #self.joint_controller = 'r_arm_controller'
00053             self.controller_frame = rospy.get_param('/r_cart/tip_name')
00054             #self.tool_frame = rospy.get_param('/r_cart/tip_name')
00055             self.tool_frame = 'r_gripper_tool_frame'
00056         else:
00057             raise RuntimeError('Invalid parameter for arm: %s' % arm)
00058 
00059         self.arm = arm
00060         self.target_pub = rospy.Publisher(self.controller + '/command_pose', gm.PoseStamped)
00061         #self.pose_sub = rospy.Subscriber(self.controller + '/state/x', gm.PoseStamped, self.pose_callback)
00062 
00063         self.tf = tf.TransformListener()
00064         self.trans_tolerance = rospy.get_param("~translation_tolerance")
00065         self.rot_tolerance = math.radians(rospy.get_param("~rotation_tolerance"))
00066         self.stall_time = rospy.get_param("~stall_time")
00067         #rospy.loginfo('trans tolerance ' + str(self.trans_tolerance))
00068         self.time_out = rospy.get_param("~timeout")
00069 
00070         self.controller_manager = ControllerManager()
00071         #self.controller_manager.cart_mode(self.arm)
00072         self._action_name = name
00073         self.linear_movement_as = actionlib.SimpleActionServer(self._action_name, ptp.LinearMovementAction, 
00074                                         execute_cb=self.action_cb, auto_start=False)
00075         self.linear_movement_as.start()
00076 
00077         rospy.loginfo('Action name: %s Arm: %s' % (self._action_name, self.arm))
00078 
00079 
00080     def action_cb(self, msg):
00081         rospy.loginfo('message that we got:\n' + str(msg))
00082         self.controller_manager.cart_mode(self.arm)
00083         #self._wait_for_pose_message()
00084         self.trans_tolerance = rospy.get_param("~translation_tolerance")
00085         self.rot_tolerance = math.radians(rospy.get_param("~rotation_tolerance"))
00086         self.time_out = rospy.get_param("~timeout")
00087 
00088         success = False
00089         r = rospy.Rate(100)
00090 
00091         goal_ps = msg.goal
00092         #relative_movement = msg.relative
00093         trans_vel = msg.trans_vel
00094         rot_vel = msg.rot_vel
00095         if trans_vel <= 0:
00096             trans_vel = .02
00097         if rot_vel <= 0:
00098             rot_vel = pi/20.
00099 
00100         tstart = rospy.get_time()
00101         tmax = tstart + self.time_out
00102         self.controller_manager = ControllerManager()
00103         rospy.loginfo('Goal is x %f y %f z %f in %s' % (goal_ps.pose.position.x, goal_ps.pose.position.y, 
00104             goal_ps.pose.position.z, goal_ps.header.frame_id))
00105 
00106         goal_torso = change_pose_stamped_frame(self.tf, goal_ps, 'torso_lift_link')
00107         rospy.loginfo('BEFORE TIP Goal is x %f y %f z %f in %s' % (goal_torso.pose.position.x, goal_torso.pose.position.y, 
00108             goal_torso.pose.position.z, goal_torso.header.frame_id))
00109 
00110         rospy.loginfo('Tool Frame %s Controller Frame %s' % (self.tool_frame, self.controller_frame))
00111 
00112         tll_T_tip = pose_to_mat(goal_torso.pose)
00113         tip_T_w = tf_as_matrix(self.tf.lookupTransform(self.tool_frame, self.controller_frame,  rospy.Time(0)))
00114         #print 'TRANSFORM', tip_T_w
00115         tll_T_w = tll_T_tip * tip_T_w
00116         goal_torso = stamp_pose(mat_to_pose(tll_T_w), 'torso_lift_link')
00117 
00118         rospy.loginfo('AFTER TIP Goal is x %f y %f z %f in %s' % (goal_torso.pose.position.x, goal_torso.pose.position.y, 
00119             goal_torso.pose.position.z, goal_torso.header.frame_id))
00120 
00121         verbose = False
00122         time_ang = None
00123         min_ang_error = None
00124         time_trans = None
00125         min_trans_error = None
00126 
00127         while True:
00128             cur_time = rospy.get_time()
00129 
00130             gripper_matrix = tfu.tf_as_matrix(self.tf.lookupTransform('torso_lift_link', self.controller_frame, rospy.Time(0)))
00131             gripper_ps = stamp_pose(mat_to_pose(gripper_matrix), 'torso_lift_link')
00132             #Someone preempted us!
00133             if self.linear_movement_as.is_preempt_requested():
00134                 #Stop our motion
00135                 self.target_pub.publish(stamp_pose(gripper_ps.pose, gripper_ps.header.frame_id))
00136                 self.linear_movement_as.set_preempted()
00137                 rospy.loginfo('action_cb: preempted!')
00138                 break
00139 
00140             #Calc feedback
00141             if verbose:
00142                 print 'current_pose %.3f %.3f %.3f, rot %.3f %.3f %.3f %.3f in %s' % (gripper_ps.pose.position.x, gripper_ps.pose.position.y, gripper_ps.pose.position.z, 
00143                         gripper_ps.pose.orientation.x, gripper_ps.pose.orientation.y, gripper_ps.pose.orientation.z, 
00144                         gripper_ps.pose.orientation.w, gripper_ps.header.frame_id)
00145                 print 'goal_pose %.3f %.3f %.3f, rot %.3f %.3f %.3f %.3f in %s' % (goal_torso.pose.position.x, goal_torso.pose.position.y, goal_torso.pose.position.z, 
00146                         goal_torso.pose.orientation.x, goal_torso.pose.orientation.y, goal_torso.pose.orientation.z, 
00147                         goal_torso.pose.orientation.w, goal_torso.header.frame_id)
00148 
00149             trans, ang, _ = pose_distance(gripper_ps, goal_torso, self.tf)
00150             feedback = ptp.LinearMovementFeedback(gm.Vector3(trans[0,0], trans[1,0], trans[2,0]))
00151             self.linear_movement_as.publish_feedback(feedback)
00152 
00153             #Reached goal
00154             trans_mag = np.linalg.norm(trans)
00155             if verbose:
00156                 print trans.T, 'trans_mag', trans_mag, 'ang', abs(ang), 'rot toler', self.rot_tolerance
00157 
00158             if min_trans_error == None or min_trans_error == None:
00159                 min_trans_error = trans_mag
00160                 min_ang_error = abs(ang)
00161                 time_ang = cur_time
00162                 time_trans = cur_time
00163 
00164             if trans_mag < min_trans_error:
00165                 min_trans_error = trans_mag
00166                 time_trans = cur_time
00167 
00168             if abs(ang) < min_ang_error:
00169                 min_ang_error = abs(ang)
00170                 time_ang = cur_time
00171 
00172             if self.trans_tolerance > trans_mag and self.rot_tolerance > abs(ang):
00173                 rospy.loginfo('action_cb: reached goal.')
00174                 break
00175 
00176             #Timed out! is this a failure?
00177             if cur_time > tmax:
00178                 rospy.loginfo('action_cb: timed out.')
00179                 break
00180 
00181             #if it has been a while since we made progress
00182             if trans_mag > min_trans_error and (cur_time - time_trans) > self.stall_time:
00183                 rospy.loginfo('action_cb: stalled.')
00184                 break
00185 
00186             # tends to not stall on angle so don't look out for this case
00187             #if abs(ang) > min_ang_error and (cur_time - time_ang) > self.stall_time:
00188             #    rospy.loginfo('action_cb: stalled.')
00189             #    break
00190 
00191             #Send controls
00192             clamped_target = self.clamp_pose(goal_torso, trans_vel, rot_vel, ref_pose=gripper_ps)
00193             if verbose:
00194                 print 'clamped_target', clamped_target.pose.position.x, clamped_target.pose.position.y, 
00195                 print clamped_target.pose.position.z, clamped_target.header.frame_id, '\n'
00196 
00197             #break
00198             self.target_pub.publish(clamped_target)
00199             #break
00200 
00201         trans, ang, _ = pose_distance(gripper_ps, goal_torso, self.tf)
00202         result = ptp.LinearMovementResult(gm.Vector3(trans[0,0], trans[1,0], trans[2,0]))
00203         if self.trans_tolerance > np.linalg.norm(trans):
00204             rospy.loginfo( 'SUCCEEDED! %.3f ang %.3f' % (np.linalg.norm(trans), np.degrees(ang)))
00205             self.linear_movement_as.set_succeeded(result)
00206         else:
00207             rospy.loginfo('ABORTED! %.3f ang %.3f' % (np.linalg.norm(trans), np.degrees(ang)))
00208             self.linear_movement_as.set_aborted(result)
00209 
00210     
00211     def clamp_pose(self, desired_pose, max_trans, max_rot, ref_pose):
00212         current_pose_d = change_pose_stamped_frame(self.tf, ref_pose, desired_pose.header.frame_id) 
00213         g_T_c  = pose_to_mat(current_pose_d.pose)
00214             
00215         desired_trans, desired_angle, desired_axis = pose_distance(ref_pose, desired_pose, self.tf)
00216         desired_trans_mag = np.linalg.norm(desired_trans)
00217         frac_trans = fabs(desired_trans_mag / max_trans)
00218         frac_rot = fabs(desired_angle / max_rot)
00219 
00220         if frac_trans <= 1 and frac_rot <= 1:
00221             return desired_pose
00222         frac = max(frac_rot, frac_trans)
00223 
00224         clamped_angle = desired_angle / frac
00225         clamped_trans = desired_trans / frac
00226 
00227 
00228         c_T_d = np.matrix(tf.transformations.rotation_matrix(clamped_angle, desired_axis))
00229         c_T_d[0:3, 3] = clamped_trans
00230         g_T_d = g_T_c * c_T_d
00231         clamped_pose = stamp_pose(mat_to_pose(g_T_d), desired_pose.header.frame_id)
00232         clamped_pose.header.stamp = rospy.Time.now()
00233         return clamped_pose
00234 
00235 if __name__ == '__main__':
00236     import sys
00237 
00238     if len(sys.argv) < 2:
00239         arm = 'left'
00240     else:
00241         arm = sys.argv[1]
00242 
00243     rospy.init_node('ptp')
00244     left_as = PTPArmActionServer(arm +'_ptp', arm)
00245     rospy.loginfo('PTP action server started.')
00246     rospy.spin()
00247 
00248 
00249         #if relative_movement:
00250         #    rospy.loginfo('Received relative motion.')
00251 
00252         #    #print 'tool frame is', self.tool_frame
00253         #    #print 'goal frame is', goal_ps.header.frame_id
00254 
00255         #    delta_ref  = pose_to_mat(goal_ps.pose)
00256         #    tll_R_ref = tfu.tf_as_matrix(self.tf.lookupTransform('torso_lift_link', goal_ps.header.frame_id, rospy.Time(0)))
00257         #    tll_R_ref[0:3,3] = 0
00258         #    delta_tll = tll_R_ref * delta_ref
00259 
00260         #    #print 'delta_tll\n', delta_tll
00261         #    tip_current_T_tll = tfu.tf_as_matrix(self.tf.lookupTransform('torso_lift_link', self.tool_frame, rospy.Time(0)))
00262         #    #print 'tip_current_T_tll\n', tip_current_T_tll
00263 
00264         #    #Find translation
00265         #    delta_T = delta_tll.copy()
00266         #    delta_T[0:3,0:3] = np.eye(3)
00267         #    tip_T = delta_T * tip_current_T_tll
00268 
00269         #    #Find rotation
00270         #    tip_R = delta_tll[0:3, 0:3] * tip_current_T_tll[0:3, 0:3]
00271 
00272 
00273         #    tip_new = np.matrix(np.eye(4))
00274         #    tip_new[0:3, 0:3] = tip_R
00275         #    tip_new[0:3, 3] = tip_T[0:3,3]
00276 
00277         #    #print 'tip_new\n', tip_new
00278         #    goal_ps = stamp_pose(mat_to_pose(tip_new), 'torso_lift_link')
00279 


ptp_arm_action
Author(s): Hai Nguyen
autogenerated on Thu Dec 12 2013 12:09:47