tabletop_executive.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # Software License Agreement (BSD License)
00003 #
00004 #  Copyright (c) 2012, Georgia Institute of Technology
00005 #  All rights reserved.
00006 #
00007 #  Redistribution and use in source and binary forms, with or without
00008 #  modification, are permitted provided that the following conditions
00009 #  are met:
00010 #
00011 #  * Redistributions of source code must retain the above copyright
00012 #     notice, this list of conditions and the following disclaimer.
00013 #  * Redistributions in binary form must reproduce the above
00014 #     copyright notice, this list of conditions and the following
00015 #     disclaimer in the documentation and/or other materials provided
00016 #     with the distribution.
00017 #  * Neither the name of the Georgia Institute of Technology nor the names of
00018 #     its contributors may be used to endorse or promote products derived
00019 #     from this software without specific prior written permission.
00020 #
00021 #  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 #  'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 #  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 #  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 #  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 #  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 #  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 #  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 #  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 #  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 #  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 #  POSSIBILITY OF SUCH DAMAGE.
00033 
00034 import roslib; roslib.load_manifest('tabletop_pushing')
00035 import rospy
00036 import actionlib
00037 import hrl_pr2_lib.pr2 as pr2
00038 import hrl_lib.tf_utils as tfu
00039 import tf
00040 import numpy as np
00041 from tabletop_pushing.srv import *
00042 from tabletop_pushing.msg import *
00043 from math import sin, cos, pi, fabs, sqrt, hypot
00044 import sys
00045 from select import select
00046 from push_learning import PushLearningIO
00047 from geometry_msgs.msg import Pose2D
00048 import time
00049 import random
00050 from push_primitives import *
00051 
00052 _OFFLINE = False
00053 _USE_LEARN_IO = False
00054 _TEST_START_POSE = False
00055 _USE_FIXED_GOAL = False
00056 
00057 class TabletopExecutive:
00058 
00059     def __init__(self, use_singulation, use_learning):
00060         self.previous_rand_pose = None
00061 
00062         rospy.init_node('tabletop_executive_node',log_level=rospy.INFO)
00063         self.min_push_dist = rospy.get_param('~min_push_dist', 0.07)
00064         self.max_push_dist = rospy.get_param('~mix_push_dist', 0.3)
00065         self.use_overhead_x_thresh = rospy.get_param('~use_overhead_x_thresh', 0.55)
00066         self.use_sweep_angle_thresh = rospy.get_param('~use_sweep_angle_thresh', pi*0.4)
00067         self.use_pull_angle_thresh = rospy.get_param('~use_sweep_angle_thresh', pi*0.525)
00068         self.use_same_side_y_thresh = rospy.get_param('~use_same_side_y_thresh', 0.3)
00069         self.use_same_side_x_thresh = rospy.get_param('~use_same_side_x_thresh', 0.8)
00070 
00071         self.gripper_offset_dist = rospy.get_param('~gripper_push_offset_dist', 0.05)
00072         self.gripper_start_z = rospy.get_param('~gripper_push_start_z', -0.29)
00073 
00074         self.pincher_offset_dist = rospy.get_param('~pincher_push_offset_dist', 0.05)
00075         self.pincher_start_z = rospy.get_param('~pincher_push_start_z', -0.29)
00076 
00077         self.sweep_face_offset_dist = rospy.get_param('~gripper_sweep_face_offset_dist', 0.03)
00078         self.sweep_wrist_offset_dist = rospy.get_param('~gripper_sweep_wrist_offset_dist', 0.01)
00079         self.sweep_start_z = rospy.get_param('~gripper_sweep_start_z', -0.30)
00080 
00081         self.overhead_offset_dist = rospy.get_param('~overhead_push_offset_dist', 0.05)
00082         self.overhead_start_z = rospy.get_param('~overhead_push_start_z', -0.29)
00083 
00084         self.gripper_pull_offset_dist = rospy.get_param('~gripper_push_offset_dist', 0.05)
00085         self.gripper_pull_start_z = rospy.get_param('~gripper_push_start_z', -0.29)
00086 
00087         self.max_restart_limit = rospy.get_param('~max_restart_limit', 2)
00088 
00089         self.min_new_pose_dist = rospy.get_param('~min_new_pose_dist', 0.2)
00090         self.min_workspace_x = rospy.get_param('~min_workspace_x', 0.5)
00091         self.max_workspace_x = rospy.get_param('~max_workspace_x', 0.8)
00092         self.max_workspace_y = rospy.get_param('~max_workspace_y', 0.4)
00093         self.min_workspace_y = -self.max_workspace_y
00094 
00095         self.goal_y_base_delta = 0.01
00096         self.num_start_loc_clusters = 5
00097         self.start_loc_use_fixed_goal = rospy.get_param('start_loc_use_fixed_goal', False)
00098         self.servo_head_during_pushing = rospy.get_param('servo_head_during_pushing', False)
00099         self.learn_file_base = rospy.get_param('push_learn_file_base_path', '/u/thermans/data/new/aff_learn_out_')
00100 
00101         # Setup service proxies
00102         if not _OFFLINE:
00103             if use_singulation:
00104                 self.gripper_push_proxy = rospy.ServiceProxy('gripper_push',
00105                                                              GripperPush)
00106                 self.gripper_pre_push_proxy = rospy.ServiceProxy('gripper_pre_push',
00107                                                                  GripperPush)
00108                 self.gripper_post_push_proxy = rospy.ServiceProxy('gripper_post_push',
00109                                                                   GripperPush)
00110                 self.gripper_pre_sweep_proxy = rospy.ServiceProxy('gripper_pre_sweep',
00111                                                                   GripperPush)
00112                 self.gripper_sweep_proxy = rospy.ServiceProxy('gripper_sweep',
00113                                                               GripperPush)
00114                 self.gripper_post_sweep_proxy = rospy.ServiceProxy('gripper_post_sweep',
00115                                                                    GripperPush)
00116                 self.overhead_pre_push_proxy = rospy.ServiceProxy('overhead_pre_push',
00117                                                                   GripperPush)
00118                 self.overhead_push_proxy = rospy.ServiceProxy('overhead_push',
00119                                                               GripperPush)
00120                 self.overhead_post_push_proxy = rospy.ServiceProxy('overhead_post_push',
00121                                                                    GripperPush)
00122             if use_learning:
00123                 # New visual feedback proxies
00124                 self.overhead_feedback_push_proxy = rospy.ServiceProxy(
00125                     'overhead_feedback_push', FeedbackPush)
00126                 self.overhead_feedback_post_push_proxy = rospy.ServiceProxy(
00127                     'overhead_feedback_post_push', FeedbackPush)
00128                 self.gripper_feedback_push_proxy = rospy.ServiceProxy(
00129                     'gripper_feedback_push', FeedbackPush)
00130                 self.gripper_feedback_post_push_proxy = rospy.ServiceProxy(
00131                     'gripper_feedback_post_push', FeedbackPush)
00132                 self.gripper_feedback_sweep_proxy = rospy.ServiceProxy(
00133                     'gripper_feedback_sweep', FeedbackPush)
00134                 self.gripper_feedback_post_sweep_proxy = rospy.ServiceProxy(
00135                     'gripper_feedback_post_sweep', FeedbackPush)
00136                 self.overhead_feedback_pre_push_proxy = rospy.ServiceProxy('overhead_pre_push',
00137                                                                            FeedbackPush)
00138                 self.gripper_feedback_pre_push_proxy = rospy.ServiceProxy('gripper_pre_push',
00139                                                                           FeedbackPush)
00140                 self.gripper_feedback_pre_sweep_proxy = rospy.ServiceProxy('gripper_pre_sweep',
00141                                                                            FeedbackPush)
00142             # Proxy to setup spine and head
00143             self.raise_and_look_proxy = rospy.ServiceProxy('raise_and_look',
00144                                                            RaiseAndLook)
00145         self.table_proxy = rospy.ServiceProxy('get_table_location', LocateTable)
00146         self.learn_io = None
00147 
00148         if use_singulation:
00149             self.use_singulation = True
00150             self.init_singulation()
00151         else:
00152             self.use_singulation = False
00153         if use_learning:
00154             self.use_learning = True
00155             self.init_learning()
00156         else:
00157             self.use_learning = False
00158         rospy.on_shutdown(self.shutdown_hook)
00159 
00160     def init_singulation(self):
00161         # Singulation Push proxy
00162         self.singulation_push_vector_proxy = rospy.ServiceProxy(
00163             'get_singulation_push_vector', SingulationPush)
00164 
00165     def init_learning(self):
00166         self.learning_push_vector_proxy = rospy.ServiceProxy(
00167             'get_learning_push_vector', LearnPush)
00168         # Get table height and raise to that before anything else
00169         if not _OFFLINE:
00170             self.raise_and_look()
00171         # Initialize push pose
00172         initialized = False
00173         r = rospy.Rate(0.5)
00174         while not initialized:
00175             initialized = self.initialize_learning_push()
00176             r.sleep()
00177         rospy.loginfo('Done initializing learning')
00178 
00179     def init_loc_learning(self):
00180         # Start loc learning stuff
00181         self.push_loc_shape_features = []
00182         self.push_count = 0
00183         self.base_trial_id = str(rospy.get_time())
00184 
00185         if _USE_LEARN_IO:
00186             self.learn_io = PushLearningIO()
00187             learn_file_name = self.learn_file_base+str(self.base_trial_id)+'.txt'
00188             self.learn_out_file_name = learn_file_name
00189             rospy.loginfo('Opening learn file: '+learn_file_name)
00190             self.learn_io.open_out_file(learn_file_name)
00191 
00192     def finish_learning(self):
00193         rospy.loginfo('Done with learning pushes and such.')
00194         if _USE_LEARN_IO and self.learn_io is not None:
00195             self.learn_io.close_out_file()
00196 
00197     def run_singulation(self, num_pushes=1, use_guided=True):
00198         # Get table height and raise to that before anything else
00199         if not _OFFLINE:
00200             self.raise_and_look()
00201         # Initialize push pose
00202         self.initialize_singulation_push_vector();
00203 
00204         # NOTE: Should exit before reaching num_pushes, this is just a backup
00205         for i in xrange(num_pushes):
00206             if _OFFLINE:
00207                 code_in = raw_input("Press <Enter> to determine next singulation push: ")
00208                 if code_in.startswith('q'):
00209                     break
00210             pose_res = self.request_singulation_push(use_guided)
00211             if pose_res is None:
00212                 rospy.logwarn("pose_res is None. Exiting pushing");
00213                 break
00214             if pose_res.no_push:
00215                 rospy.loginfo("No push. Exiting pushing.");
00216                 break
00217             rospy.loginfo('Performing push #' + str(i+1))
00218             # Decide push based on the orientation returned
00219             rospy.loginfo('Push start_point: (' + str(pose_res.start_point.x) +
00220                           ', ' + str(pose_res.start_point.y) +
00221                           ', ' + str(pose_res.start_point.z) + ')')
00222             rospy.loginfo('Push angle: ' + str(pose_res.push_angle))
00223             rospy.loginfo('Push dist: ' + str(pose_res.push_dist))
00224 
00225             behavior_primitive = self.choose_singulation_primitive(pose_res)
00226             # behavior_primitive = GRIPPER_PUSH
00227             # behavior_primitive = OVERHEAD_PUSH
00228             # behavior_primitive = GRIPPER_SWEEP
00229 
00230             # Choose arm
00231             which_arm = self.choose_singulation_arm(pose_res)
00232             push_dist = pose_res.push_dist
00233             push_dist = max(min(push_dist, self.max_push_dist),
00234                             self.min_push_dist)
00235 
00236             if _OFFLINE:
00237                 continue
00238             if behavior_primitive == GRIPPER_PUSH:
00239                 self.gripper_push_object(push_dist, which_arm, pose_res, True)
00240             if behavior_primitive == GRIPPER_SWEEP:
00241                 self.sweep_object(push_dist, which_arm, pose_res, True)
00242             if behavior_primitive == OVERHEAD_PUSH:
00243                 self.overhead_push_object(push_dist, which_arm, pose_res, True)
00244             rospy.loginfo('Done performing push behavior.\n')
00245 
00246         if not (pose_res is None):
00247             rospy.loginfo('Singulated objects: ' + str(pose_res.singulated))
00248             rospy.loginfo('Final estimate of ' + str(pose_res.num_objects) +
00249                           ' objects')
00250 
00251     def run_start_loc_learning(self, object_id, num_pushes_per_sample, num_sample_locs, start_loc_param_path=''):
00252         self.push_loc_shape_features = []
00253         for controller in CONTROLLERS:
00254             for behavior_primitive in BEHAVIOR_PRIMITIVES[controller]:
00255                 for proxy in PERCEPTUAL_PROXIES[controller]:
00256                     for arm in ROBOT_ARMS:
00257                         res = self.explore_push_start_locs(num_pushes_per_sample, num_sample_locs, behavior_primitive,
00258                                                            controller, proxy, object_id, arm, start_loc_param_path)
00259                         if res == 'quit':
00260                             rospy.loginfo('Quiting on user request')
00261                             return False
00262         return True
00263 
00264     def run_push_exploration(self, object_id):
00265         for controller in CONTROLLERS:
00266             for behavior_primitive in BEHAVIOR_PRIMITIVES[controller]:
00267                 for proxy in PERCEPTUAL_PROXIES[controller]:
00268                     for arm in ROBOT_ARMS:
00269                         precondition_method = PRECONDITION_METHODS[behavior_primitive]
00270                         res = self.explore_push(behavior_primitive, controller, proxy, object_id,
00271                                                 precondition_method, arm)
00272                         if res == 'quit':
00273                             rospy.loginfo('Quiting on user request')
00274                             return False
00275         return True
00276 
00277     def explore_push(self, behavior_primitive, controller_name, proxy_name, object_id,
00278                      precondition_method=CENTROID_PUSH_PRECONDITION, input_arm=None):
00279         if input_arm is not None:
00280             rospy.loginfo('Exploring push behavior: (' + behavior_primitive + ', '
00281                           + controller_name + ', ' + proxy_name + ', ' + input_arm + ')')
00282         else:
00283             rospy.loginfo('Exploring push triple: (' + behavior_primitive + ', '
00284                           + controller_name + ', ' + proxy_name + ')')
00285         timeout = 2
00286         rospy.loginfo("Enter something to pause before pushing: ")
00287         rlist, _, _ = select([sys.stdin], [], [], timeout)
00288         if rlist:
00289             s = sys.stdin.readline()
00290             code_in = raw_input('Move object and press <Enter> to continue: ')
00291             if code_in.lower().startswith('q'):
00292                 return 'quit'
00293         else:
00294             rospy.loginfo("No input. Moving on...")
00295 
00296         # NOTE: Get initial object pose here to make sure goal pose is far enough away
00297         if self.servo_head_during_pushing:
00298             self.raise_and_look(point_head_only=True)
00299 
00300         init_pose = self.get_feedback_push_initial_obj_pose()
00301         while not _OFFLINE and self.out_of_workspace(init_pose):
00302             rospy.loginfo('Object out of workspace at pose: (' + str(init_pose.x) + ', ' +
00303                           str(init_pose.y) + ')')
00304             code_in = raw_input('Move object inside workspace and press <Enter> to continue: ')
00305             if code_in.lower().startswith('q'):
00306                 return 'quit'
00307             init_pose = self.get_feedback_push_initial_obj_pose()
00308         goal_pose = self.generate_random_table_pose(init_pose)
00309 
00310         restart_count = 0
00311         done_with_push = False
00312         while not done_with_push:
00313             start_time = time.time()
00314             push_vec_res = self.get_feedback_push_start_pose(goal_pose, controller_name,
00315                                                              proxy_name, behavior_primitive,
00316                                                              learn_start_loc=False)
00317 
00318             if push_vec_res is None:
00319                 return None
00320             elif push_vec_res == 'quit':
00321                 return push_vec_res
00322 
00323             if input_arm is None:
00324                 which_arm = self.choose_arm(push_vec_res.push, controller_name)
00325             else:
00326                 which_arm = input_arm
00327 
00328             if _USE_LEARN_IO:
00329                 self.learn_io.write_pre_push_line(push_vec_res.centroid, push_vec_res.theta,
00330                                                   goal_pose, push_vec_res.push.start_point,
00331                                                   behavior_primitive, controller_name,
00332                                                   proxy_name, which_arm, object_id, precondition_method)
00333 
00334             res, push_res = self.perform_push(which_arm, behavior_primitive,
00335                                               push_vec_res, goal_pose,
00336                                               controller_name, proxy_name)
00337             push_time = time.time() - start_time
00338             if push_res.failed_pre_position:
00339                 if _USE_LEARN_IO:
00340                     self.learn_io.write_bad_trial_line()
00341             else:
00342                 self.analyze_push(behavior_primitive, controller_name, proxy_name, which_arm, push_time,
00343                                   push_vec_res, goal_pose, object_id, precondition_method)
00344 
00345             if res == 'quit':
00346                 return res
00347             elif res == 'aborted':
00348                 if self.servo_head_during_pushing:
00349                     self.raise_and_look(point_head_only=True)
00350                 restart_count += 1
00351                 if restart_count <= self.max_restart_limit:
00352                     rospy.loginfo('Continuing after push was aborted')
00353                     continue
00354                 else:
00355                     done_with_push = True
00356                     rospy.loginfo('Stopping push attempt because of too many restarts\n')
00357             else:
00358                 rospy.loginfo('Stopping push attempt because reached goal\n')
00359                 done_with_push = True
00360         return res
00361 
00362     def explore_push_start_locs(self, num_pushes_per_sample, num_sample_locs, behavior_primitive, controller_name,
00363                                 proxy_name, object_id, which_arm, start_loc_param_path='',
00364                                 precondition_method=CENTROID_PUSH_PRECONDITION):
00365         rospy.loginfo('Exploring push start locs for triple: (' + behavior_primitive + ', ' +
00366                       controller_name + ', ' + proxy_name + ')')
00367         timeout = 2
00368         rospy.loginfo("Enter something to pause before pushing: ")
00369         rlist, _, _ = select([sys.stdin], [], [], timeout)
00370         if rlist:
00371             s = sys.stdin.readline()
00372             code_in = raw_input('Move object and press <Enter> to continue: ')
00373             if code_in.lower().startswith('q'):
00374                 return 'quit'
00375         else:
00376             rospy.loginfo("No input. Moving on...")
00377 
00378         if self.servo_head_during_pushing:
00379             self.raise_and_look(point_head_only=True)
00380 
00381         start_loc_trials = 0
00382         self.start_loc_goal_y_delta = 0
00383         N_PUSH = num_sample_locs
00384         # HACK: Currently quit after half the locations, assuming pushing on symmetric objects
00385         # N_PUSH = num_sample_locs/2+1
00386         i = 0
00387         while i < N_PUSH:
00388             rospy.loginfo('Performing push at new pose: ' + str(i))
00389             i += 1
00390             # Doesn't matter what the goal_pose is, the start pose server picks it for us
00391             goal_pose = self.generate_random_table_pose()
00392             j = 0
00393             position_worked = True
00394             while j  < num_pushes_per_sample:
00395                 rospy.loginfo('Performing push iteration: '+str(start_loc_trials))
00396                 rospy.loginfo('Performing sample push ' + str(j) + ' for pose: ' + str(i-1))
00397                 rospy.loginfo('Sending param_path: ' + start_loc_param_path)
00398                 # NOTE: Get initial object pose here to make sure goal pose is far enough away
00399                 init_pose = self.get_feedback_push_initial_obj_pose()
00400                 if self.start_loc_use_fixed_goal: # and position_worked:
00401                     reset = False
00402                     while not reset:
00403                         code_in = raw_input('Move object to initial test pose and press <Enter> to continue: ')
00404                         if code_in.lower().startswith('q'):
00405                             return 'quit'
00406                         reset = True
00407                         init_pose = self.get_feedback_push_initial_obj_pose()
00408                 elif not _OFFLINE:
00409                     while self.out_of_workspace(init_pose):
00410                         rospy.loginfo('Object out of workspace at pose: (' + str(init_pose.x) + ', ' +
00411                                       str(init_pose.y) + ')')
00412                         code_in = raw_input('Move object inside workspace and press <Enter> to continue: ')
00413                         if code_in.lower().startswith('q'):
00414                             return 'quit'
00415                         init_pose = self.get_feedback_push_initial_obj_pose()
00416 
00417                 trial_id = str(object_id) +'_'+ str(self.base_trial_id) + '_' + str(self.push_count)
00418                 self.push_count += 1
00419                 start_time = time.time()
00420                 push_vec_res = self.get_feedback_push_start_pose(goal_pose, controller_name, proxy_name,
00421                                                                  behavior_primitive, learn_start_loc=True,
00422                                                                  new_object=(not start_loc_trials),
00423                                                                  num_clusters=self.num_start_loc_clusters,
00424                                                                  trial_id=trial_id,
00425                                                                  num_sample_locs=num_sample_locs,
00426                                                                  num_pushes_per_sample=num_pushes_per_sample,
00427                                                                  start_loc_param_path=start_loc_param_path,
00428                                                                  position_worked=position_worked)
00429                 if push_vec_res is None:
00430                     rospy.logwarn('Push vector Response is none, exiting')
00431                     return None
00432                 elif push_vec_res == 'quit':
00433                     return push_vec_res
00434 
00435                 # Pick arm if we are using learned stuff
00436                 if len(start_loc_param_path) > 0:
00437                     which_arm = self.choose_arm(push_vec_res.push, controller_name)
00438 
00439                 goal_pose = push_vec_res.goal_pose
00440                 shape_descriptor = push_vec_res.shape_descriptor[:]
00441                 self.push_loc_shape_features.append(shape_descriptor)
00442 
00443                 if _USE_LEARN_IO:
00444                     # TODO: Check that the predicted_score is sent correctly
00445                     rospy.loginfo('Predicted score: ' + str(push_vec_res.predicted_score))
00446                     self.learn_io.write_pre_push_line(push_vec_res.centroid, push_vec_res.theta,
00447                                                       goal_pose, push_vec_res.push.start_point, behavior_primitive,
00448                                                       controller_name, proxy_name, which_arm, trial_id,
00449                                                       precondition_method, push_vec_res.predicted_score,
00450                                                       shape_descriptor)
00451 
00452                 res, push_res = self.perform_push(which_arm, behavior_primitive, push_vec_res, goal_pose,
00453                                                   controller_name, proxy_name)
00454                 push_time = time.time() - start_time
00455 
00456                 if _USE_LEARN_IO and not _OFFLINE:
00457                     timeout = 2
00458                     rospy.loginfo("Enter something to not save the previous push trial: ")
00459                     rlist, _, _ = select([sys.stdin], [], [], timeout)
00460                     if rlist:
00461                         self.learn_io.write_bad_trial_line()
00462                         s = sys.stdin.readline()
00463                         rospy.loginfo('Not saving previous trial.')
00464                         if s.lower().startswith('q'):
00465                             return 'quit'
00466                         position_worked = True
00467                     elif push_res.failed_pre_position:
00468                         self.learn_io.write_bad_trial_line()
00469                         rospy.loginfo('Not saving previous trial because of failed hand placement')
00470                         position_worked = False
00471                         # TOOD: Get the next choice, to avoid infinitely trying this one
00472                     else:
00473                         rospy.loginfo("No input. Saving trial data")
00474                         self.analyze_push(behavior_primitive, controller_name, proxy_name, which_arm, push_time,
00475                                           push_vec_res, goal_pose, trial_id, precondition_method)
00476                         start_loc_trials += 1
00477                         j += 1
00478                         position_worked = True
00479                 else:
00480                     j += 1
00481                     position_worked = True
00482 
00483                 if res == 'quit':
00484                     return res
00485                 elif res == 'aborted' or res == 'done':
00486                     if self.servo_head_during_pushing:
00487                         self.raise_and_look(point_head_only=True)
00488         rospy.loginfo('Done performing push loc exploration!')
00489         return res
00490 
00491     def get_feedback_push_initial_obj_pose(self):
00492         get_push = True
00493         while get_push:
00494             goal_pose = Pose2D()
00495             controller_name = CENTROID_CONTROLLER
00496             proxy_name = ELLIPSE_PROXY
00497             behavior_primitive = OVERHEAD_PUSH
00498             push_vec_res = self.request_feedback_push_start_pose(goal_pose, controller_name,
00499                                                                  proxy_name, behavior_primitive,
00500                                                                  get_pose_only=True)
00501 
00502             if push_vec_res is None:
00503                 return None
00504             if push_vec_res.no_objects:
00505                 code_in = raw_input('No objects found. Place object and press <Enter>: ')
00506                 if code_in.lower().startswith('q'):
00507                     return 'quit'
00508             else:
00509                 return push_vec_res.centroid
00510 
00511 
00512     def get_feedback_push_start_pose(self, goal_pose, controller_name, proxy_name,
00513                                      behavior_primitive,
00514                                      learn_start_loc=False, new_object=False, num_clusters=1,
00515                                      trial_id='',num_sample_locs=1, num_pushes_per_sample=1,
00516                                      start_loc_param_path='', position_worked=True):
00517         get_push = True
00518         while get_push:
00519             push_vec_res = self.request_feedback_push_start_pose(goal_pose, controller_name,
00520                                                                  proxy_name, behavior_primitive,
00521                                                                  learn_start_loc=learn_start_loc,
00522                                                                  new_object=new_object,
00523                                                                  num_clusters=num_clusters,
00524                                                                  trial_id=trial_id,
00525                                                                  num_sample_locs=num_sample_locs,
00526                                                                  num_pushes_per_sample=num_pushes_per_sample,
00527                                                                  start_loc_param_path=start_loc_param_path,
00528                                                                  position_worked=position_worked)
00529 
00530             if push_vec_res is None:
00531                 return None
00532             if push_vec_res.no_objects:
00533                 code_in = raw_input('No objects found. Place object and press <Enter>: ')
00534                 if code_in.lower().startswith('q'):
00535                     return 'quit'
00536             else:
00537                 return push_vec_res
00538 
00539     def choose_arm(self, push_vec, controller_name):
00540         if controller_name == ROTATE_TO_HEADING:
00541             if (push_vec.start_point.y < 0):
00542                 which_arm = 'r'
00543             else:
00544                 which_arm = 'l'
00545             return which_arm
00546         elif controller_name == DIRECT_GOAL_CONTROLLER:
00547             if push_vec.push_angle > 0:
00548                 which_arm = 'r'
00549             else:
00550                 which_arm = 'l'
00551         elif (fabs(push_vec.start_point.y) > self.use_same_side_y_thresh or
00552               push_vec.start_point.x > self.use_same_side_x_thresh):
00553             if (push_vec.start_point.y < 0):
00554                 which_arm = 'r'
00555             else:
00556                 which_arm = 'l'
00557         elif push_vec.push_angle > 0:
00558             which_arm = 'r'
00559         else:
00560             which_arm = 'l'
00561 
00562         return which_arm
00563 
00564     def choose_singulation_primitive(self, pose_res):
00565         # Choose push behavior
00566         if fabs(pose_res.push_angle) > self.use_pull_angle_thresh:
00567             behavior_primitive = OVERHEAD_PUSH
00568         elif pose_res.start_point.x < self.use_overhead_x_thresh:
00569             behavior_primitive = OVERHEAD_PUSH
00570         elif fabs(pose_res.push_angle) > self.use_sweep_angle_thresh:
00571             behavior_primitive = GRIPPER_SWEEP
00572         else:
00573             behavior_primitive = GRIPPER_PUSH
00574         return behavior_primitive
00575 
00576     def choose_singulation_arm(self, pose_res):
00577         if (fabs(pose_res.start_point.y) > self.use_same_side_y_thresh or
00578             pose_res.start_point.x > self.use_same_side_x_thresh):
00579             if (pose_res.start_point.y < 0):
00580                 which_arm = 'r'
00581                 rospy.loginfo('Setting arm to right because of limits')
00582             else:
00583                 which_arm = 'l'
00584                 rospy.loginfo('Setting arm to left because of limits')
00585         elif pose_res.push_angle > 0:
00586             which_arm = 'r'
00587             rospy.loginfo('Setting arm to right because of angle')
00588         else:
00589             which_arm = 'l'
00590             rospy.loginfo('Setting arm to left because of angle')
00591         return which_arm
00592 
00593     def perform_push(self, which_arm, behavior_primitive, push_vector_res, goal_pose,
00594                      controller_name, proxy_name, high_init = True):
00595         push_angle = push_vector_res.push.push_angle
00596         # NOTE: Use commanded push distance not visually decided minimal distance
00597         if push_vector_res is None:
00598             rospy.logwarn("push_vector_res is None. Exiting pushing");
00599             return ('quit', None)
00600         if push_vector_res.no_push:
00601             rospy.loginfo("No push. Exiting pushing.");
00602             return ('quit', None)
00603         # Decide push based on the orientation returned
00604         rospy.loginfo('Push start_point: (' +
00605                       str(push_vector_res.push.start_point.x) + ', ' +
00606                       str(push_vector_res.push.start_point.y) + ', ' +
00607                       str(push_vector_res.push.start_point.z) + ')')
00608         rospy.loginfo('Push angle: ' + str(push_angle))
00609         if not _OFFLINE:
00610             if behavior_primitive == OVERHEAD_PUSH or behavior_primitive == OPEN_OVERHEAD_PUSH:
00611                 result = self.overhead_feedback_push_object(which_arm,
00612                                                             push_vector_res.push, goal_pose,
00613                                                             controller_name, proxy_name, behavior_primitive)
00614             elif behavior_primitive == GRIPPER_SWEEP:
00615                 result = self.feedback_sweep_object(which_arm, push_vector_res.push,
00616                                                     goal_pose, controller_name, proxy_name, behavior_primitive)
00617             elif behavior_primitive == GRIPPER_PUSH or behavior_primitive == PINCHER_PUSH or behavior_primitive == GRIPPER_PULL:
00618                 result = self.gripper_feedback_push_object(which_arm,
00619                                                            push_vector_res.push, goal_pose,
00620                                                            controller_name, proxy_name, behavior_primitive)
00621             else:
00622                 rospy.logwarn('Unknown behavior_primitive: ' + str(behavior_primitive))
00623                 result = None
00624         else:
00625             result = FeedbackPushResponse()
00626 
00627         # NOTE: If the call aborted, recall with the same settings
00628         if result.action_aborted:
00629             rospy.logwarn('Push was aborted. Calling push behavior again.')
00630             return ('aborted', result)
00631 
00632         rospy.loginfo('Done performing push behavior.')
00633         # if _OFFLINE:
00634         #     code_in = raw_input("Press <Enter> to try another push: ")
00635         #     if code_in.lower().startswith('q'):
00636         #         return ('quit', result)
00637         return ('done', result)
00638 
00639     def analyze_push(self, behavior_primitive, controller_name, proxy_name,
00640                      which_arm, push_time, push_vector_res, goal_pose, object_id,
00641                      precondition_method=CENTROID_PUSH_PRECONDITION):
00642         push_angle = push_vector_res.push.push_angle
00643         analysis_res = self.request_learning_analysis()
00644         rospy.loginfo('Done getting analysis response.')
00645         rospy.loginfo('Primitive: ' + str(behavior_primitive))
00646         rospy.loginfo('Controller: ' + str(controller_name))
00647         rospy.loginfo('Proxy: ' + str(proxy_name))
00648         rospy.loginfo('Arm: ' + str(which_arm))
00649         rospy.loginfo('Push time: ' + str(push_time) + 's')
00650         rospy.loginfo('Init (X,Y,Theta): (' + str(push_vector_res.centroid.x) +
00651                       ', ' + str(push_vector_res.centroid.y) + ', ' +
00652                       str(push_vector_res.theta) +')')
00653         rospy.loginfo('Final (X,Y,Theta): (' + str(analysis_res.centroid.x) + ', ' +
00654                        str(analysis_res.centroid.y) + ', ' + str(analysis_res.theta)+ ')')
00655         rospy.loginfo('Desired (X,Y,Theta): (' + str(goal_pose.x) + ', ' +
00656                        str(goal_pose.y) + ', ' + str(goal_pose.theta) + ')')
00657         rospy.loginfo('Error (X,Y,Theta): (' + str(fabs(goal_pose.x-analysis_res.centroid.x)) +
00658                       ', ' + str(fabs(goal_pose.y-analysis_res.centroid.y)) + ', ' +
00659                       str(fabs(goal_pose.theta-analysis_res.theta)) + ')\n')
00660         if _USE_LEARN_IO:
00661             self.learn_io.write_line(
00662                 push_vector_res.centroid, push_vector_res.theta,
00663                 analysis_res.centroid, analysis_res.theta,
00664                 goal_pose, push_vector_res.push.start_point, behavior_primitive, controller_name, proxy_name,
00665                 which_arm, push_time, object_id, precondition_method)
00666 
00667     def request_singulation_push(self, use_guided=True):
00668         push_vector_req = SingulationPushRequest()
00669         push_vector_req.use_guided = use_guided
00670         push_vector_req.initialize = False
00671         push_vector_req.no_push_calc = False
00672         rospy.loginfo("Calling singulation push vector service")
00673         try:
00674             push_vector_res = self.singulation_push_vector_proxy(push_vector_req)
00675             return push_vector_res
00676         except rospy.ServiceException, e:
00677             rospy.logwarn("Service did not process request: %s"%str(e))
00678             return None
00679 
00680     def request_feedback_push_start_pose(self, goal_pose, controller_name, proxy_name,
00681                                          behavior_primitive,
00682                                          get_pose_only=False, learn_start_loc=False,
00683                                          new_object=False, num_clusters=1, trial_id='',
00684                                          num_sample_locs=1, num_pushes_per_sample=1,start_loc_param_path='',
00685                                          position_worked=True):
00686         push_vector_req = LearnPushRequest()
00687         push_vector_req.initialize = False
00688         push_vector_req.analyze_previous = False
00689         push_vector_req.goal_pose = goal_pose
00690         push_vector_req.controller_name = controller_name
00691         push_vector_req.proxy_name = proxy_name
00692         push_vector_req.behavior_primitive = behavior_primitive
00693         push_vector_req.get_pose_only = get_pose_only
00694         push_vector_req.learn_start_loc = learn_start_loc
00695         push_vector_req.new_object = new_object
00696         push_vector_req.trial_id = trial_id
00697         push_vector_req.num_start_loc_clusters = num_clusters
00698         push_vector_req.num_start_loc_sample_locs = num_sample_locs
00699         push_vector_req.num_start_loc_pushes_per_sample = num_pushes_per_sample
00700         push_vector_req.start_loc_param_path=start_loc_param_path
00701         push_vector_req.previous_position_worked = position_worked
00702         try:
00703             rospy.loginfo("Calling feedback push start service")
00704             push_vector_res = self.learning_push_vector_proxy(push_vector_req)
00705             return push_vector_res
00706         except rospy.ServiceException, e:
00707             rospy.logwarn("Service did not process request: %s"%str(e))
00708             return None
00709 
00710     def request_learning_analysis(self):
00711         push_vector_req = LearnPushRequest()
00712         push_vector_req.initialize = False
00713         push_vector_req.analyze_previous = True
00714         rospy.loginfo("Calling learning push vector service")
00715         try:
00716             push_vector_res = self.learning_push_vector_proxy(push_vector_req)
00717             return push_vector_res
00718         except rospy.ServiceException, e:
00719             rospy.logwarn("Service did not process request: %s"%str(e))
00720             return None
00721 
00722     def initialize_singulation_push_vector(self):
00723         push_vector_req = SingulationPushRequest()
00724         push_vector_req.initialize = True
00725         push_vector_req.use_guided = True
00726         push_vector_req.no_push_calc = False
00727         rospy.loginfo('Initializing singulation push vector service.')
00728         self.singulation_push_vector_proxy(push_vector_req)
00729 
00730     def initialize_learning_push(self):
00731         push_vector_req = LearnPushRequest()
00732         push_vector_req.initialize = True
00733         push_vector_req.analyze_previous = False
00734         rospy.loginfo('Initializing learning push vector service.')
00735         try:
00736             self.learning_push_vector_proxy(push_vector_req)
00737         except rospy.ServiceException, e:
00738             rospy.logwarn("Service did not process request: %s"%str(e))
00739             return False
00740         return True
00741 
00742     def raise_and_look(self, request_table=True, init_arms=False, point_head_only=False):
00743         if request_table:
00744             table_req = LocateTableRequest()
00745             table_req.recalculate = True
00746         raise_req = RaiseAndLookRequest()
00747         raise_req.point_head_only = True
00748         raise_req.camera_frame = 'head_mount_kinect_rgb_link'
00749         # First make sure the head is looking the correct way before estimating
00750         # the table centroid
00751         # Also make sure the arms are out of the way
00752         raise_req.init_arms = True
00753         rospy.loginfo("Moving head")
00754         raise_res = self.raise_and_look_proxy(raise_req)
00755         if point_head_only:
00756             return
00757         if request_table:
00758             raise_req.have_table_centroid = True
00759             try:
00760                 rospy.loginfo("Getting table pose")
00761                 table_res = self.table_proxy(table_req);
00762             except rospy.ServiceException, e:
00763                 rospy.logwarn("Service did not process request: %s"%str(e))
00764                 return
00765             if not table_res.found_table:
00766                 return
00767             raise_req.table_centroid = table_res.table_centroid
00768         else:
00769             raise_req.have_table_centroid = False
00770 
00771         rospy.loginfo("Raising spine");
00772         raise_req.point_head_only = False
00773         raise_req.init_arms = init_arms
00774         raise_res = self.raise_and_look_proxy(raise_req)
00775 
00776     def overhead_feedback_push_object(self, which_arm, push_vector, goal_pose, controller_name,
00777                                       proxy_name, behavior_primitive, high_init=True, open_gripper=False):
00778         # Convert pose response to correct push request format
00779         push_req = FeedbackPushRequest()
00780         push_req.start_point.header = push_vector.header
00781         push_req.start_point.point = push_vector.start_point
00782         push_req.open_gripper = open_gripper
00783         push_req.goal_pose = goal_pose
00784         if behavior_primitive == OPEN_OVERHEAD_PUSH:
00785             push_req.open_gripper = True
00786         if _USE_LEARN_IO:
00787             push_req.learn_out_file_name = self.learn_out_file_name
00788 
00789         # Use the sent wrist yaw
00790         wrist_yaw = push_vector.push_angle
00791         push_req.wrist_yaw = wrist_yaw
00792 
00793         # Offset pose to not hit the object immediately
00794         push_req.start_point.point.x += -self.gripper_offset_dist*cos(wrist_yaw)
00795         push_req.start_point.point.y += -self.gripper_offset_dist*sin(wrist_yaw)
00796         push_req.start_point.point.z = self.overhead_start_z
00797         push_req.left_arm = (which_arm == 'l')
00798         push_req.right_arm = not push_req.left_arm
00799         push_req.high_arm_init = high_init
00800         push_req.controller_name = controller_name
00801         push_req.proxy_name = proxy_name
00802         push_req.behavior_primitive = behavior_primitive
00803 
00804         rospy.loginfo('Overhead push augmented start_point: (' +
00805                       str(push_req.start_point.point.x) + ', ' +
00806                       str(push_req.start_point.point.y) + ', ' +
00807                       str(push_req.start_point.point.z) + ')')
00808 
00809         rospy.loginfo("Calling overhead feedback pre push service")
00810         pre_push_res = self.overhead_feedback_pre_push_proxy(push_req)
00811         rospy.loginfo("Calling overhead feedback push service")
00812 
00813         if _TEST_START_POSE:
00814             raw_input('waiting for input to recall arm: ')
00815             push_res = FeedbackPushResponse()
00816         elif pre_push_res.failed_pre_position:
00817             rospy.logwarn('Failed to properly position in pre-push, aborting push')
00818             push_res = pre_push_res
00819         else:
00820             push_res = self.overhead_feedback_push_proxy(push_req)
00821         rospy.loginfo("Calling overhead feedback post push service")
00822         post_push_res = self.overhead_feedback_post_push_proxy(push_req)
00823         return push_res
00824 
00825     def gripper_feedback_push_object(self, which_arm, push_vector, goal_pose, controller_name,
00826                                      proxy_name, behavior_primitive, high_init=True, open_gripper=False):
00827         # Convert pose response to correct push request format
00828         push_req = FeedbackPushRequest()
00829         push_req.start_point.header = push_vector.header
00830         push_req.start_point.point = push_vector.start_point
00831         push_req.open_gripper = open_gripper
00832         push_req.goal_pose = goal_pose
00833         if _USE_LEARN_IO:
00834             push_req.learn_out_file_name = self.learn_out_file_name
00835 
00836         # Use the sent wrist yaw
00837         wrist_yaw = push_vector.push_angle
00838         push_req.wrist_yaw = wrist_yaw
00839         # Offset pose to not hit the object immediately
00840         if behavior_primitive == GRIPPER_PULL:
00841             offset_dist = self.gripper_pull_offset_dist
00842             start_z = self.gripper_pull_start_z
00843         elif behavior_primitive == PINCHER_PUSH:
00844             offset_dist = self.pincher_offset_dist
00845             start_z = self.pincher_start_z
00846             push_req.open_gripper = True
00847         else:
00848             offset_dist = self.gripper_offset_dist
00849             start_z = self.gripper_start_z
00850 
00851         rospy.loginfo('Gripper push pre-augmented start_point: (' +
00852                       str(push_req.start_point.point.x) + ', ' +
00853                       str(push_req.start_point.point.y) + ', ' +
00854                       str(push_req.start_point.point.z) + ')')
00855 
00856         push_req.start_point.point.x += -offset_dist*cos(wrist_yaw)
00857         push_req.start_point.point.y += -offset_dist*sin(wrist_yaw)
00858         push_req.start_point.point.z = start_z
00859         push_req.left_arm = (which_arm == 'l')
00860         push_req.right_arm = not push_req.left_arm
00861         push_req.high_arm_init = high_init
00862         push_req.controller_name = controller_name
00863         push_req.proxy_name = proxy_name
00864         push_req.behavior_primitive = behavior_primitive
00865 
00866         rospy.loginfo('Gripper push augmented start_point: (' +
00867                       str(push_req.start_point.point.x) + ', ' +
00868                       str(push_req.start_point.point.y) + ', ' +
00869                       str(push_req.start_point.point.z) + ')')
00870 
00871         rospy.loginfo("Calling gripper feedback pre push service")
00872         pre_push_res = self.gripper_feedback_pre_push_proxy(push_req)
00873 
00874         if _TEST_START_POSE:
00875             raw_input('waiting for input to recall arm: ')
00876             push_res = FeedbackPushResponse()
00877         elif pre_push_res.failed_pre_position:
00878             rospy.logwarn('Failed to properly position in pre-push, aborting push')
00879             push_res = pre_push_res
00880         else:
00881             rospy.loginfo("Calling gripper feedback push service")
00882             push_res = self.gripper_feedback_push_proxy(push_req)
00883 
00884         rospy.loginfo("Calling gripper feedback post push service")
00885         post_push_res = self.gripper_feedback_post_push_proxy(push_req)
00886         return push_res
00887 
00888     def feedback_sweep_object(self, which_arm, push_vector, goal_pose, controller_name,
00889                               proxy_name, behavior_primitive, high_init=True, open_gripper=False):
00890         # Convert pose response to correct push request format
00891         push_req = FeedbackPushRequest()
00892         push_req.start_point.header = push_vector.header
00893         push_req.start_point.point = push_vector.start_point
00894         push_req.open_gripper = open_gripper
00895         push_req.goal_pose = goal_pose
00896         if _USE_LEARN_IO:
00897             push_req.learn_out_file_name = self.learn_out_file_name
00898 
00899         # if push_req.left_arm:
00900         if push_vector.push_angle > 0:
00901             y_offset_dir = -1
00902             wrist_yaw = push_vector.push_angle - pi/2.0
00903         else:
00904             y_offset_dir = +1
00905             wrist_yaw = push_vector.push_angle + pi/2.0
00906         if abs(push_vector.push_angle) > pi/2:
00907             x_offset_dir = +1
00908         else:
00909             x_offset_dir = -1
00910 
00911         # Set offset in x y, based on distance
00912         push_req.wrist_yaw = wrist_yaw
00913         face_x_offset = self.sweep_face_offset_dist*x_offset_dir*abs(sin(wrist_yaw))
00914         face_y_offset = y_offset_dir*self.sweep_face_offset_dist*cos(wrist_yaw)
00915         wrist_x_offset = self.sweep_wrist_offset_dist*cos(wrist_yaw)
00916         wrist_y_offset = self.sweep_wrist_offset_dist*sin(wrist_yaw)
00917         rospy.loginfo('wrist_yaw: ' + str(wrist_yaw))
00918         rospy.loginfo('Face offset: (' + str(face_x_offset) + ', ' + str(face_y_offset) +')')
00919         rospy.loginfo('Wrist offset: (' + str(wrist_x_offset) + ', ' + str(wrist_y_offset) +')')
00920 
00921         push_req.start_point.point.x += face_x_offset + wrist_x_offset
00922         push_req.start_point.point.y += face_y_offset + wrist_y_offset
00923         push_req.start_point.point.z = self.sweep_start_z
00924         push_req.left_arm = (which_arm == 'l')
00925         push_req.right_arm = not push_req.left_arm
00926         push_req.high_arm_init = high_init
00927         push_req.controller_name = controller_name
00928         push_req.proxy_name = proxy_name
00929         push_req.behavior_primitive = behavior_primitive
00930 
00931         rospy.loginfo('Gripper sweep augmented start_point: (' +
00932                       str(push_req.start_point.point.x) + ', ' +
00933                       str(push_req.start_point.point.y) + ', ' +
00934                       str(push_req.start_point.point.z) + ')')
00935 
00936         rospy.loginfo("Calling feedback pre sweep service")
00937         pre_push_res = self.gripper_feedback_pre_sweep_proxy(push_req)
00938         rospy.loginfo("Calling feedback sweep service")
00939 
00940         if _TEST_START_POSE:
00941             raw_input('waiting for input to recall arm: ')
00942             push_res = FeedbackPushResponse()
00943         else:
00944             push_res = self.gripper_feedback_sweep_proxy(push_req)
00945         rospy.loginfo("Calling feedback post sweep service")
00946         post_push_res = self.gripper_feedback_post_sweep_proxy(push_req)
00947         return push_res
00948 
00949     def gripper_push_object(self, push_dist, which_arm, pose_res, high_init):
00950         # Convert pose response to correct push request format
00951         push_req = GripperPushRequest()
00952         push_req.start_point.header = pose_res.header
00953         push_req.start_point.point = pose_res.start_point
00954         push_req.arm_init = True
00955         push_req.arm_reset = True
00956         push_req.high_arm_init = True
00957 
00958         # Use the sent wrist yaw
00959         wrist_yaw = pose_res.push_angle
00960         push_req.wrist_yaw = wrist_yaw
00961         push_req.desired_push_dist = push_dist + abs(self.gripper_x_offset)
00962 
00963         # Offset pose to not hit the object immediately
00964         push_req.start_point.point.x += self.gripper_x_offset*cos(wrist_yaw)
00965         push_req.start_point.point.y += self.gripper_x_offset*sin(wrist_yaw)
00966         push_req.start_point.point.z = self.gripper_start_z
00967         push_req.left_arm = (which_arm == 'l')
00968         push_req.right_arm = not push_req.left_arm
00969 
00970         rospy.loginfo("Calling gripper pre push service")
00971         pre_push_res = self.gripper_pre_push_proxy(push_req)
00972         rospy.loginfo("Calling gripper push service")
00973         push_res = self.gripper_push_proxy(push_req)
00974         rospy.loginfo("Calling gripper post push service")
00975         post_push_res = self.gripper_post_push_proxy(push_req)
00976 
00977     def sweep_object(self, push_dist, which_arm, pose_res, high_init):
00978         # Convert pose response to correct push request format
00979         sweep_req = GripperPushRequest()
00980         sweep_req.left_arm = (which_arm == 'l')
00981         sweep_req.right_arm = not sweep_req.left_arm
00982         sweep_req.high_arm_init = True
00983 
00984         # Correctly set the wrist yaw
00985         if pose_res.push_angle > 0.0:
00986             y_offset_dir = -1
00987             wrist_yaw = pose_res.push_angle - pi/2
00988         else:
00989             wrist_yaw = pose_res.push_angle + pi/2
00990             y_offset_dir = +1
00991         if abs(pose_res.push_angle) > pi/2:
00992             x_offset_dir = +1
00993         else:
00994             x_offset_dir = -1
00995 
00996         # Set offset in x y, based on distance
00997         sweep_req.wrist_yaw = wrist_yaw
00998         face_x_offset = self.sweep_face_offset_dist*x_offset_dir*abs(sin(wrist_yaw))
00999         face_y_offset = y_offset_dir*self.sweep_face_offset_dist*cos(wrist_yaw)
01000         wrist_x_offset = self.sweep_wrist_offset_dist*cos(wrist_yaw)
01001         wrist_y_offset = self.sweep_wrist_offset_dist*sin(wrist_yaw)
01002 
01003         sweep_req.start_point.header = pose_res.header
01004         sweep_req.start_point.point = pose_res.start_point
01005         sweep_req.start_point.point.x += face_x_offset + wrist_x_offset
01006         sweep_req.start_point.point.y += face_y_offset + wrist_y_offset
01007         sweep_req.start_point.point.z = self.sweep_start_z
01008         sweep_req.arm_init = True
01009         sweep_req.arm_reset = True
01010 
01011         sweep_req.desired_push_dist = -y_offset_dir*(self.sweep_face_offset_dist + push_dist)
01012 
01013 
01014         rospy.loginfo("Calling gripper pre sweep service")
01015         pre_sweep_res = self.gripper_pre_sweep_proxy(sweep_req)
01016         rospy.loginfo("Calling gripper sweep service")
01017         sweep_res = self.gripper_sweep_proxy(sweep_req)
01018         rospy.loginfo("Calling gripper post sweep service")
01019         post_sweep_res = self.gripper_post_sweep_proxy(sweep_req)
01020 
01021     def overhead_push_object(self, push_dist, which_arm, pose_res, high_init):
01022         # Convert pose response to correct push request format
01023         push_req = GripperPushRequest()
01024         push_req.start_point.header = pose_res.header
01025         push_req.start_point.point = pose_res.start_point
01026         push_req.arm_init = True
01027         push_req.arm_reset = True
01028         push_req.high_arm_init = high_init
01029 
01030         # Correctly set the wrist yaw
01031         wrist_yaw = pose_res.push_angle
01032         push_req.wrist_yaw = wrist_yaw
01033         push_req.desired_push_dist = push_dist
01034 
01035         # Offset pose to not hit the object immediately
01036         push_req.start_point.point.x += self.overhead_offset_dist*cos(wrist_yaw)
01037         push_req.start_point.point.y += self.overhead_offset_dist*sin(wrist_yaw)
01038         push_req.start_point.point.z = self.overhead_start_z
01039         push_req.left_arm = (which_arm == 'l')
01040         push_req.right_arm = not push_req.left_arm
01041 
01042         rospy.loginfo("Calling pre overhead push service")
01043         pre_push_res = self.overhead_pre_push_proxy(push_req)
01044         rospy.loginfo("Calling overhead push service")
01045         push_res = self.overhead_push_proxy(push_req)
01046         rospy.loginfo("Calling post overhead push service")
01047         post_push_res = self.overhead_post_push_proxy(push_req)
01048 
01049     def out_of_workspace(self, init_pose):
01050         return (init_pose.x < self.min_workspace_x or init_pose.x > self.max_workspace_x or
01051                 init_pose.y < self.min_workspace_y or init_pose.y > self.max_workspace_y)
01052 
01053     def generate_random_table_pose(self, init_pose=None):
01054         if _USE_FIXED_GOAL or self.start_loc_use_fixed_goal:
01055             goal_pose = Pose2D()
01056             goal_pose.x = 0.65
01057             goal_pose.y = -0.3
01058             goal_pose.theta = 0
01059             if self.start_loc_use_fixed_goal:
01060                 goal_pose.y += self.start_loc_goal_y_delta
01061             return goal_pose
01062         min_x = self.min_workspace_x
01063         max_x = self.max_workspace_x
01064         min_y = self.min_workspace_y
01065         max_y = self.max_workspace_y
01066         max_theta = pi
01067         min_theta = -pi
01068 
01069         pose_not_found = True
01070         while pose_not_found:
01071             rand_pose = Pose2D()
01072             rand_pose.x = random.uniform(min_x, max_x)
01073             rand_pose.y = random.uniform(min_y, max_y)
01074             rand_pose.theta = random.uniform(min_theta, max_theta)
01075             pose_not_found = False
01076             # if (self.previous_rand_pose is not None and
01077             #     hypot(self.previous_rand_pose.x-rand_pose.x,
01078             #           self.previous_rand_pose.y-rand_pose.y) < self.min_new_pose_dist):
01079             #     pose_not_found = True
01080             if (init_pose is not None and
01081                 hypot(init_pose.x-rand_pose.x, init_pose.y-rand_pose.y) < self.min_new_pose_dist):
01082                 pose_not_found = True
01083 
01084         rospy.loginfo('Rand table pose is: (' + str(rand_pose.x) + ', ' + str(rand_pose.y) +
01085                       ', ' + str(rand_pose.theta) + ')')
01086         self.previous_rand_pose = rand_pose
01087         return rand_pose
01088 
01089     def shutdown_hook(self):
01090         rospy.loginfo('Cleaning up tabletop_executive_node on shutdown')
01091         if self.use_learning:
01092             self.finish_learning()
01093 
01094 if __name__ == '__main__':
01095     random.seed()
01096     learn_start_loc = False
01097     # Used for training data collection:
01098     # num_start_loc_sample_locs = 32
01099     # Used for testing data collection:
01100     num_start_loc_sample_locs = 5
01101     num_start_loc_pushes_per_sample = 3
01102     use_singulation = False
01103     use_learning = True
01104     use_guided = True
01105     running = True
01106     max_pushes = 500
01107     node = TabletopExecutive(use_singulation, use_learning)
01108     # Set the path to the learned parameter file here to use the learned SVM parameters
01109     hold_out_objects = ['small_brush', 'soap_box', 'camcorder', 'toothpaste', 'food_box', 'large_brush']
01110     for hold_out_object in hold_out_objects:
01111         if not running:
01112             break
01113         # hold_out_object = 'soap_box'
01114         rospy.loginfo('Testing with hold out object ' + hold_out_object)
01115         # rospy.loginfo('Collecting training data for object ' + hold_out_object)
01116         # start_loc_param_path = roslib.packages.get_pkg_dir('tabletop_pushing')+'/cfg/ichr_straight/push_svm_no_'+\
01117         #     hold_out_object+'.model'
01118         start_loc_param_path = roslib.packages.get_pkg_dir('tabletop_pushing')+'/cfg/ichr_rotate/push_svm_no_'+\
01119             hold_out_object+'.model'
01120         # start_loc_param_path = 'rand'
01121         # start_loc_param_path = ''
01122         if use_singulation:
01123             node.run_singulation(max_pushes, use_guided)
01124         elif use_learning:
01125             running = True
01126             need_object_id = True
01127             while need_object_id:
01128                 code_in = raw_input('Place object on table, enter id, and press <Enter>: ')
01129                 if len(code_in) > 0:
01130                     need_object_id = False
01131                 else:
01132                     rospy.logwarn("No object id given.")
01133             if code_in.lower().startswith('q'):
01134                 running = False
01135                 break
01136             if learn_start_loc:
01137                 node.init_loc_learning()
01138                 clean_exploration = node.run_start_loc_learning(code_in, num_start_loc_pushes_per_sample,
01139                                                                 num_start_loc_sample_locs, start_loc_param_path)
01140                 node.finish_learning()
01141             else:
01142                 node.start_loc_use_fixed_goal = False
01143                 node.init_loc_learning()
01144                 rospy.loginfo('Running push exploration')
01145                 clean_exploration = node.run_push_exploration(object_id=code_in)
01146                 node.finish_learning()
01147             if not clean_exploration:
01148                 rospy.loginfo('Not clean end to pushing stuff')
01149                 running = False
01150                 node.finish_learning()
01151                 break
01152 


tabletop_pushing
Author(s): Tucker Hermans
autogenerated on Wed Nov 27 2013 11:59:44