pomdp_execution_for_models.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 import roslib; roslib.load_manifest('estirabot_apps')
00004 import rospy
00005 import smach
00006 import smach_ros
00007 import tf
00008 import random
00009 
00010 from smach         import StateMachine, CBState, Iterator
00011 from smach_ros     import ServiceState
00012 from actionlib     import *
00013 from actionlib.msg import *
00014 from std_msgs.msg  import String, Int8, Int32
00015 from object_manipulation_msgs.msg import PickupAction,PickupGoal,PlaceAction,PlaceGoal
00016 from sensor_msgs.msg import PointCloud2, JointState
00017 from iri_deformable_analysis.srv import DoDeformableAnalysis, DoDeformableAnalysisRequest
00018 from estirabot_msgs.msg import PomdpGraspConfig
00019 from estirabot_msgs.srv import obs2action, obs2actionRequest
00020 from geometry_msgs.msg import Transform, PoseStamped, Pose
00021 from pprint import pprint
00022 
00023 from iri_common_smach.st_get_pcl          import GetPCL
00024 from iri_common_smach.utils_msg           import build_pose_stamped_msg
00025 from iri_common_smach.get_keystroke       import GetKeyStroke
00026 from iri_common_smach.homogeneous_product import homogeneous_product_pose_transform
00027 from iri_common_smach.st_topic_publisher  import TopicPublisher
00028 from iri_wam_smach.sm_wam_move_from_pose  import SM_WAM_MoveFromPose
00029 
00030 from estirabot_apps_base.utils_pomdp            import PomdpConfigFactory, TranslatePomdp
00031 from estirabot_apps_base.sm_move                import SM_ESTIRABOT_GoHome
00032 from estirabot_apps_base.sm_deformable_analysis import SM_ESTIRABOT_DeformableAnalysis
00033 from estirabot_apps_base.sm_generate_grasp      import SM_ESTIRABOT_GenerateGraspMsg
00034 from TranslatePomdp2piles import TranslatePomdp 
00035 
00036 class ExperimentData():
00037     def __init__(self):
00038         ########## Pol rocks and stones ##########################
00039         # how to create an index that is consistent between executions?
00040         self.iteration_number = 0 
00041 
00042         self.algorithms = [    1, 1, 1, 1, 1, 1,
00043         1, 1, 1, 1, 1, 1,
00044         1, 1, 1, 1, 1, 1,
00045         1, 1, 1] 
00046 ##self.algorithms = [   1,   2,   3,   4,   5,   6, 
00047 #                             11,  12,  13,  14,  15,  16,
00048 #                            101, 102, 103, 104, 105, 106,
00049 #                            111, 112, 113, 114, 115, 116]
00050 
00051         self.algorithms_index_list = [] #is it necessary?
00052         self.total_algs = len(self.algorithms)
00053 
00054         #build the algorithms_index_list and shuffle it
00055         self.numrounds = 10 
00056         for i in range(self.numrounds):
00057           self.algorithms_index_list.extend(range(self.total_algs)) 
00058         random.shuffle(self.algorithms_index_list)
00059 #self.algorithms_index_list = [ 19, 4, 11, 12, 9, 3, 19, 16, 5, 22, 21, 6, 14, 21, 13, 4, 13, 0, 17, 21, 7, 9, 4, 10, 16, 8, 21, 7, 17, 11, 23, 23, 10, 11, 19, 17, 23, 6, 12, 0, 11, 15, 7, 16, 20, 3, 12, 16, 5, 18, 6, 17, 17, 23, 21, 8, 18, 18, 3, 18, 0, 6, 16, 15, 13, 16, 19, 19, 14, 2, 17, 20, 9, 11, 21, 23, 5, 13, 20, 7, 20, 10, 14, 6, 8, 9, 18, 6, 0, 13, 23, 3, 13, 7, 2, 14, 22, 21, 10, 20, 17, 8, 1, 0, 7, 4, 19, 9, 9, 20, 19, 1, 4, 5, 4, 19, 6, 1, 11, 15, 21, 18, 1, 15, 1, 3] 
00060 
00061         print(self.algorithms_index_list)
00062         self.numexperiments = len(self.algorithms_index_list) 
00063         ##########################################################
00064 
00065 class InputResult(smach.State):
00066     def __init__(self):
00067         smach.State.__init__(self, outcomes=['success'])
00068 
00069     def execute(self, userdata):
00070         keyserver = GetKeyStroke()
00071         c = -1
00072         print "Press [0-5] for clothes grabbed, 9 for error:"
00073         while (c < 0):
00074             c = keyserver()
00075             try:
00076                 c = int(c)
00077             except ValueError:
00078                 print "Error. Press [0-5] for clothes grabbed:"
00079                 continue
00080 
00081         print "Your value was: " + str(c)
00082         pub = rospy.Publisher('/log/number_of_clothes', Int8, None, False, True)
00083         pub.publish(c)
00084 
00085         return 'success'
00086 
00087 class PlaceHandler():
00088     def __init__(self):
00089         self.next_left_zone  = 1
00090         self.next_right_zone = 1
00091 
00092     def calculate_place_pose(self, pomdp_config):
00093         # If place_point is None it implies special basket
00094         if (pomdp_config.place_point == None):
00095             return self.get_basket_pose_st()
00096 
00097         #leave at the same side hard trick
00098         if (pomdp_config.grabbing_zone == pomdp_config.LEFT_ZONE):
00099             return self.get_left_place_pose()
00100         elif (pomdp_config.grabbing_zone == pomdp_config.RIGHT_ZONE):
00101             return self.get_right_place_pose()
00102         else:
00103             rospy.logerr("Value for graspping zone is not LEFT or RIGHT")
00104             return build_home_pose()
00105 
00106     def get_basket_pose_st(self):
00107         return build_pose_stamped_msg('/wam_link0', -0.165, 0.514, -0.188, 1, 0, 0, 0)
00108 
00109     def get_right_place_pose(self):
00110         if (self.next_right_zone == 1):
00111             pose = build_pose_stamped_msg('/wam_link0', 0.422, -0.390, -0.234, 1, 0, 0, 0)
00112         elif (self.next_right_zone == 2):
00113             pose = build_pose_stamped_msg('/wam_link0',0.584, -0.390, -0.234, 1, 0, 0, 0)
00114         elif (self.next_right_zone == 3):
00115             pose = build_pose_stamped_msg('/wam_link0',0.633, -0.160, -0.234, 1, 0, 0, 0)
00116         elif (self.next_right_zone == 4):
00117             pose = build_pose_stamped_msg('/wam_link0',0.476, -0.160, -0.234, 1, 0, 0, 0)
00118         else:
00119             rospy.logerr("Righ pose next zone is out of range: " + str(self.next_right_zone))
00120 
00121         self.next_right_zone = self.next_right_zone + 1
00122 
00123         # reset to 1 again
00124         if (self.next_right_zone > 4):
00125             self.next_right_zone = 1
00126 
00127         return pose
00128 
00129     def get_left_place_pose(self):
00130         if (self.next_left_zone == 1):
00131             pose = build_pose_stamped_msg('/wam_link0',0.422, 0.390, -0.234, 1, 0, 0, 0)
00132         elif (self.next_left_zone == 2):
00133             pose = build_pose_stamped_msg('/wam_link0',0.584, 0.390, -0.234, 1, 0, 0, 0)
00134         elif (self.next_left_zone == 3):
00135             pose = build_pose_stamped_msg('/wam_link0',0.633, 0.160, -0.234, 1, 0, 0, 0)
00136         elif (self.next_left_zone == 4):
00137             pose = build_pose_stamped_msg('/wam_link0',0.476, 0.160, -0.234, 1, 0, 0, 0)
00138         else:
00139             rospy.logerr("Left pose next zone is out of range: " + str(self.next_left_zone))
00140 
00141         self.next_left_zone = self.next_left_zone + 1
00142 
00143         # reset to 1 again
00144         if (self.next_left_zone > 4):
00145             self.next_left_zone = 1
00146 
00147         return pose
00148 
00149 class FirstAction(smach.State):
00150     def __init__(self):
00151         smach.State.__init__(self, outcomes    = ['ok','fail'],
00152                                    output_keys = ['pomdp_action','place_handler'])
00153 
00154     def execute(self, userdata):
00155         # Config and launch the deformable analysis
00156 
00157         randaction = random.randint(0,userdata.total_algs)
00158         print("initial random action: " % randaction)
00159         userdata.pomdp_action = randaction 
00160         pub = rospy.Publisher('/log/pomdp/action', Int8, None, False, True)
00161         pub.publish(response.action)
00162 
00163         if (not response):
00164             return 'fail'
00165 
00166         # Create the place handler
00167         userdata.place_handler = PlaceHandler()
00168 
00169         return 'ok'
00170 
00171 class CountObjects(smach.State):
00172     def __init__(self):
00173         smach.State.__init__(self, outcomes    = ['fail','success'],
00174                                    input_keys  = ['sm_pcl_table_left','sm_pcl_table_right'],
00175                                    output_keys = ['left_objects','right_objects'])
00176         self.number = -1
00177         # Subscribe to count numbers
00178         sub = rospy.Subscriber("/estirabot/skills/iri_textile_count/num_objects_found",
00179                                Int32, self.recieve_number)
00180 
00181     def execute(self, userdata):
00182         # Left objects
00183         self.calculate_objects(userdata.sm_pcl_table_left)
00184         userdata.left_objects = self.number
00185         pprint ("Left objects: " + str(self.number))
00186         pub = rospy.Publisher('/debug/observation/left_objects', Int8, None, False, True)
00187         pub.publish(self.number)
00188 
00189         #TODO what's this doing here?
00190         rospy.sleep(2)
00191 
00192         # Right objects
00193         self.calculate_objects(userdata.sm_pcl_table_right)
00194         userdata.right_objects = self.number
00195         pprint ("Right objects: " + str(self.number))
00196         pub = rospy.Publisher('/debug/observation/right_objects', Int8, None, False, True)
00197         pub.publish(self.number)
00198 
00199         return 'success'
00200 
00201     def recieve_number(self, data):
00202         self.number = data.data
00203 
00204     def calculate_objects(self, pcl):
00205         self.number = -1
00206         # Publish the pcl in /estirabot/skills/table/pcl
00207         pub = rospy.Publisher('/estirabot/skills/table/pcl', PointCloud2, None, False, True)
00208         pub.publish(pcl)
00209         # Wait to recieve the callback
00210         while (self.number == -1 and (not rospy.is_shutdown())):
00211             pprint("waiting")
00212             time.sleep(.1)
00213 
00214 class PrePlaceCalculation(smach.State):
00215     def __init__(self):
00216         smach.State.__init__(self, outcomes     = ['finish'],
00217                                    input_keys   = ['sm_pomdp_config'],
00218                                    output_keys  = ['pre_pose_st'])
00219 
00220     def execute(self, userdata):
00221         tf = Transform()
00222         tf.translation.z = -0.4
00223 
00224         pre_pose_st = PoseStamped()
00225         pre_pose_st.header.frame_id = '/wam_link0'
00226         pre_pose_st.header.stamp    = rospy.Time.now()
00227         pre_pose_st.pose = homogeneous_product_pose_transform(
00228                                         userdata.sm_pomdp_config.place_point.pose, tf)
00229 
00230         userdata.pre_pose_st = pre_pose_st
00231         return 'finish'
00232 
00233 class GetNextAction(smach.State):
00234     def __init__(self):
00235         smach.State.__init__(self, outcomes     = ['fail','finish','continue'],
00236                                    input_keys   = ['experiment_data'],
00237                                    output_keys  = ['pomdp_action', 'experiment_data'])
00238 
00239 
00240     def execute(self, userdata):
00241 
00242         ####################        
00243         pprint("iteration number = %d" % userdata.experiment_data.iteration_number)
00244         userdata.experiment_data.iteration_number += 1
00245         if (userdata.experiment_data.iteration_number == userdata.experiment_data.numexperiments):
00246             return 'finish'
00247         action = userdata.experiment_data.algorithms_index_list[userdata.experiment_data.iteration_number]
00248         ####################
00249 
00250         pub = rospy.Publisher('/log/pomdp/action', Int8, None, False, True)
00251         pub.publish(action) 
00252         userdata.pomdp_action = action
00253         return 'continue'
00254 
00255 def get_sm_grasp_goal_callback(userdata, default_goal):
00256     return userdata.sm_grasp_goal
00257 
00258 def get_sm_place_goal_callback(userdata, default_goal):
00259     goal = PlaceGoal()
00260     goal.place_locations.append(userdata.sm_pomdp_config.place_point)
00261 
00262     return goal
00263 
00264 def construct_main_sm():
00265     sm = StateMachine(outcomes = ['succeeded','aborted'])
00266 
00267     factory_home = SM_ESTIRABOT_GoHome()
00268     sm_home = factory_home.build_sm()
00269 
00270     factory_analysis = SM_ESTIRABOT_DeformableAnalysis()
00271     sm_analysis = factory_analysis.build_sm()
00272 
00273     factory_grasp = SM_ESTIRABOT_GenerateGraspMsg()
00274     sm_grasp_generation = factory_grasp.build_sm()
00275 
00276     factory_move = SM_WAM_MoveFromPose('/estirabot/wam_wrapper/joints_move',
00277                                        '/estirabot/iri_wam_tcp_ik/get_wam_ik')
00278     sm_move = factory_move.build_sm()
00279 
00280     # Create the experiment_data
00281     sm.userdata.experiment_data = ExperimentData()
00282     # Create the place handler
00283     sm.userdata.place_handler = PlaceHandler()
00284 
00285     with sm:
00286         smach.StateMachine.add('START_ROUND', sm_home,
00287                           transitions={'success' : 'LOG_PCL',
00288                                        'aborted' : 'aborted'})
00289         smach.StateMachine.add('LOG_PCL', 
00290                                 GetPCL("/estirabot/ceiling_kinect/camera/rgb/points"),
00291                 transitions = {'success' : 'LOG_IMAGE',
00292                                'fail'    : 'aborted'},
00293                 remapping   = {'pcl_RGB'  : 'sm_pcl_to_log'})
00294         smach.StateMachine.add('LOG_IMAGE',
00295                                 TopicPublisher('/log/pcl_table', PointCloud2),
00296                           transitions={'finish': 'GET_NEXT_ACTION'},
00297                           remapping = {'msg'   : 'sm_pcl_to_log'})
00298 
00299         # 1 GET NEXT ACTION
00300         smach.StateMachine.add('GET_NEXT_ACTION', GetNextAction(),
00301                         transitions={'continue' : 'TRANSLATE_POMDP_ACTION',
00302                                      'finish'   : 'succeeded',
00303                                      'fail'     : 'aborted'})
00304 
00305         # 2. CALCULATE GRASP POINT
00306         smach.StateMachine.add('TRANSLATE_POMDP_ACTION', TranslatePomdp(),
00307             transitions = { 'image_from_left'  : 'GET_KINECT_IMAGE_FROM_LEFT',
00308                             'image_from_right' : 'GET_KINECT_IMAGE_FROM_RIGHT',
00309                             'fail':'aborted'},
00310             remapping   = { 'sm_pomdp_config' : 'sm_pomdp_config'})
00311 
00312 
00313         # 2.1.a GET KINECT IMAGE FROM LEFT
00314         smach.StateMachine.add('GET_KINECT_IMAGE_FROM_LEFT', 
00315                                 GetPCL("/estirabot/skills/table/left/pcl"),
00316                 transitions = {'success' : 'PERFORM_ANALISYS',
00317                                'fail'    : 'aborted'},
00318                 remapping   = {'pcl_RGB'  : 'sm_pcl_output'})
00319 
00320         # 2.1.b GET KINECT IMAGE FROM RIGHT
00321         smach.StateMachine.add('GET_KINECT_IMAGE_FROM_RIGHT', 
00322                                 GetPCL("/estirabot/skills/table/right/pcl"),
00323                 transitions = {'success' : 'PERFORM_ANALISYS',
00324                                'fail'    : 'aborted'},
00325                 remapping   = {'pcl_RGB'  : 'sm_pcl_output'})
00326 
00327         # 2.2 ANALYSIS
00328         smach.StateMachine.add('PERFORM_ANALISYS', sm_analysis,
00329                 transitions = {'success'        : 'CALCULATE_GRASP',
00330                                'timeout'        : 'PERFORM_ANALISYS', # hack relaunch since descriptors died
00331                                'fail'           : 'aborted'},
00332                 remapping   = {'deformable_config' : 'sm_pomdp_config', # compatibles
00333                                'pcl_RGB'           : 'sm_pcl_output',
00334                                'best_grasp_pose'   : 'sm_best_grasp_pose'})
00335         # 2.3 CALCULATE GRASP
00336         smach.StateMachine.add('CALCULATE_GRASP', sm_grasp_generation,
00337                 transitions = {'success'        : 'DO_GRASP',
00338                                'no_ik_solution' : 'CALCULATE_GRASP',
00339                                'fail'           : 'aborted',
00340                                'all_ik_fail'    : 'GET_TABLE_IMAGE_FROM_LEFT'},
00341                 remapping   = {'pomdp_grasp_config'  : 'sm_pomdp_config', # compatibles
00342                                'grasp_pose'          : 'sm_best_grasp_pose',
00343                                'grasp_goal'          : 'sm_grasp_goal'})
00344         # 3.1 GRASP
00345         smach.StateMachine.add('DO_GRASP',
00346                               smach_ros.SimpleActionState('/estirabot/skills/grasp/pickup',
00347                                                           PickupAction,
00348                                                           goal_cb = get_sm_grasp_goal_callback,
00349                                                           input_keys=['sm_grasp_goal']),
00350                                {'succeeded': 'DO_LIFT',
00351                                 'preempted': 'aborted',
00352                                 'aborted'  : 'aborted'})
00353         # 3.2 LIFT
00354         smach.StateMachine.add('DO_LIFT', sm_home,
00355                         transitions={'success' : 'CHECK_GRASP',
00356                                      'aborted' : 'aborted'})
00357         # 3.2b CHECK
00358         smach.StateMachine.add('CHECK_GRASP', InputResult(),
00359                         transitions={'success' : 'CALCULATE_PRE_PLACE'})
00360 
00361         # 3.3.1 DO PRE PLACE
00362         smach.StateMachine.add('CALCULATE_PRE_PLACE', PrePlaceCalculation(),
00363                         transitions={'finish' : 'MOVE_TO_PRE_PLACE'},
00364                           remapping={'pre_pose_st':'sm_pre_pose_st'})
00365 
00366         smach.StateMachine.add('MOVE_TO_PRE_PLACE', sm_move,
00367                         transitions={'success' : 'DO_PLACE',
00368                                      'aborted' : 'aborted',
00369                                      'no_kinematic_solution'  : 'DO_PLACE'}, #TODO recompute pre place point 
00370                           remapping={'pose_st':'sm_pre_pose_st'})
00371 
00372         # 3.3.2 DO PLACE
00373         smach.StateMachine.add('DO_PLACE',
00374                        smach_ros.SimpleActionState('/estirabot/skills/iri_place/place',
00375                                                   PlaceAction,
00376                                                   goal_cb = get_sm_place_goal_callback,
00377                                                   input_keys=['sm_pomdp_config']),
00378                        {'succeeded': 'BACK_TO_HOME',
00379                         'preempted': 'aborted',
00380                         'aborted'  : 'aborted'})
00381 
00382         smach.StateMachine.add('BACK_TO_HOME', sm_home,
00383                           transitions={'success' : 'GET_TABLE_IMAGE_FROM_LEFT',
00384                                        'aborted' : 'aborted'})
00385 
00386         # 4. OBSERVATION
00387         # 4.1 GET PCL FROM LEFT
00388         smach.StateMachine.add('GET_TABLE_IMAGE_FROM_LEFT', 
00389                       GetPCL("/estirabot/skills/table/left/pcl"),
00390                 transitions = {'success' : 'GET_TABLE_IMAGE_FROM_RIGHT',
00391                                'fail'    : 'aborted'},
00392                 remapping   = {'pcl_RGB'  : 'sm_pcl_table_left'})
00393         # 4.2 GET PCL FROM RIGHT
00394         smach.StateMachine.add('GET_TABLE_IMAGE_FROM_RIGHT', 
00395                       GetPCL("/estirabot/skills/table/right/pcl"),
00396                 transitions = {'success' : 'COUNT_OBJECTS',
00397                                'fail'    : 'aborted'},
00398                 remapping   = {'pcl_RGB'  : 'sm_pcl_table_right'})
00399         # 4.3 GET NUMBER OF OBJECTS
00400         smach.StateMachine.add('COUNT_OBJECTS', CountObjects(),
00401                         transitions={'success' : 'START_ROUND',
00402                                      'fail'    : 'aborted'})
00403 
00404     return sm
00405 
00406 def main():
00407     rospy.init_node("pomdp_sm")
00408     sm_main = construct_main_sm()
00409 
00410     # Run state machine introspection server for smach viewer
00411     sis = smach_ros.IntrospectionServer('estirabot_smach_replicable', sm_main,
00412                                         '/estirabot_smach_replicable')
00413 
00414     sis.start()
00415 
00416     outcome = sm_main.execute()
00417 
00418     rospy.spin()
00419     sis.stop()
00420 
00421 if __name__ == "__main__":
00422     main()


estirabot_apps
Author(s): Jose Luis Rivero
autogenerated on Fri Dec 6 2013 23:20:59