00001
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
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
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
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
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
00097
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
00120
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
00173
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
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
00332
00333
00334
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()