00001
00002
00003
00004 import roslib; roslib.load_manifest('iri_clean_board')
00005 import rospy
00006 import smach
00007 import smach_ros
00008
00009 from smach_ros import SimpleActionState
00010 from smach_ros import ServiceState
00011
00012 from actionlib import *
00013 from actionlib.msg import *
00014 from iri_clean_board.msg import *
00015 from iri_clean_board.srv import *
00016 from estirabot_msgs.msg import *
00017 from estirabot_msgs.srv import *
00018
00019
00020
00021
00022
00023 class NeedInfo(smach.State):
00024 def __init__(self):
00025 smach.State.__init__(self, outcomes=['next','failed'])
00026 self.counter = 0
00027
00028 def execute(self, userdata):
00029 rospy.logdebug('Executing state NeedInfo')
00030 return 'next'
00031
00032
00033
00034 class Planning(smach.State):
00035 def __init__(self):
00036 smach.State.__init__(self, outcomes=['next','finish','get_info','failed'],
00037 input_keys=['segmented_image_sm','pointcloud_segm','plane_coefficients'],
00038 output_keys=['poses','plane_coefficients','poses_2d_coordinates','secondary_arm'])
00039
00040
00041 def execute(self, userdata):
00042 if userdata.pointcloud_segm.height == 0:
00043 rospy.loginfo('Pointcloud isn\'t available yet')
00044 return 'get_info'
00045
00046 rospy.logdebug('Executing state Planning')
00047 rospy.wait_for_service('/iri_clean_plan/cleaning_plan/get_cleaning_plan')
00048 try:
00049 get_cleaning_plan = rospy.ServiceProxy('/iri_clean_plan/cleaning_plan/get_cleaning_plan', PlanSrv)
00050 resp = get_cleaning_plan(userdata.pointcloud_segm, userdata.segmented_image_sm, userdata.plane_coefficients)
00051 if resp.is_clean:
00052 return 'finish'
00053 elif not resp.movement:
00054 return 'get_info'
00055 else:
00056 userdata.poses = resp.poses
00057 userdata.plane_coefficients = resp.plane_coefficients
00058 userdata.poses_2d_coordinates = resp.poses_2d_coordinates
00059 userdata.secondary_arm = resp.secondary_arm
00060 return 'next'
00061 except rospy.ServiceException, e:
00062 print "Service call failed: %s"%e
00063 return 'failed'
00064
00065
00066 class ComputeStateFromImage(smach.State):
00067 def __init__(self):
00068 smach.State.__init__(self, outcomes=['succeeded','preempted','aborted','is_clean'],
00069 input_keys=['segmented_image_sm','segmented_pointcloud_sm','plane_coefficients_sm'],
00070 output_keys=['ellipses','distances','max_widths','min_widths','sparse','num_objects','arm_position','segmented_pointcloud_sm','plane_coefficients_sm'])
00071 self.service_topic = '/iri_clean_plan/cleaning_plan/get_state_representation'
00072
00073 def execute(self, userdata):
00074 rospy.logdebug('Executing state ComputeStateFromImage')
00075 rospy.wait_for_service(self.service_topic)
00076 try:
00077 get_state = rospy.ServiceProxy(self.service_topic, EllipsesStateRepresentation)
00078 resp = get_state(userdata.segmented_image_sm)
00079 if resp.is_clean:
00080 return 'is_clean'
00081 else:
00082 userdata.ellipses = resp.ellipses
00083 userdata.distances = resp.distances
00084 userdata.max_widths = resp.max_widths
00085 userdata.min_widths = resp.min_widths
00086 userdata.sparse = resp.sparse
00087 userdata.num_objects = resp.num_objects
00088 userdata.arm_position = resp.arm_position
00089
00090 return 'succeeded'
00091 except rospy.ServiceException, e:
00092 print "Service call failed: %s"%e
00093 return 'aborted'
00094
00095
00096 class PradaPlanning(smach.State):
00097 def __init__(self):
00098 smach.State.__init__(self, outcomes=['succeeded','preempted','aborted','no_plan'],
00099 input_keys=['distances','max_widths','min_widths','sparse','num_objects','arm_position','ellipses','segmented_pointcloud_sm','plane_coefficients_sm'],
00100 output_keys=['target_ellipses','actions','ellipses','segmented_pointcloud_sm','plane_coefficients_sm'])
00101 self.service_topic = '/iri_clean_plan/prada_planner/getBestAction'
00102
00103 def execute(self, userdata):
00104 rospy.logdebug('Executing state PradaPlanning')
00105 rospy.wait_for_service(self.service_topic)
00106 try:
00107 get_cleaning_plan = rospy.ServiceProxy(self.service_topic, PradaPlanSrv)
00108 resp = get_cleaning_plan(userdata.distances, userdata.max_widths, userdata.min_widths, userdata.sparse, userdata.num_objects, userdata.arm_position)
00109
00110 if resp.succeeded:
00111 userdata.target_ellipses = resp.target_ellipses
00112 userdata.actions = resp.actions
00113 return 'succeeded'
00114 else:
00115 return 'no_plan'
00116
00117 except rospy.ServiceException, e:
00118 print "Service call failed: %s"%e
00119 return 'aborted'
00120
00121
00122 class CalculateTrajectories(smach.State):
00123 def __init__(self):
00124 smach.State.__init__(self, outcomes=['succeeded','preempted','aborted','no_movements'],
00125 input_keys=['target_ellipses_sm','actions_sm','ellipses_sm','segmented_pointcloud_sm','plane_coefficients_sm'],
00126 output_keys=['poses','plane_coefficients','poses_2d_coordinates','secondary_arm'])
00127 self.service_topic = '/iri_clean_plan/cleaning_plan/get_trajectories_from_plan'
00128
00129 def execute(self, userdata):
00130 rospy.logdebug('Executing state PradaPlanning')
00131 rospy.wait_for_service(self.service_topic)
00132 try:
00133 get_cleaning_plan = rospy.ServiceProxy(self.service_topic, PlanToTrajectories)
00134 resp = get_cleaning_plan(userdata.segmented_pointcloud_sm, userdata.plane_coefficients_sm, userdata.target_ellipses_sm, userdata.actions_sm)
00135
00136 if resp.movement:
00137 userdata.poses = resp.poses
00138 userdata.plane_coefficients = resp.plane_coefficients
00139 userdata.poses_2d_coordinates = resp.poses_2d_coordinates
00140 userdata.secondary_arm = resp.secondary_arm
00141
00142 return 'succeeded'
00143 else:
00144 return 'no_movements'
00145
00146 except rospy.ServiceException, e:
00147 print "Service call failed: %s"%e
00148 return 'aborted'
00149
00150
00151 class MoveArm(smach.State):
00152 def __init__(self):
00153 smach.State.__init__(self, outcomes=['next','failed'],
00154 input_keys=['poses','plane_coefficients','poses_2d_coordinates','secondary_arm'])
00155
00156 def execute(self, userdata):
00157 rospy.logdebug('Waiting for service')
00158 rospy.wait_for_service('/iri_clean_plan/arm_movements_by_pose/clean_movement')
00159 try:
00160 move_arm = rospy.ServiceProxy('/iri_clean_plan/arm_movements_by_pose/clean_movement', ArmMovementsPosesSrv)
00161 resp = move_arm(userdata.poses, userdata.secondary_arm, userdata.plane_coefficients, 1)
00162 if resp.success:
00163 print 'Executing service success'
00164 return 'next'
00165 else:
00166
00167 pub = rospy.Publisher('/iri_clean_perception/get_board_information/unreachable_position', ImagePoint)
00168 for idx in resp.too_far_points_indexes:
00169 pub.publish(userdata.poses_2d_coordinates[idx])
00170 print 'Executing service failed. Maybe IK.'
00171 return 'next'
00172 except rospy.ServiceException, e:
00173 print "Service call failed: %s"%e
00174 return 'failed'
00175
00176
00177 class MoveArmBase(smach.State):
00178 def __init__(self):
00179 smach.State.__init__(self, outcomes=['next','failed'])
00180
00181 def execute(self, userdata):
00182 rospy.loginfo('Waiting for service')
00183 rospy.wait_for_service('/iri_clean_plan/arm_movements_by_pose/clean_movement')
00184 try:
00185
00186 clean_mov = ArmMovementsPosesSrv()
00187 clean_mov.movement_type = 0
00188 clean_mov.poses = [];
00189 move_arm = rospy.ServiceProxy('/iri_clean_plan/arm_movements_by_pose/clean_movement', ArmMovementsPosesSrv)
00190 resp = move_arm(clean_mov.poses, [], [], 0)
00191 if resp.success:
00192 print 'Executing service success'
00193 return 'next'
00194 else:
00195 print 'Executing service failed'
00196 return 'next'
00197 except rospy.ServiceException, e:
00198 print "Service call failed: %s"%e
00199 return 'failed'
00200
00201
00202 def calculate_trajectories_cb(userdata, request):
00203
00204 request.pointcloud_in = userdata.segmented_pointcloud_sm
00205 request.plane_coefficients = userdata.plane_coefficients_sm
00206 request.target_ellipses = userdata.target_ellipses_sm
00207 request.actions = userdata.actions_sm
00208 return request
00209
00210
00211 def main():
00212 rospy.init_node('smach_example_state_machine')
00213
00214
00215 sm = smach.StateMachine(outcomes=['finishOk','failedVision','failedPlanning','failedMoveArm'])
00216
00217
00218 with sm:
00219
00220 smach.StateMachine.add('NeedInfo', NeedInfo(),
00221 transitions={'next':'GetInfoAction',
00222 'failed':'failedVision'},)
00223
00224 smach.StateMachine.add('GetInfoAction',
00225
00226
00227
00228
00229
00230
00231 ServiceState('/iri_clean_perception/get_board_information/get_board_info_srv',
00232 BoardInfo,
00233 response_slots=['segmented_image',
00234 'pointcloud',
00235 'plane_coefficients']),
00236 transitions={'succeeded':'ComputeStateFromImage',
00237 'preempted':'failedVision',
00238 'aborted':'failedVision'},
00239 remapping={'segmented_image':'segmented_image_sm',
00240 'pointcloud':'segmented_pointcloud_sm',
00241 'plane_coefficients':'plane_coefficients_sm'})
00242
00243 smach.StateMachine.add('ComputeStateFromImage', ComputeStateFromImage(),
00244 transitions={'succeeded':'PradaPlanning',
00245 'preempted':'failedVision',
00246 'aborted':'failedVision',
00247 'is_clean':'MoveArmBase'},
00248 remapping={'ellipses':'ellipses_sm'})
00249
00250 smach.StateMachine.add('PradaPlanning',
00251
00252
00253
00254
00255
00256
00257 PradaPlanning(),
00258 transitions={'succeeded':'CalculateTrajectories',
00259 'preempted':'failedVision',
00260 'aborted':'failedVision',
00261 'no_plan':'NeedInfo'},
00262 remapping={'target_ellipses':'target_ellipses_sm',
00263 'actions':'actions_sm'})
00264
00265 smach.StateMachine.add('CalculateTrajectories',
00266 CalculateTrajectories(),
00267
00268
00269
00270
00271
00272
00273 transitions={'succeeded':'MoveArm',
00274 'preempted':'failedVision',
00275 'aborted':'failedVision',
00276 'no_movements':'NeedInfo'})
00277
00278 smach.StateMachine.add('Planning', Planning(),
00279 transitions={'next':'MoveArm',
00280
00281 'finish':'MoveArmBase',
00282 'get_info':'NeedInfo',
00283 'failed':'failedPlanning'})
00284
00285 smach.StateMachine.add('MoveArm', MoveArm(),
00286 transitions={'next':'NeedInfo',
00287 'failed':'failedMoveArm'})
00288
00289 smach.StateMachine.add('MoveArmBase', MoveArmBase(),
00290 transitions={'next':'NeedInfo',
00291 'failed':'failedMoveArm'})
00292
00293
00294 outcome = sm.execute()
00295
00296
00297
00298 if __name__ == '__main__':
00299 main()