00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 import roslib
00035 roslib.load_manifest('pr2_plugs_actions')
00036
00037 import rospy
00038
00039 import threading
00040
00041 import actionlib
00042 import PyKDL
00043
00044 from pr2_plugs_msgs.msg import *
00045 from pr2_plugs_msgs.srv import *
00046 from actionlib_msgs.msg import *
00047 from move_base_msgs.msg import *
00048 from geometry_msgs.msg import *
00049 from pr2_controllers_msgs.msg import *
00050 from pr2_common_action_msgs.msg import *
00051
00052 from std_srvs.srv import *
00053
00054 from tf_conversions.posemath import fromMsg, toMsg
00055 from pr2_arm_move_ik.tools import *
00056
00057
00058 import smach
00059 from smach import *
00060 from smach_ros import *
00061
00062 from detect_outlet import construct_sm as construct_detect_outlet_sm
00063 from fetch_plug import construct_sm as construct_fetch_plug_sm
00064 from plug_in import construct_sm as construct_plug_in_sm
00065
00066 from pr2_plugs_actions.tf_util import TFUtil
00067
00068 def main():
00069 rospy.init_node("recharge_toplevel")
00070 TFUtil()
00071
00072
00073 close_gripper_goal = Pr2GripperCommandGoal()
00074 close_gripper_goal.command.position = 0.0
00075 close_gripper_goal.command.max_effort = 99999
00076
00077 open_gripper_goal = Pr2GripperCommandGoal()
00078 open_gripper_goal.command.position = 0.07
00079 open_gripper_goal.command.max_effort = 99999
00080
00081
00082 recharge_sm = StateMachine(
00083 outcomes=['plugged_in','unplugged','aborted','preempted'],
00084 input_keys = ['recharge_command'],
00085 output_keys = ['recharge_state'])
00086
00087
00088 recharge_sm.set_initial_state(['PROCESS_RECHARGE_COMMAND'])
00089 recharge_sm.userdata.recharge_state = RechargeState(state=RechargeState.UNPLUGGED)
00090
00091 with recharge_sm:
00092
00093 @smach.cb_interface(input_keys=['recharge_command'])
00094 def plug_in_cond(ud):
00095 command = ud.recharge_command.command
00096 if command is RechargeCommand.PLUG_IN:
00097 return True
00098 elif command is RechargeCommand.UNPLUG:
00099 return False
00100 StateMachine.add('PROCESS_RECHARGE_COMMAND',
00101 ConditionState(cond_cb = plug_in_cond),
00102 { 'true':'NAVIGATE_TO_OUTLET',
00103 'false':'UNPLUG'})
00104
00105 sm_nav = StateMachine(
00106 outcomes=['succeeded','aborted','preempted'],
00107 input_keys = ['recharge_command'])
00108 StateMachine.add('NAVIGATE_TO_OUTLET', sm_nav,
00109 {'succeeded':'DETECT_OUTLET',
00110 'aborted':'FAIL_STILL_UNPLUGGED'})
00111 with sm_nav:
00112 StateMachine.add('GOAL_IS_LOCAL',
00113 ConditionState(
00114 cond_cb = lambda ud: ud.recharge_command.plug_id == 'local',
00115 input_keys = ['recharge_command']),
00116 {'true': 'UNTUCK_AT_OUTLET',
00117 'false': 'SAFETY_TUCK'})
00118 StateMachine.add('SAFETY_TUCK',
00119 SimpleActionState('tuck_arms', TuckArmsAction,
00120 goal = TuckArmsGoal(True,True)),
00121 { 'succeeded':'GET_OUTLET_LOCATIONS',
00122 'aborted':'SAFETY_TUCK'})
00123 StateMachine.add('GET_OUTLET_LOCATIONS',
00124 ServiceState('outlet_locations', GetOutlets,
00125 response_slots=['poses']),
00126 {'succeeded':'NAVIGATE'},
00127 remapping={'poses':'approach_poses'})
00128
00129 @smach.cb_interface(input_keys=['approach_poses','recharge_command'])
00130 def get_outlet_approach_goal(ud,goal):
00131 """Get the approach pose from the outlet approach poses list"""
00132
00133
00134 plug_id = ud.recharge_command.plug_id
00135
00136
00137 for outlet in ud.approach_poses:
00138 if outlet.name == plug_id or outlet.id == plug_id:
00139 target_pose = PoseStamped(pose=outlet.approach_pose)
00140
00141
00142 move_base_goal = MoveBaseGoal()
00143 move_base_goal.target_pose = target_pose
00144 move_base_goal.target_pose.header.stamp = rospy.Time.now()
00145 move_base_goal.target_pose.header.frame_id = "map"
00146
00147 return move_base_goal
00148 StateMachine.add('NAVIGATE',
00149 SimpleActionState('pr2_move_base',MoveBaseAction,
00150 goal_cb=get_outlet_approach_goal,
00151 exec_timeout = rospy.Duration(20*60.0)),
00152 { 'succeeded':'UNTUCK_AT_OUTLET' })
00153 StateMachine.add('UNTUCK_AT_OUTLET',
00154 SimpleActionState('tuck_arms', TuckArmsAction,
00155 goal = TuckArmsGoal(False, False)))
00156
00157 StateMachine.add('DETECT_OUTLET',
00158 SimpleActionState('detect_outlet',DetectOutletAction,
00159 result_slots = ['base_to_outlet_pose']),
00160 {'succeeded':'FETCH_PLUG',
00161 'aborted':'FAIL_STILL_UNPLUGGED'},
00162 remapping = {'base_to_outlet_pose':'base_to_outlet'})
00163
00164 StateMachine.add('FETCH_PLUG',
00165 SimpleActionState('fetch_plug',FetchPlugAction,
00166 result_slots = ['plug_on_base_pose', 'gripper_plug_grasp_pose']),
00167 {'succeeded':'PLUG_IN',
00168 'aborted':'FAIL_OPEN_GRIPPER'},
00169 remapping = {'plug_on_base_pose':'base_to_plug_on_base', 'gripper_plug_grasp_pose':'gripper_to_plug_grasp'})
00170
00171 @smach.cb_interface(input_keys=['recharge_state'], output_keys=['recharge_state'])
00172 def set_plug_in_result(ud, result_status, result):
00173 if result_status == GoalStatus.SUCCEEDED:
00174 ud.recharge_state.state = RechargeState.PLUGGED_IN
00175 StateMachine.add('PLUG_IN',
00176 SimpleActionState('plug_in',PlugInAction,
00177 goal_slots = ['base_to_outlet'],
00178 result_slots = ['gripper_to_plug'],
00179 result_cb = set_plug_in_result),
00180 { 'succeeded':'plugged_in',
00181 'aborted':'RECOVER_STOW_PLUG'})
00182
00183
00184 unplug_sm = StateMachine(
00185 outcomes = ['succeeded','aborted','preempted'],
00186 input_keys=['recharge_state','gripper_to_plug_grasp','gripper_to_plug','base_to_outlet','base_to_plug_on_base'],
00187 output_keys=['recharge_state'])
00188 StateMachine.add('UNPLUG', unplug_sm,
00189 { 'succeeded':'unplugged',
00190 'aborted':'FAIL_OPEN_GRIPPER'})
00191 with unplug_sm:
00192 """Unplug from outlet"""
00193
00194 StateMachine.add('CLOSE_GRIPPER',
00195 SimpleActionState('r_gripper_controller/gripper_action', Pr2GripperCommandAction,
00196 goal = close_gripper_goal),
00197 { 'succeeded':'aborted',
00198 'aborted':'WIGGLE_OUT'})
00199
00200
00201 def get_wiggle_out_goal(ud, goal):
00202
00203 goal.wiggle_period = rospy.Duration(0.5)
00204 goal.insert = 0
00205 return goal
00206 StateMachine.add('WIGGLE_OUT',
00207 SimpleActionState('wiggle_plug',WigglePlugAction,
00208 goal_slots = ['gripper_to_plug','base_to_outlet'],
00209 goal_cb = get_wiggle_out_goal),
00210 {'succeeded':'PULL_BACK_FROM_WALL'})
00211
00212 @smach.cb_interface(input_keys=['base_to_outlet','gripper_to_plug'])
00213 def get_pull_back_goal(ud, goal):
00214 """Generate an ik goal to move along the local x axis of the outlet."""
00215
00216 pose_outlet_plug = PyKDL.Frame(PyKDL.Vector(-0.10, 0, 0))
00217 pose_gripper_wrist = fromMsg(TFUtil.wait_and_lookup('r_gripper_tool_frame', 'r_wrist_roll_link').pose)
00218
00219 pose_base_wrist = fromMsg(ud.base_to_outlet) * pose_outlet_plug * fromMsg(ud.gripper_to_plug).Inverse() * pose_gripper_wrist
00220
00221 goal.pose.pose = toMsg(pose_base_wrist)
00222 goal.pose.header.stamp = rospy.Time.now()
00223 goal.pose.header.frame_id = 'base_link'
00224 goal.ik_seed = get_action_seed('pr2_plugs_configuration/approach_outlet_seed')
00225 goal.move_duration = rospy.Duration(5.0)
00226
00227 StateMachine.add('PULL_BACK_FROM_WALL',
00228 SimpleActionState('r_arm_ik', ArmMoveIKAction, goal_cb = get_pull_back_goal),
00229 {'succeeded':'STOW_PLUG',
00230 'aborted':'WIGGLE_OUT'})
00231
00232
00233 @smach.cb_interface(input_keys=['recharge_state'],output_keys=['recharge_state'])
00234 def set_unplug_result(ud, result_state, result):
00235 if result_state is GoalStatus.SUCCEEDED:
00236 ud.recharge_state.state = RechargeState.UNPLUGGED
00237
00238 StateMachine.add('STOW_PLUG', SimpleActionState('stow_plug',StowPlugAction,
00239 goal_slots = ['gripper_to_plug_grasp','base_to_plug'],
00240 result_cb = set_unplug_result),
00241 {'succeeded':'succeeded'},
00242 remapping = {'base_to_plug':'base_to_plug_on_base'})
00243
00244
00245 StateMachine.add('RECOVER_STOW_PLUG', SimpleActionState('stow_plug',StowPlugAction,
00246 goal_slots = ['gripper_to_plug_grasp','base_to_plug']),
00247 { 'succeeded':'FAIL_STILL_UNPLUGGED',
00248 'aborted':'FAIL_OPEN_GRIPPER'},
00249 remapping = {'base_to_plug':'base_to_plug_on_base'})
00250
00251
00252
00253 @smach.cb_interface(input_keys=['recharge_state'],output_keys=['recharge_state'],outcomes=['done'])
00254 def remain_unplugged(ud):
00255 ud.recharge_state.state = RechargeState.UNPLUGGED
00256 return 'done'
00257 StateMachine.add('FAIL_STILL_UNPLUGGED',
00258 CBState(cb = remain_unplugged),
00259 {'done':'FAIL_LOWER_SPINE'})
00260
00261
00262 StateMachine.add('FAIL_OPEN_GRIPPER',
00263 SimpleActionState('r_gripper_controller/gripper_action', Pr2GripperCommandAction,
00264 goal = open_gripper_goal),
00265 {'succeeded':'FAIL_UNTUCK'})
00266
00267 StateMachine.add('FAIL_UNTUCK',
00268 SimpleActionState('tuck_arms',TuckArmsAction,
00269 goal = TuckArmsGoal(False, False)),
00270 {'succeeded':'FAIL_LOWER_SPINE'})
00271
00272
00273 StateMachine.add('FAIL_LOWER_SPINE',
00274 SimpleActionState('torso_controller/position_joint_action', SingleJointPositionAction,
00275 goal = SingleJointPositionGoal(position=0.02)),
00276 {'succeeded':'aborted'})
00277
00278
00279
00280 intro_server = IntrospectionServer('recharge',recharge_sm,'/RECHARGE')
00281 intro_server.start()
00282
00283
00284 sms = ActionServerWrapper(
00285 'recharge', RechargeAction, recharge_sm,
00286 succeeded_outcomes = ['plugged_in','unplugged'],
00287 aborted_outcomes = ['aborted'],
00288 preempted_outcomes = ['preempted'],
00289 goal_slots_map = {'command':'recharge_command'},
00290 result_slots_map = {'state':'recharge_state'})
00291 sms.run_server()
00292
00293 rospy.spin()
00294
00295 intro_server.stop()
00296
00297 if __name__ == "__main__":
00298 main()
00299