00001
00002
00003 import sys
00004 import numpy as np
00005
00006 import roslib
00007 roslib.load_manifest('hrl_pr2_arms')
00008 roslib.load_manifest('smach_ros')
00009 roslib.load_manifest('actionlib')
00010 import rospy
00011
00012 import smach
00013 from smach_ros import SimpleActionState, ServiceState, IntrospectionServer
00014 import actionlib
00015 import tf
00016 import tf.transformations as tf_trans
00017 from std_msgs.msg import Bool, Float32
00018 from std_srvs.srv import Empty
00019 from geometry_msgs.msg import PoseStamped, Vector3
00020 from actionlib_msgs.msg import GoalStatus
00021
00022
00023 from hrl_generic_arms.pose_converter import PoseConverter
00024 from hrl_pr2_arms.pr2_arm import create_pr2_arm
00025 from hrl_pr2_arms.pr2_arm_hybrid import PR2ArmHybridForce
00026
00027 class ClickMonitor(smach.State):
00028 def __init__(self):
00029 smach.State.__init__(self, outcomes=['click', 'shutdown'],
00030 output_keys=['click_pose'])
00031 self.cur_msg = None
00032 rospy.Subscriber('/pixel3d', PoseStamped, self.click_cb)
00033
00034 def click_cb(self, msg):
00035 self.cur_msg = msg
00036
00037 def execute(self, userdata):
00038 self.cur_msg = None
00039 while not rospy.is_shutdown():
00040 if self.cur_msg is not None:
00041 userdata.click_pose = self.cur_msg
00042 return 'click'
00043 rospy.sleep(0.01)
00044 return 'shutdown'
00045
00046 class TFPubLoop(object):
00047 def __init__(self, parent_frame_name, child_frame_name, rate=100):
00048 self.child_frame_name = child_frame_name
00049 self.parent_frame_name = parent_frame_name
00050 self.tf_broad = tf.TransformBroadcaster()
00051 self.timer = rospy.Timer(rospy.Duration(1. / rate), self.pub_tf)
00052 self.tf_pose = None
00053
00054 def pub_tf(self, timer_info):
00055 if self.tf_pose is not None:
00056 self.tf_broad.sendTransform(self.tf_pose[0], self.tf_pose[1], rospy.Time.now(),
00057 self.child_frame_name, self.parent_frame_name)
00058
00059 def update_pose(self, pose):
00060 self.tf_pose = PoseConverter.to_pos_quat(pose)
00061 self.pub_tf(None)
00062
00063 class SMTouchSimple(object):
00064 def __init__(self):
00065 self.tf_listener = tf.TransformListener()
00066 self.start_frame_pub = rospy.Publisher("~start_frame", PoseStamped)
00067 self.end_frame_pub = rospy.Publisher("~end_frame", PoseStamped)
00068
00069 self.arm = create_pr2_arm('l', PR2ArmHybridForce)
00070 self.tf_pub = TFPubLoop("/torso_lift_link", "/contact_control_frame")
00071
00072 def get_transform(self, from_frame, to_frame, time=None):
00073 if time is None:
00074 time = rospy.Time.now()
00075 try:
00076 self.tf_listener.waitForTransform(from_frame, to_frame, time, rospy.Duration(5))
00077 pos, quat = self.tf_listener.lookupTransform(from_frame, to_frame, time)
00078 return util.pose_pq_to_mat(pos, quat)
00079 except (tf.Exception, tf.LookupException, tf.ConnectivityException):
00080 return None
00081
00082 def get_trajectory_generator(self):
00083
00084 @smach.cb_interface(input_keys=['start_click', 'end_click'],
00085 output_keys=['start_traj_frame', 'end_traj_frame'],
00086 outcomes=['succeeded'])
00087 def generate_trajectory(ud):
00088 b_B_s = PoseConverter.to_homo_mat(ud.start_click)
00089 b_B_e = PoseConverter.to_homo_mat(ud.end_click)
00090 s_B_e = (b_B_s ** -1) * b_B_e
00091 b_normal = b_B_s[:3, 2] / np.linalg.norm(b_B_s[:3, 2])
00092 s_vel = np.mat([s_B_e[0, 3], s_B_e[1, 3], 0]).T
00093 s_vel = s_vel / np.linalg.norm(s_vel)
00094 b_vel = b_B_s[:3, :3].T * s_vel
00095 b_ortho = np.mat(np.cross(b_normal.T, b_vel.T)).T
00096 b_ortho = b_ortho / np.linalg.norm(b_ortho)
00097 b_R_traj = np.vstack([b_vel.T, b_ortho.T, b_normal.T])
00098
00099 b_p_start = b_B_s[:3, 3]
00100 b_p_end = b_B_e[:3, 3]
00101 b_p_end = 3
00102
00103 self.start_frame_pub.publish(PoseConverter.to_pose_stamped_msg(ud.start_click.header.frame_id,
00104 (b_p_start, b_R_traj)))
00105 self.end_frame_pub.publish(PoseConverter.to_pose_stamped_msg(ud.start_click.header.frame_id,
00106 (b_p_end, b_R_traj)))
00107
00108
00109 ud.start_traj_frame = (b_p_start, b_R_traj)
00110 ud.end_traj_frame = (b_p_end, b_R_traj)
00111 return 'succeeded'
00112
00113 return smach.CBState(generate_trajectory)
00114
00115
00116 def get_sm(self):
00117 sm = smach.StateMachine(outcomes=['succeeded','preempted','shutdown'])
00118
00119 with sm:
00120 smach.StateMachine.add(
00121 'INPUT_START_CLICK',
00122 ClickMonitor(),
00123 transitions={'click' : 'INPUT_END_CLICK',
00124 'shutdown' : 'shutdown'},
00125 remapping={'click_pose' : 'start_click'})
00126
00127 smach.StateMachine.add(
00128 'INPUT_END_CLICK',
00129 ClickMonitor(),
00130 transitions={'click' : 'GENERATE_TRAJECTORY',
00131 'shutdown' : 'shutdown'},
00132 remapping={'click_pose' : 'end_click'})
00133
00134 smach.StateMachine.add(
00135 'GENERATE_TRAJECTORY',
00136 self.get_trajectory_generator(),
00137 transitions={'succeeded' : 'INPUT_START_CLICK'})
00138
00139 return sm
00140
00141 def get_sm_basic(self):
00142 sm = smach.StateMachine(outcomes=['succeeded','preempted','shutdown'])
00143
00144 with sm:
00145 smach.StateMachine.add(
00146 'INPUT_START_CLICK',
00147 ClickMonitor(),
00148 transitions={'click' : 'PUBLISH_CONTROL_FRAME',
00149 'shutdown' : 'shutdown'},
00150 remapping={'click_pose' : 'start_click'})
00151
00152 @smach.cb_interface(input_keys=['start_click'],
00153 outcomes=['succeeded', 'failed'])
00154 def publish_control_frame(ud):
00155 if ud.start_click.pose.position.x == -10000.0:
00156 return 'failed'
00157 pose = ud.start_click
00158 pose.header.stamp = rospy.Time(0)
00159 click_torso = self.tf_listener.transformPose("/torso_lift_link", pose)
00160 self.tf_pub.update_pose(click_torso)
00161 rospy.sleep(1)
00162 self.arm.set_tip_frame("/contact_control_frame")
00163
00164 self.arm.update_gains()
00165 return 'succeeded'
00166 smach.StateMachine.add(
00167 'PUBLISH_CONTROL_FRAME',
00168 smach.CBState(publish_control_frame),
00169 transitions={'succeeded' : 'INPUT_START_CLICK',
00170 'failed' : 'INPUT_START_CLICK'})
00171
00172 return sm
00173
00174
00175 def main():
00176 rospy.init_node('pr2_touch_simple')
00177 smts = SMTouchSimple()
00178 sm = smts.get_sm_basic()
00179 rospy.sleep(1)
00180
00181 sis = IntrospectionServer('touch_simple', sm, '/INPUT_START_CLICK')
00182 sis.start()
00183
00184 outcome = sm.execute()
00185
00186 sis.stop()
00187
00188 if __name__ == '__main__':
00189 main()