executive.py
Go to the documentation of this file.
00001 #! /usr/bin/env python
00002 # Copyright (c) 2008, Willow Garage, Inc.
00003 # All rights reserved.
00004 #
00005 # Redistribution and use in source and binary forms, with or without
00006 # modification, are permitted provided that the following conditions are met:
00007 #
00008 #         * Redistributions of source code must retain the above copyright
00009 #             notice, this list of conditions and the following disclaimer.
00010 #         * Redistributions in binary form must reproduce the above copyright
00011 #             notice, this list of conditions and the following disclaimer in the
00012 #             documentation and/or other materials provided with the distribution.
00013 #         * Neither the name of the Willow Garage, Inc. nor the names of its
00014 #             contributors may be used to endorse or promote products derived from
00015 #             this software without specific prior written permission.
00016 #
00017 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027 # POSSIBILITY OF SUCH DAMAGE.
00028 
00029 # Author: Wim Meeussen
00030 
00031 
00032 import roslib; roslib.load_manifest('pr2_doors_executive')
00033 import rospy
00034 
00035 from actionlib import *
00036 from actionlib.msg import *
00037 import smach
00038 from smach import *
00039 from smach_ros import *
00040 from door_msgs.msg import *
00041 from move_base_msgs.msg import *
00042 from pr2_common_action_msgs.msg import *
00043 from pr2_mechanism_msgs.srv import SwitchController, SwitchControllerRequest
00044 from pr2_controllers_msgs.msg import *
00045 from std_msgs.msg import *
00046 
00047 import threading
00048 
00049 import door_functions
00050 
00051 class SwitchControllersState(State):
00052     def __init__(self, stop_controllers, start_controllers):
00053         State.__init__(self, outcomes=['succeeded', 'aborted'])
00054         rospy.wait_for_service('pr2_controller_manager/switch_controller')
00055         self.srv = rospy.ServiceProxy('pr2_controller_manager/switch_controller', SwitchController)
00056         self.start_list = start_controllers
00057         self.stop_list = stop_controllers
00058 
00059     def execute(self,ud):
00060         try:
00061             self.srv(self.start_list, self.stop_list, SwitchControllerRequest.STRICT)
00062             return 'succeeded'
00063         except rospy.ServiceException, e:
00064             return 'aborted'
00065 
00066 def main():
00067     rospy.init_node('doors_executive')
00068 
00069     # construct state machine
00070     sm = StateMachine(
00071             ['succeeded', 'aborted', 'preempted'],
00072             input_keys = ['door'],
00073             output_keys = ['door'])
00074 
00075     with sm:
00076         StateMachine.add('INIT_CONTROLLERS',
00077                 SwitchControllersState(
00078                     stop_controllers = ["r_arm_cartesian_tff_controller"],
00079                     start_controllers = ["r_arm_controller"]),
00080                 { 'succeeded':'TUCK_ARMS' })
00081         StateMachine.add('TUCK_ARMS',
00082                 SimpleActionState('tuck_arms', TuckArmsAction, TuckArmsGoal(True, True)),
00083                 { 'succeeded': 'DETECT_DOOR',
00084                     'aborted': 'TUCK_ARMS'})
00085         
00086         @smach.cb_interface(
00087                 outcomes=['unlatched', 'closed', 'aborted'],
00088                 output_keys=['door'])
00089         def detect_door_result_cb(ud, status, result):
00090             if status == GoalStatus.SUCCEEDED:
00091                 ud.door = result.door
00092                 if result.door.latch_state == Door.UNLATCHED:
00093                     return 'unlatched'
00094                 else:
00095                     return 'closed'
00096             return 'aborted'
00097         StateMachine.add('DETECT_DOOR',
00098                 SimpleActionState('detect_door',DoorAction,
00099                     goal_slots = ['door'],
00100                     result_cb = detect_door_result_cb),
00101                 { 'closed': 'DETECT_HANDLE',
00102                     'unlatched': 'aborted',
00103                     'aborted': 'DETECT_DOOR'})
00104 
00105         # Sequence for opening the door with the handle
00106         @smach.cb_interface(output_keys=['door'])
00107         def detect_handle_result_cb(ud, status, result):
00108             if status == GoalStatus.SUCCEEDED:
00109                 ud.door = result.door
00110         StateMachine.add('DETECT_HANDLE',
00111                          SimpleActionState('detect_handle', DoorAction,
00112                                            goal_slots = ['door'],
00113                                            result_cb=detect_handle_result_cb),
00114                          { 'succeeded': 'APPROACH_DOOR',
00115                            'aborted': 'DETECT_HANDLE'})
00116 
00117         @smach.cb_interface(input_keys=['door'])
00118         def get_approach_goal(userdata, goal):
00119             target_pose = door_functions.get_robot_pose(userdata.door, -0.7)
00120             return MoveBaseGoal(target_pose)
00121         StateMachine.add('APPROACH_DOOR',
00122                 SimpleActionState('pr2_move_base_local', MoveBaseAction, goal_cb = get_approach_goal),
00123                 { 'succeeded':'GRASP_HANDLE',
00124                     'aborted':'APPROACH_DOOR'})
00125 
00126         StateMachine.add('UNTUCK_FOR_GRASP',
00127                 SimpleActionState('tuck_arms', TuckArmsAction, TuckArmsGoal(True, False)),
00128                 { 'succeeded': 'GRASP_HANDLE',
00129                     'aborted': 'aborted'})
00130 
00131         open_gripper_goal = Pr2GripperCommandGoal()
00132         open_gripper_goal.command.position = 0.07
00133         open_gripper_goal.command.max_effort = 99999
00134         StateMachine.add('OPEN_GRIPPER',
00135                 SimpleActionState('r_gripper_controller/gripper_action',
00136                     Pr2GripperCommandAction,
00137                     goal = open_gripper_goal),
00138                 {'succeeded':'GRASP_HANDLE'})
00139 
00140         StateMachine.add('GRASP_HANDLE',
00141                 SimpleActionState('grasp_handle', DoorAction, goal_slots = ['door']),
00142                 { 'succeeded':'TFF_START',
00143                     'aborted':'RECOVER_RELEASE_HANDLE'})
00144 
00145         StateMachine.add('RECOVER_RELEASE_HANDLE',
00146                 SimpleActionState('release_handle',DoorAction,goal_slots = ['door']),
00147                 { 'succeeded':'RECOVER_TUCK_ARMS',
00148                     'aborted':'RECOVER_RELEASE_HANDLE'})
00149         StateMachine.add('RECOVER_TUCK_ARMS', SimpleActionState('tuck_arms', TuckArmsAction, TuckArmsGoal(True, True)),
00150                 { 'succeeded': 'APPROACH_DETECT_POSE',
00151                     'aborted': 'RECOVER_TUCK_ARMS'})
00152 
00153         @smach.cb_interface(input_keys=['door'])
00154         def get_approach_detect_goal(userdata, goal):
00155             target_pose = door_functions.get_robot_pose(userdata.door, -1.5)
00156             return MoveBaseGoal(target_pose)
00157         StateMachine.add('APPROACH_DETECT_POSE',
00158                 SimpleActionState('pr2_move_base_local', MoveBaseAction, goal_cb = get_approach_detect_goal),
00159                 { 'succeeded':'DETECT_DOOR',
00160                     'aborted':'APPROACH_DETECT_POSE'})
00161 
00162 
00163         StateMachine.add('TFF_START',
00164                 SwitchControllersState(
00165                     stop_controllers = ["r_arm_controller"],
00166                     start_controllers = ["r_arm_cartesian_tff_controller"]),
00167                 { 'succeeded':'TURN_HANDLE' })
00168 
00169         # @TODO: When door is locked, unlatch_handle still returns success, but the resulting door message
00170         # contains the information that the door is locked. So the outcome of the TURN_HANDLE state 
00171         # should depend on the information in the action result.
00172 
00173         StateMachine.add('TURN_HANDLE',
00174                 SimpleActionState('unlatch_handle',DoorAction,goal_slots = ['door']),
00175                 { 'succeeded':'OPEN_DOOR'})
00176 
00177         open_door_cc = Concurrence(
00178                 ['succeeded','aborted','preempted'],
00179                 default_outcome = 'aborted',
00180                 input_keys = ['door'],
00181                 output_keys = ['door'],
00182                 child_termination_cb = lambda so: True,
00183                 outcome_map = {
00184                     'succeeded':{'MOVE_THROUGH':'succeeded'},
00185                     'aborted':{'MOVE_THROUGH':'aborted'},
00186                     'preempted':{'MOVE_THROUGH':'preempted'}})
00187         StateMachine.add('OPEN_DOOR',open_door_cc,
00188                 { 'succeeded':'TFF_STOP' })
00189         with open_door_cc:
00190             Concurrence.add('MOVE_THROUGH',SimpleActionState('move_base_door',DoorAction, goal_slots = ['door']))
00191             Concurrence.add('PUSH_DOOR',SimpleActionState('open_door',DoorAction, goal_slots = ['door']))
00192 
00193         StateMachine.add('TFF_STOP',
00194                 SwitchControllersState(
00195                     stop_controllers = ["r_arm_cartesian_tff_controller"],
00196                     start_controllers = ["r_arm_controller"]),
00197                 { 'succeeded':'RELEASE_HANDLE' })
00198 
00199         StateMachine.add('RELEASE_HANDLE',
00200                 SimpleActionState('release_handle',DoorAction,goal_slots = ['door']),
00201                 { 'succeeded':'FINISH_TUCK_ARMS'})
00202 
00203         StateMachine.add('FINISH_TUCK_ARMS', SimpleActionState('tuck_arms', TuckArmsAction, TuckArmsGoal(True, True)),
00204                 { 'succeeded': 'succeeded'})
00205         
00206 
00207         """
00208         # Sequence for pushing the door
00209         StateMachine.add('TOUCH_DOOR',
00210             SimpleActionState('touch_door', DoorAction, goal_slots = ['door']),
00211             {'succeeded':'PUSH_DOOR','aborted':'TOUCH_DOOR'})
00212 
00213         push_door = Concurrence(['succeeded','aborted','preempted'])
00214         push_door.add(
00215                 ('PUSH_DOOR',SimpleActionState('push_door',DoorAction, goal_slots = ['door'])),
00216                 ('MOVE_THROUGH',SimpleActionState('move_base_door',DoorAction, goal_slots = ['door'])))
00217         push_door.set_slave_states('PUSH_DOOR')
00218         push_door.add_outcome_map(
00219                 ({'MOVE_THROUGH':'succeeded'},'succeeded'),
00220                 ({'MOVE_THROUGH':'aborted'},'aborted'),
00221                 ({'MOVE_THROUGH':'preempted'},'preempted'))
00222         StateMachine.add('PUSH_DOOR',push_door,{})
00223         """
00224 
00225 
00226     intro_server = IntrospectionServer('doorman',sm,'/DOORMAN')
00227     intro_server.start()
00228 
00229     if 'run' in  rospy.myargv():
00230         sm_thread = threading.Thread(target=sm.execute)
00231         sm_thread.start()
00232     else:
00233         asw = ActionServerWrapper('move_through_door', DoorAction,
00234                 wrapped_container = sm,
00235                 goal_slots_map = {'door': 'door'},
00236                 succeeded_outcomes = ['succeeded'],
00237                 aborted_outcomes = ['aborted'],
00238                 preempted_outcomes = ['preeempted'])
00239         asw.run_server()
00240 
00241     rospy.spin()
00242 
00243     intro_server.stop()
00244 
00245 if __name__ == '__main__':
00246         main()
00247 


pr2_doors_executive
Author(s): Wim Meeussen
autogenerated on Wed Dec 11 2013 14:17:59