sm_pr2_servoing.py
Go to the documentation of this file.
00001 #!/usr/bin/python
00002 
00003 import numpy as np
00004 import functools
00005 
00006 import roslib
00007 roslib.load_manifest('hrl_pr2_ar_servo')
00008 roslib.load_manifest('smach_ros')
00009 #roslib.load_manifest('costmap_services')
00010 import rospy
00011 import smach
00012 import smach_ros
00013 from std_msgs.msg import Bool, Int8
00014 
00015 from pykdl_utils.joint_kinematics import create_joint_kin
00016 #from costmap_services.python_client import CostmapServices
00017 from pr2_ar_servo import PR2ARServo
00018 
00019 outcomes_spa = ['succeeded','preempted','aborted']
00020 
00021 class ServoStates:
00022     BEGIN_FIND_TAG = 1
00023     FOUND_TAG = 2
00024     TIMEOUT_FIND_TAG = 3
00025     BEGIN_SERVO = 4
00026     SUCCESS_SERVO = 5
00027     ARM_COLLISION = 6
00028     LASER_COLLISION = 7
00029     LOST_TAG = 8
00030     USER_PREEMPT = 9
00031 
00032 class ArmCollisionDetection(smach.State):
00033     def __init__(self, min_l_torques=[-5.]*7, min_r_torques=[-5.]*7,
00034                        max_l_torques=[5.]*7, max_r_torques=[5.]*7):
00035         smach.State.__init__(self, outcomes=['collision', 'preempted', 'aborted'])
00036         self.min_l_tor = np.array(min_l_torques)
00037         self.min_r_tor = np.array(min_r_torques)
00038         self.max_l_tor = np.array(max_l_torques)
00039         self.max_r_tor = np.array(max_r_torques)
00040         self.l_arm = create_joint_kin('torso_lift_link', 'l_gripper_tool_frame')
00041         self.r_arm = create_joint_kin('torso_lift_link', 'r_gripper_tool_frame')
00042 
00043     def execute(self, userdata):
00044         r = rospy.Rate(20)
00045         while not rospy.is_shutdown():
00046             l_tor = self.l_arm.get_joint_efforts()
00047             r_tor = self.r_arm.get_joint_efforts()
00048             if np.any(l_tor < self.min_l_tor):
00049                 print "Collision detected on left arm with torque:", l_tor
00050                 print "Minimum torques:", self.min_l_tor
00051                 return 'collision'
00052             if np.any(l_tor > self.max_l_tor):
00053                 print "Collision detected on left arm with torque:", l_tor
00054                 print "Maximum torques:", self.max_l_tor
00055                 return 'collision'
00056             if np.any(r_tor < self.min_r_tor):
00057                 print "Collision detected on right arm with torque:", r_tor
00058                 print "Minimum torques:", self.min_r_tor
00059                 return 'collision'
00060             if np.any(r_tor > self.max_r_tor):
00061                 print "Collision detected on right arm with torque:", r_tor
00062                 print "Minimum torques:", self.max_r_tor
00063                 return 'collision'
00064                 
00065             if self.preempt_requested():
00066                 self.service_preempt()
00067                 return 'preempted'
00068             r.sleep()
00069         return 'aborted'
00070 
00071 #class LaserCollisionDetection(smach.State):
00072 #    def __init__(self):
00073 #        smach.State.__init__(self, outcomes=['collision', 'preempted', 'aborted'])
00074 #        self.cs = CostmapServices(accum=3)
00075 #
00076 #    def execute(self, userdata):
00077 #        r = rospy.Rate(20)
00078 #        while not rospy.is_shutdown():
00079 #            vx, vy, vtheta = 0., 0., 0. #TODO REMOVE
00080 #            score = self.cs.scoreTraj_PosHyst(vx, vy, vtheta) # TODO
00081 #            if score < 0:
00082 #                print "Base laser detected a collision."
00083 #                return 'collision'
00084 #            if self.preempt_requested():
00085 #                self.service_preempt()
00086 #                return 'preempted'
00087 #            r.sleep()
00088 #        return 'aborted'
00089 
00090 def build_cc_servoing(viz_servos):
00091     def term_cb(outcome_map):
00092         return True
00093     def out_cb(outcome_map):
00094         if outcome_map['ARM_COLLISION_DETECTION'] == 'collision':
00095             return 'arm_collision'
00096         #if outcome_map['LASER_COLLISION_DETECTION'] == 'collision':
00097         #    return 'laser_collision'
00098         if outcome_map['USER_PREEMPT_DETECTION'] == 'true':
00099             return 'user_preempted'
00100         if outcome_map['USER_PREEMPT_DETECTION'] == 'false':
00101             return 'aborted'
00102         return outcome_map['SERVOING']
00103 
00104     cc_servoing = smach.Concurrence(
00105                             outcomes=outcomes_spa+
00106                             ['arm_collision', 'laser_collision', 'lost_tag', 'user_preempted'],
00107                             input_keys=['goal_ar_pose', 'initial_ar_pose', 'servo_topic'],
00108                             default_outcome='aborted',
00109                             child_termination_cb=term_cb,
00110                             outcome_cb=out_cb)
00111     
00112     with cc_servoing:
00113         smach.Concurrence.add('SERVOING',
00114                               ServoARTagState(viz_servos))
00115 
00116         smach.Concurrence.add('ARM_COLLISION_DETECTION',
00117                               ArmCollisionDetection())
00118 
00119         #smach.Concurrence.add('LASER_COLLISION_DETECTION',
00120         #                      LaserCollisionDetection())
00121 
00122         smach.Concurrence.add('USER_PREEMPT_DETECTION',
00123                               BoolTopicState("/pr2_ar_servo/preempt"))
00124                               
00125     return cc_servoing
00126 
00127 class BoolTopicState(smach.State):
00128     def __init__(self, topic, rate=20):
00129         smach.State.__init__(self, outcomes=['true', 'false', 'preempted', 'aborted'])
00130         self.rate = rate
00131         self.ui_list = rospy.Subscriber(topic, Bool, self.ui_cb)
00132     
00133     def ui_cb(self, msg):
00134         self.bool_msg = msg.data
00135         self.got_msg = True
00136 
00137     def execute(self, userdata):
00138         self.got_msg = False
00139         r = rospy.Rate(self.rate)
00140         while not rospy.is_shutdown():
00141             if self.got_msg:
00142                 if self.bool_msg:
00143                     return 'true'
00144                 else:
00145                     return 'false'
00146             if self.preempt_requested():
00147                 self.service_preempt()
00148                 return 'preempted'
00149             r.sleep()
00150         return 'aborted'
00151 
00152 class PublishState(smach.State):
00153     def __init__(self, topic, msg_type, msg):
00154         smach.State.__init__(self, outcomes=['succeeded'])
00155         self.pub = rospy.Publisher(topic, msg_type)
00156         self.msg = msg
00157 
00158     def execute(self, userdata):
00159         self.pub.publish(self.msg)
00160         return 'succeeded'
00161 
00162 class FindARTagState(smach.State):
00163     def __init__(self, viz_servos, viz_servo_goals, timeout=6.):
00164         smach.State.__init__(self, 
00165                              outcomes=['found_tag', 'timeout', 'preempted', 'aborted'],
00166                              output_keys=['initial_ar_pose', 'goal_ar_pose', 'servo_topic'])
00167         self.viz_servos = viz_servos
00168         self.viz_servo_goals = viz_servo_goals
00169         self.timeout = timeout
00170 
00171     def execute(self, userdata):
00172         # This is just a mess.
00173         # Figure this out and rewrite it...
00174         self.service_preempt()
00175 
00176         self.outcome_dict = {}
00177         def call_find_ar_tag(te, viz_servo, fart_state, topic):
00178             mean_ar, outcome = viz_servo.find_ar_tag(self.timeout)
00179             fart_state.outcome_dict[topic] = (mean_ar, outcome)
00180             if outcome == "found_tag":
00181                 fart_state.request_preempt()
00182         for topic in self.viz_servos:
00183             call_find_ar_tag_filled = functools.partial(call_find_ar_tag, 
00184                                                         viz_servo=self.viz_servos[topic],
00185                                                         fart_state=self,
00186                                                         topic=topic)
00187             rospy.Timer(rospy.Duration(0.01), call_find_ar_tag_filled, oneshot=True)
00188         while not rospy.is_shutdown():
00189             if self.preempt_requested() or len(self.outcome_dict) == len(self.viz_servos):
00190                 break
00191             rospy.sleep(0.05)
00192         outcome = "timeout"
00193         for topic in self.outcome_dict:
00194             if self.outcome_dict[topic][1] == "found_tag":
00195                 userdata['initial_ar_pose'] = self.outcome_dict[topic][0]
00196                 userdata['goal_ar_pose'] = self.viz_servo_goals[topic]
00197                 userdata['servo_topic'] = topic
00198                 outcome = "found_tag"
00199                 # FIXME I should be shot for these lines: FIXME
00200                 if topic == "r_pr2_ar_pose_marker":
00201                     rospy.set_param("/shaving_side", 'r')
00202                 else:
00203                     rospy.set_param("/shaving_side", 'l')
00204                 ##################################################
00205                 break
00206             
00207         return outcome
00208 
00209 class ServoARTagState(smach.State):
00210     def __init__(self, viz_servos):
00211         smach.State.__init__(self, 
00212                              outcomes=['lost_tag'] + outcomes_spa,
00213                              input_keys=['goal_ar_pose', 'initial_ar_pose', 'servo_topic'])
00214         self.viz_servos = viz_servos
00215 
00216     def execute(self, userdata):
00217         if 'initial_ar_pose' in userdata:
00218             initial_ar_pose = userdata.initial_ar_pose
00219         else:
00220             rospy.logerr("Initial AR pose should be in userdata")
00221             initial_ar_pose = None
00222 
00223         servo_topic = userdata['servo_topic']
00224         def check_preempt(event):
00225             if self.preempt_requested():
00226                 self.service_preempt()
00227                 self.viz_servos[servo_topic].request_preempt()
00228                 
00229         preempt_timer = rospy.Timer(rospy.Duration(0.1), check_preempt)
00230         self.viz_servos[servo_topic].preempt_requested = False
00231         outcome = self.viz_servos[servo_topic].servo_to_tag(pose_goal=userdata.goal_ar_pose,
00232                                                             initial_ar_pose=initial_ar_pose)
00233         preempt_timer.shutdown()
00234         return outcome
00235 
00236 def build_full_sm(viz_servo_goals):
00237     find_tag_timeout = 6.
00238 
00239     viz_servos = {}
00240     for viz_servo_topic in viz_servo_goals:
00241         viz_servos[viz_servo_topic] = PR2ARServo(viz_servo_topic)
00242 
00243     sm_pr2_servoing = smach.StateMachine(outcomes=outcomes_spa,
00244                                          input_keys=['goal_ar_pose', 'initial_ar_pose'])
00245     with sm_pr2_servoing:
00246 
00247         smach.StateMachine.add('UI_FIND_TAG_WAIT',
00248                                BoolTopicState("/pr2_ar_servo/find_tag"),
00249                                transitions={'true' : 'BEGIN_FIND_TAG',
00250                                             'false' : 'aborted'})
00251 
00252         smach.StateMachine.add('BEGIN_FIND_TAG',
00253                                PublishState("/pr2_ar_servo/state_feedback",
00254                                             Int8, Int8(ServoStates.BEGIN_FIND_TAG)),
00255                                transitions={'succeeded' : 'FIND_AR_TAG'})
00256 
00257         smach.StateMachine.add('FIND_AR_TAG',
00258                                FindARTagState(viz_servos, viz_servo_goals, timeout=find_tag_timeout),
00259                                transitions={'found_tag' : 'FOUND_TAG',
00260                                             'timeout' : 'TIMEOUT_FIND_TAG'})
00261 
00262         smach.StateMachine.add('FOUND_TAG',
00263                                PublishState("/pr2_ar_servo/state_feedback",
00264                                             Int8, Int8(ServoStates.FOUND_TAG)),
00265                                transitions={'succeeded' : 'UI_SERVO_WAIT'})
00266 
00267         smach.StateMachine.add('TIMEOUT_FIND_TAG',
00268                                PublishState("/pr2_ar_servo/state_feedback",
00269                                             Int8, Int8(ServoStates.TIMEOUT_FIND_TAG)),
00270                                transitions={'succeeded' : 'UI_FIND_TAG_WAIT'})
00271 
00272         smach.StateMachine.add('UI_SERVO_WAIT',
00273                                BoolTopicState("/pr2_ar_servo/tag_confirm"),
00274                                transitions={'true' : 'BEGIN_SERVO',
00275                                             'false' : 'UI_FIND_TAG_WAIT'})
00276 
00277         smach.StateMachine.add('BEGIN_SERVO',
00278                                PublishState("/pr2_ar_servo/state_feedback",
00279                                             Int8, Int8(ServoStates.BEGIN_SERVO)),
00280                                transitions={'succeeded' : 'CC_SERVOING'})
00281 
00282         smach.StateMachine.add('CC_SERVOING', 
00283                                build_cc_servoing(viz_servos),
00284                                transitions={'arm_collision' : 'ARM_COLLISION',
00285                                             'laser_collision' : 'LASER_COLLISION',
00286                                             'user_preempted' : 'USER_PREEMPT',
00287                                             'lost_tag' : 'LOST_TAG',
00288                                             'succeeded' : 'SUCCESS_SERVO'})
00289 
00290         smach.StateMachine.add('SUCCESS_SERVO',
00291                                PublishState("/pr2_ar_servo/state_feedback",
00292                                             Int8, Int8(ServoStates.SUCCESS_SERVO)),
00293                                transitions={'succeeded' : 'UI_FIND_TAG_WAIT'})
00294 
00295         smach.StateMachine.add('ARM_COLLISION',
00296                                PublishState("/pr2_ar_servo/state_feedback",
00297                                             Int8, Int8(ServoStates.ARM_COLLISION)),
00298                                transitions={'succeeded' : 'UI_FIND_TAG_WAIT'})
00299 
00300         smach.StateMachine.add('LASER_COLLISION',
00301                                PublishState("/pr2_ar_servo/state_feedback",
00302                                             Int8, Int8(ServoStates.LASER_COLLISION)),
00303                                transitions={'succeeded' : 'UI_FIND_TAG_WAIT'})
00304 
00305         smach.StateMachine.add('LOST_TAG',
00306                                PublishState("/pr2_ar_servo/state_feedback",
00307                                             Int8, Int8(ServoStates.LOST_TAG)),
00308                                transitions={'succeeded' : 'UI_FIND_TAG_WAIT'})
00309 
00310         smach.StateMachine.add('USER_PREEMPT',
00311                                PublishState("/pr2_ar_servo/state_feedback",
00312                                             Int8, Int8(ServoStates.USER_PREEMPT)),
00313                                transitions={'succeeded' : 'UI_FIND_TAG_WAIT'})
00314 
00315     return sm_pr2_servoing
00316 
00317 def build_test_sm():
00318     viz_servo = PR2ARServo("r_pr2_ar_pose_marker")
00319     
00320     sm_only_servo = smach.StateMachine(outcomes=['lost_tag'] + outcomes_spa,
00321                                        input_keys=['goal_ar_pose', 'initial_ar_pose'])
00322     with sm_only_servo:
00323         smach.StateMachine.add('ONLY_SERVO',
00324                                ServoARTagState(viz_servo))
00325     return sm_only_servo
00326 
00327 def main():
00328     rospy.init_node("sm_pr2_servoing")
00329     userdata = smach.user_data.UserData()
00330 
00331     # old testing
00332     #userdata['goal_ar_pose'] = [ 0.57160106, -0.4300153 , -1.70840111]
00333 
00334     # both sides spot?
00335     userdata['goal_ar_pose'] = [ 0.57226345,  0.32838129, -1.15480113]
00336     viz_servo_goals = rospy.get_param("~ar_servo_poses", {})
00337     print viz_servo_goals
00338 
00339     if True:
00340         sm_pr2_servoing = build_full_sm(viz_servo_goals)
00341         sis = smach_ros.IntrospectionServer('pr2_servo', sm_pr2_servoing, 'UI_FIND_TAG_WAIT')
00342         sis.start()
00343         sm_pr2_servoing.execute(userdata)
00344         sis.stop()
00345     else:
00346         sm_test = build_test_sm()
00347         rospy.sleep(4)
00348         sm_test.execute(userdata)
00349 
00350 if __name__ == "__main__":
00351     main()


hrl_pr2_ar_servo
Author(s): Kelsey Hawkins, Advisor: Prof. Charlie Kemp, Lab: Healthcare Robotics Lab
autogenerated on Wed Nov 27 2013 11:43:43