+#!/usr/bin/env python
+# -*- coding: iso-8859-15 -*-
+
+"""
+roslaunch darknet_ros darknet_ros.launch image:=/camera/color/image_raw
+"""
+
+import sys
+import rospy
+import tf
+import tf2_ros
+import tf2_geometry_msgs
+import image_geometry
+import moveit_commander
+import numpy as np
+from math import *
+from time import sleep
+from sensor_msgs.msg import Image, CameraInfo
+from darknet_ros_msgs.msg import BoundingBoxes
+from geometry_msgs.msg import PoseStamped
+from cv_bridge import CvBridge
+
+class OpenManipGrabBottle:
+ def __init__(self):
+ rospy.init_node('open_manip_grab_bottle')
+ moveit_commander.roscpp_initialize(sys.argv)
+ self.sub_depthinfo = rospy.Subscriber("/camera/aligned_depth_to_color/camera_info", CameraInfo, self.depthinfo_received)
+ self.tf_broadcaster = tf.broadcaster.TransformBroadcaster()
+ self.depthimgmsg = None
+ self.camera_model = None
+ self.bridge = CvBridge()
+ self.tfBuffer = tf2_ros.Buffer()
+ self.listener = tf2_ros.TransformListener(self.tfBuffer)
+ self.target_class = "bottle"
+
+ self.gripper_pose_pub = rospy.Publisher('gripper_pose', PoseStamped)
+ self.arm = moveit_commander.MoveGroupCommander("arm")
+ self.gripper = moveit_commander.MoveGroupCommander("gripper")
+ self.arm.set_goal_position_tolerance(0.01)
+ self.arm.set_goal_orientation_tolerance(5*pi/180)
+ self.home()
+ sleep(10) # wait for image
+ self.register_subscriber()
+ rospy.spin()
+
+ def register_subscriber(self):
+ self.sub_obj_detection = rospy.Subscriber("/darknet_ros/bounding_boxes", BoundingBoxes, self.detected_objects)
+ self.sub_depthimage = rospy.Subscriber("/camera/aligned_depth_to_color/image_raw", Image, self.depthimage_received)
+
+ def home(self):
+ self.gripper.set_named_target('close')
+ self.gripper.go()
+ #self.arm.set_named_target('home')
+ self.arm.go([f * pi/180 for f in [90.0, -90, 77, 20]], wait=True)
+
+ def detected_objects(self, msg):
+ if self.depthimgmsg is None or self.camera_model is None:
+ return
+ box_bottles = filter(lambda box: box.Class == self.target_class and box.probability > 0.5, msg.bounding_boxes)
+ if len(box_bottles) > 0:
+ box = box_bottles[0] # just use the first one found for now
+ box_x = int(box.xmin + (box.xmax - box.xmin)/2.0)
+ box_y = int(box.ymin + (box.ymax - box.ymin)/2.0)
+ depthframe = self.bridge.imgmsg_to_cv2(self.depthimgmsg)
+ dist = depthframe[box_y][box_x]/1000.0 # assume size rgb = size depth
+ if dist == 0:
+ rospy.logerr("depth invalid")
+ return
+
+ self.sub_obj_detection.unregister()
+ self.sub_depthimage.unregister()
+
+ coords3d = [f * dist for f in self.camera_model.projectPixelTo3dRay([box_x, box_y])]
+ point = PoseStamped()
+ point.header.frame_id = self.depthimgmsg.header.frame_id
+ point.header.stamp = rospy.Time.now()
+ point.pose.position.x = coords3d[0]
+ point.pose.position.y = coords3d[1]
+ point.pose.position.z = coords3d[2]
+ point = self.tfBuffer.transform(point, "open_manipulator_base", rospy.Duration(1))
+ point.pose.orientation.x, point.pose.orientation.y, point.pose.orientation.z, point.pose.orientation.w = [0, 0, 0, 1] # bottle stands up
+ print point
+ point.pose.position.z-=0.02
+
+ self.tf_broadcaster.sendTransform([point.pose.position.x, point.pose.position.y, point.pose.position.z], [point.pose.orientation.x, point.pose.orientation.y, point.pose.orientation.z, point.pose.orientation.w], rospy.Time.now(), self.target_class, "open_manipulator_base")
+
+ if self.pick(point):
+ rospy.signal_shutdown("done")
+ else:
+ self.home()
+ self.register_subscriber()
+
+ def depthimage_received(self, msg):
+ self.depthimgmsg = msg
+
+ def depthinfo_received(self, msg):
+ self.camera_model = image_geometry.PinholeCameraModel()
+ self.camera_model.fromCameraInfo(msg)
+ self.sub_depthinfo.unregister()
+
+ def pick(self, pose):
+ pos2d = [pose.pose.position.x, pose.pose.position.y]
+ dist = np.linalg.norm(pos2d)
+ pos2d_unit = pos2d / dist # unit vector
+
+ # orientation towards base
+ q = tf.transformations.quaternion_from_euler(0, 0, acos(np.dot(pos2d_unit, [1, 0]))) # use the dot product to get the angle
+ pose.pose.orientation.x, pose.pose.orientation.y, pose.pose.orientation.z, pose.pose.orientation.w = [q[0], q[1], q[2], q[3]]
+
+ # goal 5cm before
+ pose.pose.position.x = pos2d_unit[0] * (dist-0.05)
+ pose.pose.position.y = pos2d_unit[1] * (dist-0.05)
+ self.arm.set_pose_target(pose)
+ if not self.arm.go():
+ print "before position failed"
+ return False
+
+ self.gripper.set_named_target('open')
+ self.gripper.go()
+
+ # goal on target +3cm
+ pose.pose.position.x = pos2d_unit[0] * (dist+0.03)
+ pose.pose.position.y = pos2d_unit[1] * (dist+0.03)
+ self.arm.set_pose_target(pose)
+ if not self.arm.go():
+ print "position on target failed"
+ return False
+
+ self.gripper.set_named_target('close')
+ self.gripper.go()
+
+ # height
+ angles = [0.0, 0.0, 0.0, 0.0]
+ while angles == [0.0, 0.0, 0.0, 0.0]: # invalid
+ angles = self.arm.get_current_joint_values()
+ print [f * 180/pi for f in angles]
+ angles[1]-=20*pi/180
+ if not self.arm.go(angles, wait=True):
+ print "higher position failed"
+ return True
+
+ if not self.arm.go([f * pi/180 for f in [-90, -60, 0, 0]], wait=True):
+ print "final position failed"
+ return True
+
+ return True
+
+if __name__ == "__main__":
+ OpenManipGrabBottle()