4 pick_and_place.py - Version 0.1 2014-08-01 6 Command the gripper to grasp a target object and move it to a new 7 location, all while avoiding simulated obstacles. 9 Before running, set environment variable TURTLEBOT_ARM1 to either: 10 turtlebot - for original turtlebot arm 11 pincher - for PhantomX Pincher arm 13 Created for the Pi Robot Project: http://www.pirobot.org 14 Copyright (c) 2014 Patrick Goebel. All rights reserved. 16 Adapted to the Turtlebot arm by Jorge Santos 18 This program is free software; you can redistribute it and/or modify 19 it under the terms of the GNU General Public License as published by 20 the Free Software Foundation; either version 2 of the License, or 21 (at your option) any later version.5 23 This program is distributed in the hope that it will be useful, 24 but WITHOUT ANY WARRANTY; without even the implied warranty of 25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 GNU General Public License for more details at: 28 http://www.gnu.org/licenses/gpl.html 35 import tf2_geometry_msgs
36 import moveit_commander
38 from math
import atan2
39 from copy
import deepcopy
40 from geometry_msgs.msg
import Pose, PoseStamped
41 from moveit_msgs.msg
import PlanningScene, ObjectColor
42 from moveit_msgs.msg
import CollisionObject, AttachedCollisionObject
43 from moveit_msgs.msg
import Grasp, GripperTranslation
44 from moveit_msgs.msg
import MoveItErrorCodes
45 from trajectory_msgs.msg
import JointTrajectory, JointTrajectoryPoint
46 from moveit_commander
import MoveGroupCommander, PlanningSceneInterface
47 from tf.transformations
import quaternion_from_euler, quaternion_matrix, quaternion_from_matrix
49 GROUP_NAME_ARM =
'arm' 50 GROUP_NAME_GRIPPER =
'gripper' 52 GRIPPER_FRAME =
'gripper_link' 53 GRIPPER_JOINT_NAMES = [
'gripper_joint']
54 GRIPPER_EFFORT = [1.0]
55 GRIPPER_PARAM =
'/gripper_controller' 57 REFERENCE_FRAME =
'base_link' 58 ARM_BASE_FRAME =
'arm_base_link' 63 moveit_commander.roscpp_initialize(sys.argv)
65 rospy.init_node(
'moveit_demo')
71 except rospy.ROSException
as err:
72 rospy.logerr(
"MoveItDemo: could not start tf buffer client: " + str(err))
75 self.
gripper_opened = [rospy.get_param(GRIPPER_PARAM +
"/max_opening") - 0.01]
76 self.
gripper_closed = [rospy.get_param(GRIPPER_PARAM +
"/min_opening") + 0.01]
83 self.
scene = PlanningSceneInterface()
86 self.
scene_pub = rospy.Publisher(
'planning_scene', PlanningScene, queue_size=10)
95 arm = MoveGroupCommander(GROUP_NAME_ARM)
98 gripper = MoveGroupCommander(GROUP_NAME_GRIPPER)
101 end_effector_link = arm.get_end_effector_link()
104 arm.set_goal_position_tolerance(0.04)
105 arm.set_goal_orientation_tolerance(0.01)
108 arm.allow_replanning(
True)
111 arm.set_pose_reference_frame(REFERENCE_FRAME)
114 arm.set_planning_time(5)
117 max_pick_attempts = 3
120 max_place_attempts = 3
121 rospy.loginfo(
"Scaling for MoveIt timeout=" + str(rospy.get_param(
'/move_group/trajectory_execution/allowed_execution_duration_scaling')))
131 self.scene.remove_world_object(table_id)
132 self.scene.remove_world_object(box1_id)
133 self.scene.remove_world_object(box2_id)
134 self.scene.remove_world_object(target_id)
135 self.scene.remove_world_object(tool_id)
138 self.scene.remove_attached_object(GRIPPER_FRAME, target_id)
144 rospy.loginfo(
"Set Arm: right_up")
145 arm.set_named_target(
'right_up')
147 rospy.logwarn(
" Go failed")
152 if gripper.go() !=
True:
153 rospy.logwarn(
" Go failed")
159 table_size = [0.2, 0.7, 0.01]
160 box1_size = [0.1, 0.05, 0.05]
161 box2_size = [0.05, 0.05, 0.15]
164 target_size = [0.02, 0.005, 0.12]
167 table_pose = PoseStamped()
168 table_pose.header.frame_id = REFERENCE_FRAME
169 table_pose.pose.position.x = 0.36
170 table_pose.pose.position.y = 0.0
171 table_pose.pose.position.z = table_ground + table_size[2] / 2.0
172 table_pose.pose.orientation.w = 1.0
173 self.scene.add_box(table_id, table_pose, table_size)
175 box1_pose = PoseStamped()
176 box1_pose.header.frame_id = REFERENCE_FRAME
177 box1_pose.pose.position.x = table_pose.pose.position.x - 0.04
178 box1_pose.pose.position.y = 0.0
179 box1_pose.pose.position.z = table_ground + table_size[2] + box1_size[2] / 2.0
180 box1_pose.pose.orientation.w = 1.0
181 self.scene.add_box(box1_id, box1_pose, box1_size)
183 box2_pose = PoseStamped()
184 box2_pose.header.frame_id = REFERENCE_FRAME
185 box2_pose.pose.position.x = table_pose.pose.position.x - 0.06
186 box2_pose.pose.position.y = 0.2
187 box2_pose.pose.position.z = table_ground + table_size[2] + box2_size[2] / 2.0
188 box2_pose.pose.orientation.w = 1.0
189 self.scene.add_box(box2_id, box2_pose, box2_size)
192 target_pose = PoseStamped()
193 target_pose.header.frame_id = REFERENCE_FRAME
194 target_pose.pose.position.x = table_pose.pose.position.x - 0.03
195 target_pose.pose.position.y = 0.1
196 target_pose.pose.position.z = table_ground + table_size[2] + target_size[2] / 2.0
197 target_pose.pose.orientation.w = 1.0
200 self.scene.add_box(target_id, target_pose, target_size)
203 self.
setColor(table_id, 0.8, 0, 0, 1.0)
204 self.
setColor(box1_id, 0.8, 0.4, 0, 1.0)
205 self.
setColor(box2_id, 0.8, 0.4, 0, 1.0)
208 self.
setColor(target_id, 0.9, 0.9, 0, 1.0)
214 arm.set_support_surface_name(table_id)
217 place_pose = PoseStamped()
218 place_pose.header.frame_id = REFERENCE_FRAME
219 place_pose.pose.position.x = table_pose.pose.position.x - 0.03
220 place_pose.pose.position.y = -0.15
221 place_pose.pose.position.z = table_ground + table_size[2] + target_size[2] / 2.0
222 place_pose.pose.orientation.w = 1.0
225 grasp_pose = target_pose
228 grasp_pose.pose.position.y -= target_size[1] / 2.0
234 result = MoveItErrorCodes.FAILURE
238 while result != MoveItErrorCodes.SUCCESS
and n_attempts < max_pick_attempts:
239 rospy.loginfo(
"Pick attempt #" + str(n_attempts))
242 self.gripper_pose_pub.publish(grasp.grasp_pose)
245 result = arm.pick(target_id, grasps)
246 if result == MoveItErrorCodes.SUCCESS:
253 if result == MoveItErrorCodes.SUCCESS:
254 rospy.loginfo(
" Pick: Done!")
262 while not success
and n_attempts < max_place_attempts:
263 rospy.loginfo(
"Place attempt #" + str(n_attempts))
266 self.gripper_pose_pub.publish(place)
269 success = arm.place(target_id, place)
277 rospy.logerr(
"Place operation failed after " + str(n_attempts) +
" attempts.")
279 rospy.loginfo(
" Place: Done!")
281 rospy.logerr(
"Pick operation failed after " + str(n_attempts) +
" attempts.")
284 arm.set_named_target(
'right_up')
287 arm.set_named_target(
'resting')
297 moveit_commander.roscpp_shutdown()
300 moveit_commander.os._exit(0)
305 t = JointTrajectory()
308 t.header.stamp = rospy.get_rostime()
309 t.joint_names = GRIPPER_JOINT_NAMES
312 tp = JointTrajectoryPoint()
315 tp.positions = joint_positions
318 tp.effort = GRIPPER_EFFORT
320 tp.time_from_start = rospy.Duration(0.0)
331 g = GripperTranslation()
334 g.direction.vector.x = vector[0]
335 g.direction.vector.y = vector[1]
336 g.direction.vector.z = vector[2]
339 g.direction.header.frame_id = GRIPPER_FRAME
342 g.min_distance = min_dist
343 g.desired_distance = desired
348 def make_grasps(self, initial_pose_stamped, allowed_touch_objects, grasp_opening=[0]):
362 g.grasp_pose = initial_pose_stamped
365 pitch_vals = [0, 0.1, -0.1, 0.2, -0.2, 0.4, -0.4]
369 target_pose_arm_ref = self._tf2_buff.transform(initial_pose_stamped, ARM_BASE_FRAME)
370 x = target_pose_arm_ref.pose.position.x
371 y = target_pose_arm_ref.pose.position.y
372 yaw_vals = [atan2(y, x) + inc
for inc
in [0, 0.1,-0.1]]
379 for pitch
in pitch_vals:
381 q = quaternion_from_euler(0, pitch, yaw)
384 g.grasp_pose.pose.orientation.x = q[0]
385 g.grasp_pose.pose.orientation.y = q[1]
386 g.grasp_pose.pose.orientation.z = q[2]
387 g.grasp_pose.pose.orientation.w = q[3]
390 g.id = str(len(grasps))
393 g.allowed_touch_objects = allowed_touch_objects
396 g.max_contact_force = 0
399 g.grasp_quality = 1.0 - abs(pitch)
402 grasps.append(deepcopy(g))
410 place = PoseStamped()
416 x_vals = [0, 0.005, -0.005]
419 y_vals = [0, 0.005, -0.005, 0.01, -0.01]
428 for pitch
in pitch_vals:
431 place.pose.position.x = init_pose.pose.position.x + dx
432 place.pose.position.y = init_pose.pose.position.y + dy
436 target_pose_arm_ref = self._tf2_buff.transform(place, ARM_BASE_FRAME)
437 x = target_pose_arm_ref.pose.position.x
438 y = target_pose_arm_ref.pose.position.y
442 q = quaternion_from_euler(0, pitch, yaw)
445 place.pose.orientation.x = q[0]
446 place.pose.orientation.y = q[1]
447 place.pose.orientation.z = q[2]
448 place.pose.orientation.w = q[3]
455 acobjs = self.scene.get_attached_objects([target_id])
456 aco_pose = self.
get_pose(acobjs[target_id])
458 rospy.logerr(
"Attached collision object '%s' not found" % target_id)
464 rospy.logdebug(
"Compensate place pose with the attached object pose [%s]. Results: [%s]" \
465 % (aco_pose, place.pose))
468 places.append(deepcopy(place))
476 color = ObjectColor()
499 for color
in self.colors.values():
500 p.object_colors.append(color)
503 self.scene_pub.publish(p)
507 if isinstance(co, CollisionObject):
509 return co.mesh_poses[0]
510 elif co.primitive_poses:
511 return co.primitive_poses[0]
513 rospy.logerr(
"Collision object '%s' has no mesh/primitive poses" % co.id)
515 elif isinstance(co, AttachedCollisionObject):
516 if co.object.mesh_poses:
517 return co.object.mesh_poses[0]
518 elif co.object.primitive_poses:
519 return co.object.primitive_poses[0]
521 rospy.logerr(
"Attached collision object '%s' has no mesh/primitive poses" % co.id)
524 rospy.logerr(
"Input parameter is not a collision object")
528 '''Convert a pose message to a 4x4 numpy matrix. 531 pose (geometry_msgs.msg.Pose): Pose rospy message class. 534 mat (numpy.matrix): 4x4 numpy matrix 536 quat = [pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w]
537 pos = np.matrix([pose.position.x, pose.position.y, pose.position.z]).T
538 mat = np.matrix(quaternion_matrix(quat))
543 '''Convert a homogeneous matrix to a Pose message, optionally premultiply by a transform. 546 mat (numpy.ndarray): 4x4 array (or matrix) representing a homogenous transform. 547 transform (numpy.ndarray): Optional 4x4 array representing additional transform 550 pose (geometry_msgs.msg.Pose): Pose message representing transform. 552 if transform !=
None:
553 mat = np.dot(mat, transform)
555 pose.position.x = mat[0,3]
556 pose.position.y = mat[1,3]
557 pose.position.z = mat[2,3]
558 quat = quaternion_from_matrix(mat)
559 pose.orientation.x = quat[0]
560 pose.orientation.y = quat[1]
561 pose.orientation.z = quat[2]
562 pose.orientation.w = quat[3]
565 if __name__ ==
"__main__":
def make_gripper_posture(self, joint_positions)
def setColor(self, name, r, g, b, a=0.9)
def pose_to_mat(self, pose)
def make_gripper_translation(self, min_dist, desired, vector)
def mat_to_pose(self, mat, transform=None)
def make_grasps(self, initial_pose_stamped, allowed_touch_objects, grasp_opening=[0])
def make_places(self, target_id, init_pose)