00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 import roslib; roslib.load_manifest('tabletop_pushing')
00035 import rospy
00036 import actionlib
00037 import hrl_pr2_lib.linear_move as lm
00038 import hrl_pr2_lib.pr2 as pr2
00039 import hrl_lib.tf_utils as tfu
00040 from geometry_msgs.msg import PoseStamped
00041 import tf
00042 import numpy as np
00043 from tabletop_pushing.srv import *
00044 from tabletop_pushing.msg import *
00045 from math import sin, cos, pi, fabs
00046 import sys
00047
00048 GRIPPER_PUSH = 0
00049 GRIPPER_SWEEP = 1
00050 OVERHEAD_PUSH = 2
00051 OVERHEAD_PULL = 3
00052
00053 class SingulationExecutive:
00054
00055 def __init__(self, use_fake_push_pose=False):
00056 rospy.init_node('tabletop_executive_node',log_level=rospy.DEBUG)
00057
00058 self.min_push_dist = rospy.get_param('~min_push_dist', 0.07)
00059 self.max_push_dist = rospy.get_param('~mix_push_dist', 0.3)
00060 self.use_overhead_x_thresh = rospy.get_param('~use_overhead_x_thresh',
00061 0.55)
00062 self.use_sweep_angle_thresh = rospy.get_param('~use_sweep_angle_thresh',
00063 pi*0.4)
00064 self.use_pull_angle_thresh = rospy.get_param('~use_sweep_angle_thresh',
00065 pi*0.525)
00066 self.use_same_side_y_thresh = rospy.get_param('~use_same_side_y_thresh',
00067 0.3)
00068 self.use_same_side_x_thresh = rospy.get_param('~use_same_side_x_thresh',
00069 0.8)
00070
00071
00072
00073 self.gripper_x_offset = rospy.get_param('~gripper_push_start_x_offset',
00074 -0.05)
00075 self.gripper_y_offset = rospy.get_param('~gripper_push_start_y_offset',
00076 0.0)
00077 self.gripper_start_z = rospy.get_param('~gripper_push_start_z',
00078 -0.25)
00079
00080 self.sweep_x_offset = rospy.get_param('~gripper_sweep_start_x_offset',
00081 -0.01)
00082 self.sweep_y_offset = rospy.get_param('~gripper_sweep_start_y_offset',
00083 0.03)
00084 self.sweep_start_z = rospy.get_param('~gripper_sweep_start_z',
00085 -0.22)
00086
00087 self.overhead_x_offset = rospy.get_param('~overhead_push_start_x_offset',
00088 0.00)
00089 self.overhead_y_offset = rospy.get_param('~overhead_push_start_y_offset',
00090 0.00)
00091 self.overhead_start_z = rospy.get_param('~overhead_push_start_z',
00092 -0.25)
00093 self.pull_dist_offset = rospy.get_param('~overhead_pull_dist_offset',
00094 0.05)
00095 self.pull_start_z = rospy.get_param('~overhead_push_start_z',
00096 -0.27)
00097
00098 self.push_pose_proxy = rospy.ServiceProxy('get_push_pose', PushVector)
00099 self.gripper_push_proxy = rospy.ServiceProxy('gripper_push',
00100 GripperPush)
00101 self.gripper_pre_push_proxy = rospy.ServiceProxy('gripper_pre_push',
00102 GripperPush)
00103 self.gripper_post_push_proxy = rospy.ServiceProxy('gripper_post_push',
00104 GripperPush)
00105 self.gripper_pre_sweep_proxy = rospy.ServiceProxy('gripper_pre_sweep',
00106 GripperPush)
00107 self.gripper_sweep_proxy = rospy.ServiceProxy('gripper_sweep',
00108 GripperPush)
00109 self.gripper_post_sweep_proxy = rospy.ServiceProxy('gripper_post_sweep',
00110 GripperPush)
00111 self.overhead_pre_push_proxy = rospy.ServiceProxy('overhead_pre_push',
00112 GripperPush)
00113 self.overhead_push_proxy = rospy.ServiceProxy('overhead_push',
00114 GripperPush)
00115 self.overhead_post_push_proxy = rospy.ServiceProxy('overhead_post_push',
00116 GripperPush)
00117 self.overhead_pre_pull_proxy = rospy.ServiceProxy('overhead_pre_pull',
00118 GripperPush)
00119 self.overhead_pull_proxy = rospy.ServiceProxy('overhead_pull',
00120 GripperPush)
00121 self.overhead_post_pull_proxy = rospy.ServiceProxy('overhead_post_pull',
00122 GripperPush)
00123 self.raise_and_look_proxy = rospy.ServiceProxy('raise_and_look',
00124 RaiseAndLook)
00125 self.table_proxy = rospy.ServiceProxy('get_table_location', LocateTable)
00126
00127 self.use_fake_push_pose = use_fake_push_pose
00128 self.push_count = 0
00129
00130 def run(self, num_pushes=1, use_guided=True):
00131
00132 self.raise_and_look()
00133
00134 self.initialize_push_pose();
00135
00136
00137 for i in xrange(num_pushes):
00138 pose_res = self.request_singulation_push(use_guided)
00139
00140
00141 if pose_res is None:
00142 rospy.logwarn("pose_res is None. Exiting pushing");
00143 break
00144 if pose_res.no_push:
00145 rospy.loginfo("No push. Exiting pushing.");
00146 break
00147 rospy.loginfo('Performing push #' + str(i+1))
00148
00149 rospy.loginfo('Push start_point: (' + str(pose_res.start_point.x) +
00150 ', ' + str(pose_res.start_point.y) +
00151 ', ' + str(pose_res.start_point.z) + ')')
00152 rospy.loginfo('Push angle: ' + str(pose_res.push_angle))
00153 rospy.loginfo('Push dist: ' + str(pose_res.push_dist))
00154
00155
00156
00157 if fabs(pose_res.push_angle) > self.use_pull_angle_thresh:
00158 push_opt = OVERHEAD_PULL
00159 elif pose_res.start_point.x < self.use_overhead_x_thresh:
00160 push_opt = OVERHEAD_PUSH
00161 elif fabs(pose_res.push_angle) > self.use_sweep_angle_thresh:
00162 push_opt = GRIPPER_SWEEP
00163 else:
00164 push_opt = GRIPPER_PUSH
00165
00166
00167
00168 if (fabs(pose_res.start_point.y) > self.use_same_side_y_thresh or
00169 pose_res.start_point.x > self.use_same_side_x_thresh):
00170 if (pose_res.start_point.y < 0):
00171 which_arm = 'r'
00172 rospy.loginfo('Setting arm to right because of limits')
00173 else:
00174 which_arm = 'l'
00175 rospy.loginfo('Setting arm to left because of limits')
00176 elif pose_res.push_angle > 0:
00177 which_arm = 'r'
00178 rospy.loginfo('Setting arm to right because of angle')
00179 else:
00180 which_arm = 'l'
00181 rospy.loginfo('Setting arm to left because of angle')
00182
00183 push_dist = pose_res.push_dist
00184 push_dist = max(min(push_dist, self.max_push_dist),
00185 self.min_push_dist)
00186 if push_opt == GRIPPER_PUSH:
00187 self.gripper_push_object(push_dist, which_arm, pose_res)
00188 if push_opt == GRIPPER_SWEEP:
00189 self.sweep_object(push_dist, which_arm, pose_res)
00190 if push_opt == OVERHEAD_PUSH:
00191 self.overhead_push_object(push_dist, which_arm, pose_res)
00192 if push_opt == OVERHEAD_PULL:
00193 self.overhead_pull_object(push_dist, which_arm, pose_res)
00194 rospy.loginfo('Done performing push behavior.\n')
00195
00196 if not (pose_res is None):
00197 rospy.loginfo('Singulated objects: ' + str(pose_res.singulated))
00198 rospy.loginfo('Final estimate of ' + str(pose_res.num_objects) +
00199 ' objects')
00200
00201 def request_singulation_push(self, use_guided=True, which_arm='l'):
00202 if (self.use_fake_push_pose):
00203 return request_fake_singulation_push(which_arm)
00204 pose_req = PushVectorRequest()
00205 pose_req.use_guided = use_guided
00206 pose_req.initialize = False
00207 pose_req.no_push_calc = False
00208 rospy.loginfo("Calling push pose service")
00209 try:
00210 pose_res = self.push_pose_proxy(pose_req)
00211 return pose_res
00212 except rospy.ServiceException, e:
00213 rospy.logwarn("Service did not process request: %s"%str(e))
00214 return None
00215
00216 def request_fake_singulation_push(self, which_arm):
00217 pose_res = PushVectorResponse()
00218 push_opt = GRIPPER_PUSH
00219 if push_opt == GRIPPER_PUSH:
00220 pose_res = PushVectorResponse()
00221 pose_res.start_point.x = 0.5
00222 pose_res.header.frame_id = '/torso_lift_link'
00223 pose_res.header.stamp = rospy.Time(0)
00224 if which_arm == 'l':
00225 pose_res.start_point.y = 0.3 - self.push_count*0.15
00226 else:
00227 pose_res.start_point.y = -0.3 + self.push_count*0.15
00228 pose_res.start_point.z = -0.22
00229 elif push_opt == GRIPPER_SWEEP:
00230 pose_res.header.frame_id = '/torso_lift_link'
00231 pose_res.header.stamp = rospy.Time(0)
00232 pose_res.start_point.x = 0.75
00233 if which_arm == 'l':
00234 pose_res.start_point.y = 0.05
00235 else:
00236 pose_res.start_point.y = -0.15
00237 pose_res.start_point.z = -0.25
00238 elif push_opt == OVERHEAD_PUSH:
00239 pose_res.header.frame_id = '/torso_lift_link'
00240 pose_res.header.stamp = rospy.Time(0)
00241 pose_res.start_point.x = 0.7
00242 pose_res.start_point.y = 0.0
00243 pose_res.start_point.z = -0.25
00244 pose_res.push_dist = 0.15
00245 pose_res.push_angle = 0.75*pi
00246 return pose_res
00247
00248 def initialize_push_pose(self):
00249 pose_req = PushVectorRequest()
00250 pose_req.initialize = True
00251 pose_req.use_guided = True
00252 pose_req.no_push_calc = False
00253 rospy.loginfo('Initializing push pose service.')
00254 self.push_pose_proxy(pose_req)
00255
00256 def raise_and_look(self):
00257 table_req = LocateTableRequest()
00258 table_req.recalculate = True
00259 raise_req = RaiseAndLookRequest()
00260 raise_req.point_head_only = True
00261 raise_req.camera_frame = 'openni_rgb_frame'
00262
00263
00264
00265 raise_req.init_arms = True
00266 rospy.loginfo("Moving head and arms")
00267 raise_res = self.raise_and_look_proxy(raise_req)
00268 try:
00269 rospy.loginfo("Getting table pose")
00270 table_res = self.table_proxy(table_req);
00271 except rospy.ServiceException, e:
00272 rospy.logwarn("Service did not process request: %s"%str(e))
00273 return
00274 if not table_res.found_table:
00275 return
00276 raise_req.table_centroid = table_res.table_centroid
00277
00278
00279
00280 rospy.loginfo("Raising spine");
00281 raise_req.point_head_only = False
00282 raise_req.init_arms = False
00283 raise_res = self.raise_and_look_proxy(raise_req)
00284
00285 def gripper_push_object(self, push_dist, which_arm, pose_res):
00286
00287 push_req = GripperPushRequest()
00288 push_req.start_point.header = pose_res.header
00289 push_req.start_point.point = pose_res.start_point
00290 push_req.arm_init = True
00291 push_req.arm_reset = True
00292 push_req.high_arm_init = True
00293
00294
00295 wrist_yaw = pose_res.push_angle
00296 push_req.wrist_yaw = wrist_yaw
00297 push_req.desired_push_dist = push_dist + abs(self.gripper_x_offset)
00298
00299
00300 push_req.start_point.point.x += self.gripper_x_offset*cos(wrist_yaw)
00301 push_req.start_point.point.y += self.gripper_x_offset*sin(wrist_yaw)
00302 push_req.start_point.point.z = self.gripper_start_z
00303 push_req.left_arm = (which_arm == 'l')
00304 push_req.right_arm = not push_req.left_arm
00305
00306 rospy.loginfo("Calling gripper pre push service")
00307 pre_push_res = self.gripper_pre_push_proxy(push_req)
00308 rospy.loginfo("Calling gripper push service")
00309 push_res = self.gripper_push_proxy(push_req)
00310 rospy.loginfo("Calling gripper post push service")
00311 post_push_res = self.gripper_post_push_proxy(push_req)
00312
00313 def sweep_object(self, push_dist, which_arm, pose_res):
00314
00315 sweep_req = GripperPushRequest()
00316 sweep_req.left_arm = (which_arm == 'l')
00317 sweep_req.right_arm = not sweep_req.left_arm
00318 push_req.high_arm_init = True
00319
00320
00321 if pose_res.push_angle > 0:
00322 y_offset_dir = -1
00323 else:
00324 y_offset_dir = +1
00325
00326
00327 if pose_res.push_angle > 0.0:
00328 wrist_yaw = pose_res.push_angle - pi/2
00329 else:
00330 wrist_yaw = pose_res.push_angle + pi/2
00331 sweep_req.wrist_yaw = wrist_yaw
00332 sweep_req.desired_push_dist = -y_offset_dir*(self.sweep_y_offset +
00333 push_dist)
00334
00335
00336 sweep_req.start_point.header = pose_res.header
00337 sweep_req.start_point.point = pose_res.start_point
00338 sweep_req.start_point.point.x += self.sweep_x_offset
00339 sweep_req.start_point.point.y += y_offset_dir*self.sweep_y_offset
00340 sweep_req.start_point.point.z = self.sweep_start_z
00341 sweep_req.arm_init = True
00342 sweep_req.arm_reset = True
00343
00344 rospy.loginfo("Calling gripper pre sweep service")
00345 pre_sweep_res = self.gripper_pre_sweep_proxy(sweep_req)
00346 rospy.loginfo("Calling gripper sweep service")
00347 sweep_res = self.gripper_sweep_proxy(sweep_req)
00348 rospy.loginfo("Calling gripper post sweep service")
00349 post_sweep_res = self.gripper_post_sweep_proxy(sweep_req)
00350
00351 def overhead_push_object(self, push_dist, which_arm, pose_res):
00352
00353 push_req = GripperPushRequest()
00354 push_req.start_point.header = pose_res.header
00355 push_req.start_point.point = pose_res.start_point
00356 push_req.arm_init = True
00357 push_req.arm_reset = True
00358 push_req.high_arm_init = True
00359
00360
00361 wrist_yaw = pose_res.push_angle
00362 push_req.wrist_yaw = wrist_yaw
00363 push_req.desired_push_dist = push_dist
00364
00365
00366 push_req.start_point.point.x += self.overhead_x_offset*cos(wrist_yaw)
00367 push_req.start_point.point.y += self.overhead_x_offset*sin(wrist_yaw)
00368 push_req.start_point.point.z = self.overhead_start_z
00369 push_req.left_arm = (which_arm == 'l')
00370 push_req.right_arm = not push_req.left_arm
00371
00372 rospy.loginfo("Calling pre overhead push service")
00373 pre_push_res = self.overhead_pre_push_proxy(push_req)
00374 rospy.loginfo("Calling overhead push service")
00375 push_res = self.overhead_push_proxy(push_req)
00376 rospy.loginfo("Calling post overhead push service")
00377 post_push_res = self.overhead_post_push_proxy(push_req)
00378
00379 def overhead_pull_object(self, push_dist, which_arm, pose_res):
00380
00381 push_req = GripperPushRequest()
00382 push_req.start_point.header = pose_res.header
00383 push_req.start_point.point = pose_res.start_point
00384 push_req.arm_init = True
00385 push_req.arm_reset = True
00386 push_req.high_arm_init = True
00387
00388 wrist_yaw = pose_res.push_angle
00389
00390 while wrist_yaw < -pi*0.5:
00391 wrist_yaw += pi
00392 while wrist_yaw > pi*0.5:
00393 wrist_yaw -= pi
00394 push_req.wrist_yaw = wrist_yaw
00395
00396 push_req.desired_push_dist = push_dist + self.pull_dist_offset
00397
00398
00399 rospy.loginfo('Pre pull offset (x,y): (' +
00400 str(push_req.start_point.point.x) + ', ' +
00401 str(push_req.start_point.point.y) + ')')
00402 push_req.start_point.point.x += self.pull_dist_offset*cos(wrist_yaw)
00403 push_req.start_point.point.y += self.pull_dist_offset*sin(wrist_yaw)
00404 push_req.start_point.point.z = self.pull_start_z
00405 push_req.left_arm = (which_arm == 'l')
00406 push_req.right_arm = not push_req.left_arm
00407
00408 rospy.loginfo('Post pull offset (x,y): (' +
00409 str(push_req.start_point.point.x) + ', ' +
00410 str(push_req.start_point.point.y) + ')')
00411
00412 rospy.loginfo("Calling pre overhead pull service")
00413 pre_push_res = self.overhead_pre_pull_proxy(push_req)
00414 rospy.loginfo("Calling overhead pull service")
00415 push_res = self.overhead_pull_proxy(push_req)
00416 rospy.loginfo("Calling post overhead pull service")
00417 post_push_res = self.overhead_post_pull_proxy(push_req)
00418
00419 if __name__ == '__main__':
00420 guided = True
00421 node = SingulationExecutive(False)
00422 node.run(50, guided)