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
00035
00036
00037 PKG = 'kinect_depth_calibration'
00038 NAME = 'depth_calibrator'
00039
00040 import roslib; roslib.load_manifest(PKG)
00041
00042 import rospy
00043 import tf
00044 import numpy
00045 import math
00046 from geometry_msgs.msg import PoseStamped
00047 from kinect_depth_calibration.srv import GetCheckerboardPose, GetCheckerboardPoseResponse, GetCheckerboardPoseRequest
00048 from kinect_depth_calibration.srv import GetCheckerboardCenter, GetCheckerboardCenterResponse, GetCheckerboardCenterRequest
00049
00050 from geometry_msgs.msg import Quaternion, Pose
00051
00052 from sensor_msgs.msg import CameraInfo
00053
00054 def msg_to_quaternion(msg):
00055 return [msg.x, msg.y, msg.z, msg.w]
00056
00057 def quaternion_to_msg(q):
00058 msg = Quaternion()
00059 msg.x = q[0]
00060 msg.y = q[1]
00061 msg.z = q[2]
00062 msg.w = q[3]
00063 return msg
00064
00065 def msg_to_pose(msg):
00066 trans = tf.transformations.quaternion_matrix(msg_to_quaternion(msg.orientation))
00067 trans[0, 3] = msg.position.x
00068 trans[1, 3] = msg.position.y
00069 trans[2, 3] = msg.position.z
00070 trans[3, 3] = 1.0
00071 return trans
00072
00073 def pose_to_msg(pose):
00074 msg = Pose()
00075 msg.position.x = pose[0, 3]
00076 msg.position.y = pose[1, 3]
00077 msg.position.z = pose[2, 3]
00078 q = tf.transformations.quaternion_from_matrix(pose)
00079 msg.orientation.x = q[0]
00080 msg.orientation.y = q[1]
00081 msg.orientation.z = q[2]
00082 msg.orientation.w = q[3]
00083 return msg
00084
00085 def find_board_min(board_pose, corners_x, corners_y, spacing):
00086 trans = msg_to_pose(board_pose.pose)
00087 origin = tf.transformations.translation_matrix([-spacing, -spacing, 0.0])
00088 pose_mat = numpy.dot(trans, origin)
00089 return pose_to_msg(pose_mat)
00090
00091 def find_board_max(board_pose, corners_x, corners_y, spacing):
00092 trans = msg_to_pose(board_pose.pose)
00093 origin = tf.transformations.translation_matrix([((corners_x) * spacing), ((corners_y) * spacing), 0.0])
00094 pose_mat = numpy.dot(trans, origin)
00095 return pose_to_msg(pose_mat)
00096
00097 def find_board_center(board_pose, corners_x, corners_y, spacing):
00098 trans = msg_to_pose(board_pose.pose)
00099 origin = tf.transformations.translation_matrix([((corners_x - 1) * spacing) / 2.0, ((corners_y - 1) * spacing) / 2.0, 0.0])
00100 pose_mat = numpy.dot(trans, origin)
00101 return pose_to_msg(pose_mat)
00102
00103 def project_pose(proj, pose):
00104 position = pose.pose.position
00105 point = numpy.array([[position.x], [position.y], [position.z]])
00106 mult = numpy.dot(proj, point)
00107 return mult / mult[2]
00108
00109 def depth_calibrator_main(argv=None):
00110 rospy.init_node(NAME, anonymous=False)
00111 pose_pub = rospy.Publisher("new_pose", PoseStamped, latch=True)
00112
00113 corners_x = rospy.get_param('~corners_x', 5)
00114 corners_y = rospy.get_param('~corners_y', 4)
00115 spacing = rospy.get_param('~spacing', 0.0245)
00116
00117 listener = tf.TransformListener()
00118
00119 print "Waiting to receive camera info for the depth camera..."
00120 depth_info = rospy.wait_for_message('depth_camera_info', CameraInfo)
00121 depth_proj = numpy.reshape(numpy.array(depth_info.P), (3,4))[:3, :3]
00122 depth_frame_id = depth_info.header.frame_id
00123 print "Got camera info, the depth camera operates in frame %s" % depth_frame_id
00124
00125 run = True
00126 while run:
00127
00128 while(raw_input("Is a checkerboard visible for your image producing camera? (y/n): ") != 'y'):
00129 print "For the Kinect, you may need to cover the IR projector for the CB to be detected."
00130
00131 print "OK, thanks! Checking for the 'get_checkerboard_pose' service."
00132
00133 rospy.wait_for_service('get_checkerboard_pose')
00134
00135 print "Found the checkerboard service."
00136
00137 print "Looking for a %d x %d checkerboard, with %.4f spacing...." % (corners_x, corners_y, spacing)
00138
00139 cb_detector = rospy.ServiceProxy('get_checkerboard_pose', GetCheckerboardPose)
00140 cb = cb_detector.call(GetCheckerboardPoseRequest(corners_x, corners_y, spacing, spacing))
00141 img_center = find_board_center(cb.board_pose, corners_x, corners_y, spacing)
00142 img_msg = PoseStamped()
00143 img_msg.header = cb.board_pose.header
00144 img_msg.pose = img_center
00145 pose_pub.publish(img_msg)
00146
00147 depth_center = None
00148
00149 if depth_frame_id is not None and img_msg.header.frame_id != depth_frame_id:
00150 img_min = PoseStamped(cb.board_pose.header, find_board_min(cb.board_pose, corners_x, corners_y, spacing))
00151 img_max = PoseStamped(cb.board_pose.header, find_board_max(cb.board_pose, corners_x, corners_y, spacing))
00152
00153 print "Waiting for the transform between %s and %s" % (img_msg.header.frame_id, depth_frame_id)
00154 listener.waitForTransform(depth_frame_id, img_msg.header.frame_id, img_msg.header.stamp, rospy.Duration(2.0))
00155 depth_pose = listener.transformPose(depth_frame_id, img_msg)
00156 depth_min = listener.transformPose(depth_frame_id, img_min)
00157 depth_max = listener.transformPose(depth_frame_id, img_max)
00158
00159 depth_min_pt = project_pose(depth_proj, depth_min)
00160 depth_max_pt = project_pose(depth_proj, depth_max)
00161
00162 cb.min_x = depth_min_pt[0]
00163 cb.min_y = depth_min_pt[1]
00164 cb.max_x = depth_max_pt[0]
00165 cb.max_y = depth_max_pt[1]
00166
00167 depth_center = depth_pose.pose
00168 else:
00169 depth_center = img_center
00170
00171 print "Successfully found a checkerboard, with depth %.4f, noise_vel: %f, noise_rot: %f in frame %s" % (depth_center.position.z,
00172 cb.noise_vel, cb.noise_rot,
00173 depth_frame_id)
00174
00175
00176 print "Now we want to look for the center of the checkerboard in the depth image."
00177 while(raw_input("Have you uncovered the IR projector and turned off any other IR light source? (y/n): ") != 'y'):
00178 print "Don't be difficult, just do it."
00179
00180 print "OK, thanks! Waiting for the 'get_checkerboard_center' service."
00181
00182 rospy.wait_for_service('get_checkerboard_center')
00183
00184 print "Found the service, looking for the center of the checkerboard bounded by the rectangle (%.2f, %.2f), (%.2f, %.2f)." % (
00185 cb.min_x, cb.min_y, cb.max_x, cb.max_y)
00186
00187 center_detector = rospy.ServiceProxy('get_checkerboard_center', GetCheckerboardCenter)
00188 center_depth = center_detector.call(GetCheckerboardCenterRequest(cb.min_x, cb.max_x, cb.min_y, cb.max_y, depth_center.position.z))
00189
00190 print "Found the center of the board at depth %.4f in the pointcloud" % (center_depth.depth)
00191
00192 print "The offset between the img and the point cloud is: %.4f" % (depth_center.position.z - center_depth.depth)
00193
00194 run = raw_input("Would you like to run again? (y/n): ") == 'y'
00195
00196 if __name__ == '__main__':
00197 depth_calibrator_main()