detect_outlet.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 import roslib
00004 roslib.load_manifest('pr2_plugs_actions')
00005 
00006 import rospy
00007 
00008 import os,sys,time
00009 from math import *
00010 import PyKDL
00011 
00012 from actionlib_msgs.msg import *
00013 from pr2_common_action_msgs.msg import *
00014 from pr2_plugs_msgs.msg import *
00015 from pr2_controllers_msgs.msg import *
00016 from geometry_msgs.msg import *
00017 from trajectory_msgs.msg import *
00018 from move_base_msgs.msg import *
00019 import copy
00020 
00021 from pr2_arm_move_ik.tools import *
00022 from tf_conversions.posemath import fromMsg, toMsg
00023 from joint_trajectory_action_tools.tools import get_action_goal as get_generator_goal
00024 
00025 # State machine classes
00026 import smach
00027 from smach import *
00028 from smach_ros import *
00029 from pr2_plugs_actions.tf_util import TFUtil
00030 
00031 import actionlib
00032 import dynamic_reconfigure.client
00033 
00034 __all__ = ['construct_sm']
00035 
00036 class OutletSearchState(State):
00037     def __init__(self, offsets, desired_distance):
00038         State.__init__(self,
00039                 outcomes=['succeeded','preempted','aborted'],
00040                 input_keys=['align_base_goal','vision_detect_outlet_goal'],
00041                 output_keys=['outlet_rough_pose'])
00042 
00043         # Store lateral offset goals
00044         self.offsets = offsets
00045         self.desired_distance = desired_distance
00046 
00047         # Create action clients
00048         self.align_base_client = actionlib.SimpleActionClient('align_base', AlignBaseAction)
00049         self.align_base_client.wait_for_server()
00050         self.vision_detect_outlet_client = actionlib.SimpleActionClient('vision_outlet_detection', VisionOutletDetectionAction)
00051         self.vision_detect_outlet_client.wait_for_server()
00052 
00053     def execute(self,ud):
00054         """Iterate across a set of offsets to find the outlet"""
00055         preempt_timeout = rospy.Duration(10.0)
00056 
00057         align_base_goal = ud.align_base_goal
00058         vision_detect_outlet_goal = ud.vision_detect_outlet_goal
00059 
00060         # Iterate across move_base offsets
00061         for offset in self.offsets:
00062             # align base
00063             rospy.loginfo("Search base alignment, offset %f..."%offset)
00064             align_base_goal.offset = offset
00065             align_base_goal.desired_distance = self.desired_distance
00066             if self.align_base_client.send_goal_and_wait(align_base_goal, rospy.Duration(40.0), preempt_timeout) != GoalStatus.SUCCEEDED:
00067                 rospy.logerr('Aligning base failed')
00068                 return 'aborted'
00069 
00070             # call vision outlet detection
00071             rospy.loginfo("Detecting outlet with the forearm camera...")
00072             vision_detect_outlet_goal.wall_normal = self.align_base_client.get_result().wall_norm
00073             vision_detect_outlet_goal.wall_normal.header.stamp = rospy.Time.now()
00074             vision_detect_outlet_goal.prior.header.stamp = rospy.Time.now()
00075             if self.vision_detect_outlet_client.send_goal_and_wait(vision_detect_outlet_goal, rospy.Duration(5.0), preempt_timeout) == GoalStatus.SUCCEEDED:
00076                 # Store the rough outlet position in the state machiine user data structure
00077                 ud.outlet_rough_pose = TFUtil.wait_and_transform('r_forearm_cam_optical_frame', self.vision_detect_outlet_client.get_result().outlet_pose)
00078                 # Set succeeded, and return
00079                 return 'succeeded'
00080 
00081         rospy.logerr("Could not find outlet in search.")
00082         return 'aborted'
00083 
00084 
00085 # Code block state for grasping the plug
00086 def construct_sm():
00087     TFUtil()
00088 
00089     # Check to see if this is running in sim where the dynamic reconfigure doesn't exist
00090     sim = rospy.get_param('~sim', False)
00091     rospy.logdebug('sim is %s', sim)
00092     if not sim:
00093         #this ensures that the forearm camera triggers when the texture projector is off
00094         projector_client = dynamic_reconfigure.client.Client('camera_synchronizer_node')
00095         forearm_projector_off = {'forearm_r_trig_mode': 4} #off
00096         projector_client.update_configuration(forearm_projector_off)
00097 
00098     # Define fixed goals
00099     # Declare wall norm goal
00100     # This is the point at which we want the head to look
00101     rough_align_distance = 0.88
00102     precise_align_distance = 0.74
00103     look_point = PointStamped()
00104     look_point.header.frame_id = 'base_link'
00105     look_point.point.x = -0.14
00106     look_point.point.y = -rough_align_distance # later over written in align_base
00107     look_point.point.z = 0.3
00108 
00109     wall_norm_goal = DetectWallNormGoal()
00110     wall_norm_goal.look_point = look_point
00111     wall_norm_goal.look_point.point.y = -precise_align_distance
00112 
00113     align_base_goal = AlignBaseGoal()
00114     align_base_goal.look_point = look_point
00115     align_base_goal.desired_distance = rough_align_distance
00116     align_base_goal_rough = copy.deepcopy(align_base_goal)
00117 
00118     vision_detect_outlet_goal = VisionOutletDetectionGoal()
00119     vision_detect_outlet_goal.camera_name = "/r_forearm_cam"
00120     vision_detect_outlet_goal.prior.pose = toMsg(PyKDL.Frame(PyKDL.Rotation.RPY(0, 0, -pi/2), PyKDL.Vector(-0.14, -0.82, 0.29)))
00121     vision_detect_outlet_goal.prior.header.frame_id = "base_link"
00122 
00123     # Construct state machine
00124     sm = StateMachine(
00125             outcomes=['succeeded','aborted','preempted'],
00126             output_keys=['base_to_outlet'])
00127 
00128     # Add static goals to userdata
00129     sm.userdata.wall_norm_goal = wall_norm_goal
00130     sm.userdata.align_base_goal = align_base_goal
00131     sm.userdata.vision_detect_outlet_goal = vision_detect_outlet_goal
00132 
00133     # Define nominal sequence
00134     with sm:
00135         StateMachine.add('LOWER_SPINE',
00136                 SimpleActionState('torso_controller/position_joint_action', SingleJointPositionAction,
00137                     goal = SingleJointPositionGoal(position=0.01)),
00138                 {'succeeded':'ROUGH_ALIGN_BASE'})
00139 
00140         StateMachine.add('ROUGH_ALIGN_BASE',
00141                 SimpleActionState('align_base', AlignBaseAction,
00142                     goal = align_base_goal_rough),
00143                 {'succeeded':'MOVE_ARM_DETECT_OUTLET'})
00144 
00145         StateMachine.add('MOVE_ARM_DETECT_OUTLET',
00146                 SimpleActionState('r_arm_controller/joint_trajectory_generator',JointTrajectoryAction, goal = get_generator_goal('pr2_plugs_configuration/detect_outlet')),
00147                 {'succeeded':'OUTLET_LATERAL_SEARCH',
00148                     'aborted':'FAIL_MOVE_ARM_OUTLET_TO_FREE'}),
00149 
00150         StateMachine.add('OUTLET_LATERAL_SEARCH',
00151                 OutletSearchState(offsets = (0.0, 0.15, -0.3, 0.45, -0.6), desired_distance = rough_align_distance),
00152                 {'succeeded':'PRECISE_ALIGN_BASE',
00153                     'aborted':'FAIL_MOVE_ARM_OUTLET_TO_FREE'})
00154 
00155         # Align the base precisely
00156         @smach.cb_interface(input_keys=['outlet_rough_pose'])
00157         def get_precise_align_goal(ud, goal):
00158             goal.offset = ud.outlet_rough_pose.pose.position.y
00159             return goal
00160         StateMachine.add('PRECISE_ALIGN_BASE',
00161                 SimpleActionState('align_base', AlignBaseAction,
00162                     goal = AlignBaseGoal(offset = 0, desired_distance = precise_align_distance, look_point=look_point),
00163                     goal_cb = get_precise_align_goal),
00164                 {'succeeded':'DETECT_WALL_NORM',
00165                     'aborted':'FAIL_MOVE_ARM_OUTLET_TO_FREE'})
00166 
00167         # Get wall norm
00168         @smach.cb_interface(input_keys=['wall_norm_goal'], output_keys=['wall_norm_goal'])
00169         def get_wall_norm_goal(ud, goal):
00170             ud.wall_norm_goal.look_point.header.stamp = rospy.Time.now()
00171             return ud.wall_norm_goal
00172 
00173         @smach.cb_interface(input_keys=['vision_detect_outlet_goal'], output_keys=['vision_detect_outlet_goal'])
00174         def store_wall_norm_result(ud, result_state, result):
00175             ud.vision_detect_outlet_goal.wall_normal = result.wall_norm
00176 
00177         StateMachine.add('DETECT_WALL_NORM',
00178                 SimpleActionState('detect_wall_norm', DetectWallNormAction,
00179                     goal_cb = get_wall_norm_goal,
00180                     result_cb = store_wall_norm_result),
00181                 {'succeeded':'DETECT_OUTLET',
00182                     'aborted':'DETECT_WALL_NORM'})
00183 
00184         # Precise detection
00185         @smach.cb_interface(input_keys=['vision_detect_outlet_goal'], output_keys=['vision_detect_outlet_goal'])
00186         def get_vision_detect_goal(ud, goal):
00187             ud.vision_detect_outlet_goal.wall_normal.header.stamp = rospy.Time.now()
00188             ud.vision_detect_outlet_goal.prior.header.stamp = rospy.Time.now()
00189             return ud.vision_detect_outlet_goal
00190 
00191         @smach.cb_interface(output_keys=['base_to_outlet'])
00192         def store_precise_outlet_result(ud, result_state, result):
00193             if result_state == GoalStatus.SUCCEEDED:
00194                 y = rospy.get_param('plugs_calibration_offset/y')
00195                 z = rospy.get_param('plugs_calibration_offset/z')
00196                 outlet_pose_corrected = PoseStamped()
00197                 outlet_pose_corrected.pose = toMsg(fromMsg(result.outlet_pose.pose) * PyKDL.Frame(PyKDL.Vector(0, y, z)))
00198                 outlet_pose_corrected.header = result.outlet_pose.header
00199                 rospy.loginfo("Using calibration offset y: %f and z: %f"%(y,z))
00200                 ud.base_to_outlet = TFUtil.wait_and_transform("base_link", outlet_pose_corrected).pose
00201                 print 'outlet not corrected'
00202                 print  TFUtil.wait_and_transform("base_link", result.outlet_pose).pose
00203                 print 'outlet corrected'
00204                 print  TFUtil.wait_and_transform("base_link", outlet_pose_corrected).pose
00205 
00206         StateMachine.add('DETECT_OUTLET', SimpleActionState('vision_outlet_detection', VisionOutletDetectionAction,
00207                                                             goal_cb = get_vision_detect_goal,
00208                                                             result_cb = store_precise_outlet_result),
00209                          {'succeeded':'succeeded',
00210                           'aborted':'FAIL_MOVE_ARM_OUTLET_TO_FREE'})
00211 
00212         # Define recovery states
00213         StateMachine.add('FAIL_MOVE_ARM_OUTLET_TO_FREE',
00214                 SimpleActionState('r_arm_controller/joint_trajectory_generator',JointTrajectoryAction, goal = get_generator_goal('pr2_plugs_configuration/recover_outlet_to_free')),
00215                 {'succeeded':'aborted'})
00216 
00217     return sm
00218 
00219 if __name__ == "__main__":
00220     rospy.init_node("detect_outlet")#,log_level=rospy.DEBUG)
00221     TFUtil()
00222 
00223     sm_detect_outlet = construct_sm()
00224 
00225     # Run state machine introspection server
00226     intro_server = IntrospectionServer('detect_outlet',sm_detect_outlet,'/RECHARGE/DETECT_OUTLET')
00227     intro_server.start()
00228 
00229     # Run state machine action server 
00230     asw = ActionServerWrapper(
00231             'detect_outlet', DetectOutletAction, sm_detect_outlet,
00232             succeeded_outcomes = ['succeeded'],
00233             aborted_outcomes = ['aborted'],
00234             preempted_outcomes = ['preempted'],
00235             result_slots_map = {'base_to_outlet_pose':'base_to_outlet'})
00236     asw.run_server()
00237 
00238     rospy.spin()
00239 
00240     intro_server.stop()


pr2_plugs_actions
Author(s): Jon Bohren, Patrick Mihelich, Wim Meeussen, and Melonee Wise
autogenerated on Mon Dec 2 2013 13:24:10