00001
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
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
00022
00023
00024 def pose_distance(ps_a, ps_b, tflistener):
00025
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
00047 self.controller_frame = rospy.get_param('/l_cart/tip_name')
00048
00049 self.tool_frame = 'l_gripper_tool_frame'
00050 elif arm == 'right':
00051 self.controller = 'r_cart'
00052
00053 self.controller_frame = rospy.get_param('/r_cart/tip_name')
00054
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
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
00068 self.time_out = rospy.get_param("~timeout")
00069
00070 self.controller_manager = ControllerManager()
00071
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
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
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
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
00133 if self.linear_movement_as.is_preempt_requested():
00134
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
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
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
00177 if cur_time > tmax:
00178 rospy.loginfo('action_cb: timed out.')
00179 break
00180
00181
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
00187
00188
00189
00190
00191
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
00198 self.target_pub.publish(clamped_target)
00199
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
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279