00001
00002
00003 import copy
00004 import pygame
00005 import pygame.image
00006 from vec2d import *
00007
00008 import numpy as np
00009
00010 import roslib
00011 roslib.load_manifest('tf')
00012 roslib.load_manifest('rosparam')
00013 roslib.load_manifest('sensor_msgs')
00014 roslib.load_manifest('camera_calibration')
00015 roslib.load_manifest('pixel_2_3d')
00016 roslib.load_manifest('hrl_generic_arms')
00017 roslib.load_manifest('opencv2')
00018
00019 import cv
00020
00021 import rospy
00022 import rosparam
00023 import rosbag
00024 import tf
00025 from sensor_msgs.msg import PointCloud2
00026 from hrl_generic_arms.pose_converter import PoseConverter
00027 from camera_calibration.calibrator import ChessboardInfo, Calibrator
00028 from sensor_msgs.msg import Image
00029 from cv_bridge import CvBridge, CvBridgeError
00030
00031 from msg import PHRIPointCloudCapture
00032
00033 DEBUG = True
00034
00035 class PCSaver:
00036 def __init__(self, pc_topic, img_topic, base_frame, frames, filename):
00037 self.base_frame = base_frame
00038 self.frames = frames
00039 self.seq = 0
00040 self.i = 0
00041 self.pcc = None
00042 self.bag = rosbag.Bag(filename, 'w')
00043 self.tf_list = tf.TransformListener()
00044 self.img_list = ImageListener(img_topic)
00045 rospy.sleep(1.)
00046 rospy.Subscriber(pc_topic, PointCloud2, self.record_data)
00047
00048 def record_data(self, msg):
00049 if self.i == 0:
00050 print "Got first PC"
00051 self.i += 1
00052
00053 pcc = PHRIPointCloudCapture()
00054 pcc.header.seq = self.seq
00055 pcc.header.frame_id = self.base_frame
00056 pcc.header.stamp = rospy.Time.now()
00057 pcc.pc_capture = msg
00058 pcc.frame_names = self.frames
00059
00060 for frame in self.frames:
00061 try:
00062 pos, quat = self.tf_list.lookupTransform(self.base_frame,
00063 frame, rospy.Time(0))
00064 pose_stmpd = PoseConverter.to_pose_stamped_msg(pos, quat)
00065 pose_stmpd.header = copy.deepcopy(pcc.header)
00066 pcc.saved_frames.append(pose_stmpd)
00067 except Exception,e:
00068 if not DEBUG:
00069 print e
00070 print "%d, Missing frame: %s" % (self.i, frame)
00071 pcc = None
00072 self.pcc = pcc
00073
00074 def save_data(self, register=False):
00075 if DEBUG:
00076 self.pcc = PHRIPointCloudCapture()
00077 if self.pcc is not None:
00078 self.bag.write("/point_cloud_captures", self.pcc)
00079 self.seq += 1
00080 print "%2d Saved PC and frames" % self.seq
00081 if register:
00082 self.get_registration()
00083 return True
00084 else:
00085 print "Invalid capture, no PC saved"
00086 return False
00087
00088 def get_registration(self):
00089 forehead = Vec2d(320, 150)
00090 chin = Vec2d(320, 340)
00091 l_eye = Vec2d(240, 200)
00092 r_eye = Vec2d(390, 200)
00093 r_mouth = Vec2d(350, 285)
00094 l_mouth = Vec2d(290, 285)
00095 control_points = [forehead, chin, l_eye, r_eye, r_mouth, l_mouth]
00096
00097 pg_img = self.img_list.get_pg_img()
00098 pygame.init()
00099 screen = pygame.display.set_mode((640, 480))
00100 clock = pygame.time.Clock()
00101 selected = None
00102 running = True
00103 while not rospy.is_shutdown() and running:
00104 for event in pygame.event.get():
00105 if event.type == pygame.QUIT:
00106 running = False
00107 elif event.type == pygame.KEYDOWN:
00108 if event.dict['key'] == pygame.K_SPACE:
00109 running = False
00110 elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
00111 for p in control_points:
00112 if abs(p.x - event.pos[0]) < 10 and abs(p.y - event.pos[1]) < 10 :
00113 selected = p
00114 elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 3:
00115 x,y = pygame.mouse.get_pos()
00116 control_points.append(Vec2d(x,y))
00117 elif event.type == pygame.MOUSEBUTTONUP and event.button == 1:
00118 selected = None
00119
00120 screen.blit(pg_img, (0, 0))
00121
00122 pygame.draw.lines(screen, (255, 255, 0), False, [forehead, chin])
00123 pygame.draw.lines(screen, (255, 255, 0), False, [l_eye, r_eye, r_mouth, l_mouth, l_eye])
00124
00125 if selected is not None:
00126 selected.x, selected.y = pygame.mouse.get_pos()
00127 pygame.draw.circle(screen, (0, 255, 0), selected, 10)
00128
00129 for p in control_points:
00130 pygame.draw.circle(screen, (0, 0, 255), p, 4)
00131
00132 pygame.display.flip()
00133 pygame.quit()
00134 print "Selected points:", control_points
00135
00136
00137
00138 class ImageListener:
00139 def __init__(self, topic):
00140 self.bridge = CvBridge()
00141 self.image_sub = rospy.Subscriber(topic, Image, self.callback)
00142 self.img_msg = None
00143 self.got_first_img = False
00144
00145 def callback(self, data):
00146 if not self.got_first_img:
00147 self.got_first_img = True
00148 print "Got first image"
00149 self.img_msg = data
00150
00151 def get_pg_img(self):
00152 try:
00153 cv_img = self.bridge.imgmsg_to_cv(self.img_msg, "rgb8")
00154 except CvBridgeError, e:
00155 print e
00156 return
00157 return pygame.image.frombuffer(cv_img.tostring(),
00158 cv.GetSize(cv_img), "RGB")
00159
00160 def main():
00161 rospy.init_node('phri_setup_capture')
00162
00163 from optparse import OptionParser
00164 p = OptionParser()
00165 p.add_option('-l', '--load_file', dest="load_file", default="",
00166 help="YAML file to load parameters from.")
00167 p.add_option('-b', '--bagfile', dest="bagname", default="phri_output.bag",
00168 help="Bag file to save to.")
00169 p.add_option('-r', '--rate', dest="rate", default="0", type="int",
00170 help="""Rate in hz to capture at. If not specified or 0,
00171 will only capture when pressing enter.""")
00172 opts, args = p.parse_args()
00173 assert opts.load_file != ""
00174
00175 params = rosparam.load_file(opts.load_file, "phri_setup_capture")[0][0]
00176 base_frame = params['base_frame']
00177 frames = params['frames_to_save']
00178 pc_topic = params['pc_topic']
00179 img_topic = params['img_topic']
00180
00181 pcs = PCSaver(pc_topic, img_topic, base_frame, frames, opts.bagname)
00182 if opts.rate != 0:
00183 r = rospy.Rate(opts.rate)
00184 first = True
00185 while not rospy.is_shutdown():
00186 if opts.rate == 0:
00187 if raw_input("Type 'd' when done: ") == 'd':
00188 break
00189 else:
00190 r.sleep()
00191 pcs.save_data(first)
00192 first = False
00193 pcs.bag.close()
00194
00195
00196 if __name__ == "__main__":
00197 main()