00001
00002
00003 """
00004 pick_and_place.py - Version 0.1 2014-08-01
00005
00006 Command the gripper to grasp a target object and move it to a new
00007 location, all while avoiding simulated obstacles.
00008
00009 Created for the Pi Robot Project: http://www.pirobot.org
00010 Copyright (c) 2014 Patrick Goebel. All rights reserved.
00011
00012 Adapted to the Turtlebot arm by Jorge Santos
00013
00014 This program is free software; you can redistribute it and/or modify
00015 it under the terms of the GNU General Public License as published by
00016 the Free Software Foundation; either version 2 of the License, or
00017 (at your option) any later version.5
00018
00019 This program is distributed in the hope that it will be useful,
00020 but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00022 GNU General Public License for more details at:
00023
00024 http://www.gnu.org/licenses/gpl.html
00025 """
00026
00027 import rospy, sys
00028 import moveit_commander
00029 from geometry_msgs.msg import PoseStamped
00030 from moveit_commander import MoveGroupCommander, PlanningSceneInterface
00031 from moveit_msgs.msg import PlanningScene, ObjectColor
00032 from moveit_msgs.msg import Grasp, GripperTranslation
00033 from moveit_msgs.msg import MoveItErrorCodes
00034 from trajectory_msgs.msg import JointTrajectory, JointTrajectoryPoint
00035 from tf.transformations import quaternion_from_euler
00036 from copy import deepcopy
00037
00038 GROUP_NAME_ARM = 'arm'
00039 GROUP_NAME_GRIPPER = 'gripper'
00040
00041 GRIPPER_FRAME = 'gripper_link'
00042
00043 GRIPPER_OPENED = [0.053]
00044 GRIPPER_CLOSED = [0.001]
00045 GRIPPER_NEUTRAL = [0.028]
00046 GRASP_OVERTIGHTEN = 0.002
00047
00048 GRIPPER_JOINT_NAMES = ['gripper_joint']
00049
00050 GRIPPER_EFFORT = [1.0]
00051
00052 REFERENCE_FRAME = '/base_link'
00053
00054 class MoveItDemo:
00055 def __init__(self):
00056
00057 moveit_commander.roscpp_initialize(sys.argv)
00058
00059 rospy.init_node('moveit_demo')
00060
00061
00062 scene = PlanningSceneInterface()
00063
00064
00065 self.scene_pub = rospy.Publisher('planning_scene', PlanningScene)
00066
00067
00068 self.gripper_pose_pub = rospy.Publisher('gripper_pose', PoseStamped)
00069
00070
00071 self.colors = dict()
00072
00073
00074 arm = MoveGroupCommander(GROUP_NAME_ARM)
00075
00076
00077 gripper = MoveGroupCommander(GROUP_NAME_GRIPPER)
00078
00079
00080 end_effector_link = arm.get_end_effector_link()
00081
00082
00083 arm.set_goal_position_tolerance(0.04)
00084 arm.set_goal_orientation_tolerance(0.1)
00085
00086
00087 arm.allow_replanning(True)
00088
00089
00090 arm.set_pose_reference_frame(REFERENCE_FRAME)
00091
00092
00093 arm.set_planning_time(5)
00094
00095
00096 max_pick_attempts = 5
00097
00098
00099 max_place_attempts = 5
00100
00101
00102 rospy.sleep(2)
00103
00104
00105 table_id = 'table'
00106 box1_id = 'box1'
00107 box2_id = 'box2'
00108 target_id = 'target'
00109 tool_id = 'tool'
00110
00111
00112 scene.remove_world_object(table_id)
00113 scene.remove_world_object(box1_id)
00114 scene.remove_world_object(box2_id)
00115 scene.remove_world_object(target_id)
00116 scene.remove_world_object(tool_id)
00117
00118
00119 scene.remove_attached_object(GRIPPER_FRAME, target_id)
00120
00121
00122 rospy.sleep(1)
00123
00124
00125 arm.set_named_target('right_up')
00126 arm.go()
00127
00128
00129 gripper.set_joint_value_target(GRIPPER_NEUTRAL)
00130 gripper.go()
00131
00132 rospy.sleep(1)
00133
00134
00135 table_ground = 0.4
00136
00137
00138 table_size = [0.2, 0.7, 0.01]
00139 box1_size = [0.1, 0.05, 0.05]
00140 box2_size = [0.05, 0.05, 0.15]
00141
00142
00143 target_size = [0.02, 0.01, 0.12]
00144
00145
00146 table_pose = PoseStamped()
00147 table_pose.header.frame_id = REFERENCE_FRAME
00148 table_pose.pose.position.x = 0.4
00149 table_pose.pose.position.y = 0.0
00150 table_pose.pose.position.z = table_ground + table_size[2] / 2.0
00151 table_pose.pose.orientation.w = 1.0
00152 scene.add_box(table_id, table_pose, table_size)
00153
00154 box1_pose = PoseStamped()
00155 box1_pose.header.frame_id = REFERENCE_FRAME
00156 box1_pose.pose.position.x = table_pose.pose.position.x - 0.04
00157 box1_pose.pose.position.y = -0.15
00158 box1_pose.pose.position.z = table_ground + table_size[2] + box1_size[2] / 2.0
00159 box1_pose.pose.orientation.w = 1.0
00160 scene.add_box(box1_id, box1_pose, box1_size)
00161
00162 box2_pose = PoseStamped()
00163 box2_pose.header.frame_id = REFERENCE_FRAME
00164 box2_pose.pose.position.x = table_pose.pose.position.x - 0.06
00165 box2_pose.pose.position.y = 0.13
00166 box2_pose.pose.position.z = table_ground + table_size[2] + box2_size[2] / 2.0
00167 box2_pose.pose.orientation.w = 1.0
00168 scene.add_box(box2_id, box2_pose, box2_size)
00169
00170
00171 target_pose = PoseStamped()
00172 target_pose.header.frame_id = REFERENCE_FRAME
00173 target_pose.pose.position.x = table_pose.pose.position.x - 0.03
00174 target_pose.pose.position.y = 0.02
00175 target_pose.pose.position.z = table_ground + table_size[2] + target_size[2] / 2.0
00176 target_pose.pose.orientation.w = 1.0
00177
00178
00179 scene.add_box(target_id, target_pose, target_size)
00180
00181
00182 self.setColor(table_id, 0.8, 0, 0, 1.0)
00183 self.setColor(box1_id, 0.8, 0.4, 0, 1.0)
00184 self.setColor(box2_id, 0.8, 0.4, 0, 1.0)
00185
00186
00187 self.setColor(target_id, 0.9, 0.9, 0, 1.0)
00188
00189
00190 self.sendColors()
00191
00192
00193 arm.set_support_surface_name(table_id)
00194
00195
00196 place_pose = PoseStamped()
00197 place_pose.header.frame_id = REFERENCE_FRAME
00198 place_pose.pose.position.x = table_pose.pose.position.x - 0.07
00199 place_pose.pose.position.y = -0.06
00200 place_pose.pose.position.z = table_ground + table_size[2] + target_size[2] / 2.0
00201 place_pose.pose.orientation.w = 1.0
00202
00203
00204 grasp_pose = target_pose
00205
00206
00207 grasp_pose.pose.position.y -= target_size[1] / 2.0
00208
00209
00210 grasps = self.make_grasps(grasp_pose, [target_id], [target_size[1] - GRASP_OVERTIGHTEN])
00211
00212
00213 for grasp in grasps:
00214 self.gripper_pose_pub.publish(grasp.grasp_pose)
00215 rospy.sleep(0.2)
00216
00217
00218 result = MoveItErrorCodes.FAILURE
00219 n_attempts = 0
00220
00221
00222 while result != MoveItErrorCodes.SUCCESS and n_attempts < max_pick_attempts:
00223 result = arm.pick(target_id, grasps)
00224 n_attempts += 1
00225 rospy.loginfo("Pick attempt: " + str(n_attempts))
00226 rospy.sleep(0.2)
00227
00228
00229 if result == MoveItErrorCodes.SUCCESS:
00230 success = False
00231 n_attempts = 0
00232
00233
00234 places = self.make_places(place_pose)
00235
00236
00237 while not success and n_attempts < max_place_attempts:
00238 for place in places:
00239
00240 self.gripper_pose_pub.publish(place)
00241 rospy.sleep(0.2)
00242
00243 success = arm.place(target_id, place)
00244 if success:
00245 break
00246 n_attempts += 1
00247 rospy.loginfo("Place attempt: " + str(n_attempts))
00248 rospy.sleep(0.2)
00249
00250 if not success:
00251 rospy.loginfo("Place operation failed after " + str(n_attempts) + " attempts.")
00252 else:
00253 rospy.loginfo("Pick operation failed after " + str(n_attempts) + " attempts.")
00254
00255
00256 arm.set_named_target('right_up')
00257 arm.go()
00258 arm.set_named_target('resting')
00259 arm.go()
00260
00261
00262 gripper.set_joint_value_target(GRIPPER_NEUTRAL)
00263 gripper.go()
00264
00265 rospy.sleep(1)
00266
00267
00268 moveit_commander.roscpp_shutdown()
00269
00270
00271 moveit_commander.os._exit(0)
00272
00273
00274 def make_gripper_posture(self, joint_positions):
00275
00276 t = JointTrajectory()
00277
00278
00279 t.joint_names = GRIPPER_JOINT_NAMES
00280
00281
00282 tp = JointTrajectoryPoint()
00283
00284
00285 tp.positions = joint_positions
00286
00287
00288 tp.effort = GRIPPER_EFFORT
00289
00290 tp.time_from_start = rospy.Duration(1.0)
00291
00292
00293 t.points.append(tp)
00294
00295
00296 return t
00297
00298
00299 def make_gripper_translation(self, min_dist, desired, vector):
00300
00301 g = GripperTranslation()
00302
00303
00304 g.direction.vector.x = vector[0]
00305 g.direction.vector.y = vector[1]
00306 g.direction.vector.z = vector[2]
00307
00308
00309 g.direction.header.frame_id = GRIPPER_FRAME
00310
00311
00312 g.min_distance = min_dist
00313 g.desired_distance = desired
00314
00315 return g
00316
00317
00318 def make_grasps(self, initial_pose_stamped, allowed_touch_objects, grasp_opening=[0]):
00319
00320 g = Grasp()
00321
00322
00323
00324 g.pre_grasp_posture = self.make_gripper_posture(GRIPPER_OPENED)
00325 g.grasp_posture = self.make_gripper_posture(grasp_opening)
00326
00327
00328 g.pre_grasp_approach = self.make_gripper_translation(0.01, 0.1, [1.0, 0.0, 0.0])
00329 g.post_grasp_retreat = self.make_gripper_translation(0.1, 0.15, [0.0, -1.0, 1.0])
00330
00331
00332 g.grasp_pose = initial_pose_stamped
00333
00334
00335 pitch_vals = [0, 0.1, -0.1, 0.2, -0.2, 0.4, -0.4]
00336
00337
00338 yaw_vals = [0]
00339
00340
00341 grasps = []
00342
00343
00344 for y in yaw_vals:
00345 for p in pitch_vals:
00346
00347 q = quaternion_from_euler(0, p, y)
00348
00349
00350 g.grasp_pose.pose.orientation.x = q[0]
00351 g.grasp_pose.pose.orientation.y = q[1]
00352 g.grasp_pose.pose.orientation.z = q[2]
00353 g.grasp_pose.pose.orientation.w = q[3]
00354
00355
00356 g.id = str(len(grasps))
00357
00358
00359 g.allowed_touch_objects = allowed_touch_objects
00360
00361
00362 g.max_contact_force = 0
00363
00364
00365 g.grasp_quality = 1.0 - abs(p)
00366
00367
00368 grasps.append(deepcopy(g))
00369
00370
00371 return grasps
00372
00373
00374 def make_places(self, init_pose):
00375
00376 place = PoseStamped()
00377
00378
00379 place = init_pose
00380
00381
00382 x_vals = [0, 0.005, 0.01, 0.015, -0.005, -0.01, -0.015]
00383
00384
00385 y_vals = [0, 0.005, 0.01, 0.015, -0.005, -0.01, -0.015]
00386
00387
00388
00389
00390 pitch_vals = [0]
00391
00392
00393 yaw_vals = [0]
00394
00395
00396 places = []
00397
00398
00399 for y in yaw_vals:
00400 for p in pitch_vals:
00401 for y in y_vals:
00402 for x in x_vals:
00403 place.pose.position.x = init_pose.pose.position.x + x
00404 place.pose.position.y = init_pose.pose.position.y + y
00405
00406
00407 q = quaternion_from_euler(0, p, y)
00408
00409
00410 place.pose.orientation.x = q[0]
00411 place.pose.orientation.y = q[1]
00412 place.pose.orientation.z = q[2]
00413 place.pose.orientation.w = q[3]
00414
00415
00416 places.append(deepcopy(place))
00417
00418
00419 return places
00420
00421
00422 def setColor(self, name, r, g, b, a=0.9):
00423
00424 color = ObjectColor()
00425
00426
00427 color.id = name
00428
00429
00430 color.color.r = r
00431 color.color.g = g
00432 color.color.b = b
00433 color.color.a = a
00434
00435
00436 self.colors[name] = color
00437
00438
00439 def sendColors(self):
00440
00441 p = PlanningScene()
00442
00443
00444 p.is_diff = True
00445
00446
00447 for color in self.colors.values():
00448 p.object_colors.append(color)
00449
00450
00451 self.scene_pub.publish(p)
00452
00453 if __name__ == "__main__":
00454 MoveItDemo()