00001
00002
00003 import numpy as np
00004 import yaml
00005 import sys
00006 import cv
00007
00008 import roslib
00009 roslib.load_manifest('camera_calibration')
00010 roslib.load_manifest('hrl_geom')
00011 roslib.load_manifest('tf')
00012
00013 import rospy
00014 import rosbag
00015 import tf
00016 from sensor_msgs.msg import Image, PointCloud2, CameraInfo
00017
00018 from hrl_geom.pose_converter import PoseConv
00019 from cv_bridge import CvBridge, CvBridgeError
00020 from camera_calibration.calibrator import ChessboardInfo, Calibrator
00021 from point_cloud import read_points, create_cloud, create_cloud_xyz32
00022
00023 class DataListener(object):
00024 def __init__(self, is_kinect, bridge, calib):
00025 self.is_kinect = is_kinect
00026 self.cur_img = None
00027 self.cur_pc = None
00028 self.cam_info = None
00029 self.cur_corners = None
00030 self.bridge = bridge
00031 self.calib = calib
00032 self.cam_sub = rospy.Subscriber("/camera", Image, self.sub_img)
00033 if self.is_kinect:
00034 self.pc_sub = rospy.Subscriber("/pc", PointCloud2, self.sub_pc)
00035 else:
00036 self.cam_info_sub = rospy.Subscriber("/camera_info", CameraInfo, self.sub_info)
00037 self.vis_pub = rospy.Publisher("/cb_img_raw", Image)
00038 print "Waiting for image/PC"
00039 r = rospy.Rate(10)
00040 while not rospy.is_shutdown():
00041 if self.cur_img is not None:
00042 if self.is_kinect:
00043 if self.cur_pc is not None:
00044 break
00045 else:
00046 if self.cam_info is not None:
00047 break
00048 r.sleep()
00049 print "Received image/PC"
00050
00051 def sub_img(self, img):
00052 self.cur_img = img
00053 cv_img = self.bridge.imgmsg_to_cv(img, "rgb8")
00054 has_corners, cur_corners, chess = self.calib.get_corners(cv_img)
00055 if not has_corners:
00056 cur_corners = None
00057 return
00058 self.cur_corners = cur_corners
00059 cv.DrawChessboardCorners(cv_img,
00060 (self.calib._boards[0].n_cols, self.calib._boards[0].n_rows),
00061 self.cur_corners, has_corners)
00062 new_img = self.bridge.cv_to_imgmsg(cv_img, "rgb8")
00063 new_img.header = img.header
00064 self.vis_pub.publish(new_img)
00065
00066 def sub_pc(self, pc):
00067 self.cur_pc = pc
00068
00069 def sub_info(self, cam_info):
00070 self.cam_info = cam_info
00071
00072 def wait_for_new(self, timeout):
00073 last_img_id = self.cur_img.header.seq
00074 if self.is_kinect:
00075 last_other_id = self.cur_pc.header.seq
00076 else:
00077 last_other_id = self.cam_info.header.seq
00078 r = rospy.Rate(10)
00079 start_time = rospy.get_time()
00080 while not rospy.is_shutdown():
00081 if rospy.get_time() - start_time > timeout:
00082 print "Timed out"
00083 return None
00084 if last_img_id != self.cur_img.header.seq:
00085 if self.is_kinect:
00086 cur_id = self.cur_pc.header.seq
00087 else:
00088 cur_id = self.cam_info.header.seq
00089 if last_other_id != cur_id:
00090 return self.cur_corners
00091 r.sleep()
00092
00093 def main():
00094 if len(sys.argv) < 3:
00095 print 'grab_cbs_auto cb_config.yaml output_bag.bag'
00096 return
00097 rospy.init_node("grab_cbs")
00098
00099 f = file(sys.argv[1], 'r')
00100 cb_config = yaml.safe_load(f.read())
00101 print cb_config
00102 f.close()
00103 is_kinect = rospy.get_param("/grab_cbs/is_kinect", True)
00104
00105
00106 chessboard = ChessboardInfo()
00107 chessboard.n_cols = cb_config['cols']
00108 chessboard.n_rows = cb_config['rows']
00109 chessboard.dim = cb_config['dim']
00110 calib = Calibrator([chessboard])
00111 bridge = CvBridge()
00112
00113 l = DataListener(is_kinect, bridge, calib)
00114 tf_list = tf.TransformListener()
00115
00116 cb_knowns = []
00117 for j in range(chessboard.n_cols):
00118 for i in range(chessboard.n_rows):
00119 cb_knowns.append((chessboard.dim*i, chessboard.dim*j, 0.0))
00120
00121 bag = rosbag.Bag(sys.argv[2], 'w')
00122 i = 0
00123 while not rospy.is_shutdown():
00124 if raw_input("Press enter to take CB, type 'q' to quit: ") == "q":
00125 break
00126
00127 tries = 0
00128 while not rospy.is_shutdown() and tries < 3:
00129 corners = l.wait_for_new(5.)
00130 if corners is None:
00131 print "No corners detected"
00132 tries += 1
00133 continue
00134 corners_2d = np.uint32(np.round(corners)).tolist()
00135 corners_3d = []
00136 if is_kinect:
00137 for x,y,z in read_points(l.cur_pc, field_names=['x', 'y', 'z'], uvs=corners_2d):
00138 corners_3d.append((x,y,z))
00139 frame_id = l.cur_pc.header
00140 else:
00141 obj_pts = cv.fromarray(np.array(cb_knowns))
00142 img_pts = cv.fromarray(np.array(corners))
00143 K = cv.fromarray(np.reshape(l.cam_info.K,(3,3)))
00144 D = cv.fromarray(np.array([l.cam_info.D]))
00145 R_vec = cv.fromarray(np.zeros((3,1)))
00146 t = cv.fromarray(np.zeros((3,1)))
00147 cv.FindExtrinsicCameraParams2(obj_pts, img_pts, K, D, R_vec, t)
00148 R_mat = cv.fromarray(np.zeros((3,3)))
00149 cv.Rodrigues2(R_vec, R_mat)
00150 T = PoseConv.to_homo_mat(np.mat(np.asarray(t)).T.A.tolist(),
00151 np.mat(np.asarray(R_mat)).A.tolist())
00152 cb_knowns_mat = np.vstack((np.mat(cb_knowns).T, np.mat(np.ones((1, len(cb_knowns))))))
00153 corners_3d = np.array((T * cb_knowns_mat)[:3,:].T)
00154 frame_id = l.cur_img.header
00155 print corners_3d
00156 if np.any(np.isnan(corners_3d)):
00157 print "Pointcloud malformed"
00158 tries += 1
00159 continue
00160 now = rospy.Time.now()
00161 corners_pc = create_cloud_xyz32(frame_id, corners_3d)
00162 try:
00163 pose = tf_list.lookupTransform('/base_link', '/ee_link', rospy.Time(0))
00164 except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):
00165 print "TF screwed up..."
00166 continue
00167 bag.write("/pose", PoseConv.to_pose_stamped_msg('/base_link', pose), now)
00168 bag.write("/pc", corners_pc, now)
00169 print "Wrote pose/CB to bag file"
00170 break
00171 i += 1
00172 bag.close()
00173
00174 if __name__ == "__main__":
00175 main()