optitrak_calibration.py
Go to the documentation of this file.
00001 #! /usr/bin/python
00002 
00003 import numpy as np
00004 import sys
00005 import cPickle as pickle
00006 
00007 import roslib
00008 roslib.load_manifest('kelsey_sandbox')
00009 roslib.load_manifest('hrl_generic_arms')
00010 import rospy
00011 import rosparam
00012 import tf
00013 import tf.transformations as tf_trans
00014 from hrl_generic_arms.pose_converter import PoseConverter
00015 #from umeyama_method import umeyama_method
00016 
00017 def capture_data():
00018     tf_list = tf.TransformListener()
00019     opti_mat, robot_mat = [], []
00020     print "Hit enter to collect a data sample"
00021     i = 0
00022     while not rospy.is_shutdown():
00023         rospy.sleep(0.3)
00024 #if raw_input(".") == 'q':
00025 #    break
00026         now = rospy.Time(0.)
00027         (opti_pos, opti_rot) = tf_list.lookupTransform("/pr2_antenna", 
00028                                                        "/optitrak", now)
00029         (robot_pos, robot_rot) = tf_list.lookupTransform("/wide_stereo_link", 
00030                                                          "/base_footprint", now)
00031         opti_mat.append(opti_pos)
00032         opti_rot_foot = np.mat([[-0.17496687,  0.03719102, -0.98387165],
00033                                 [-0.98098458, -0.09183928,  0.17098186],
00034                                 [-0.08399907,  0.99507908,  0.05255265]]).T
00035         opti_pos_foot = np.mat([[ 1.276  ],
00036                                 [-0.81755],
00037                                 [-0.06905]])
00038         foot_B_opti = PoseConverter.to_homo_mat(opti_pos_foot, opti_rot_foot) ** -1
00039         opti_B_ant = PoseConverter.to_homo_mat(opti_pos, opti_rot) ** -1
00040         wide_B_foot = PoseConverter.to_homo_mat(robot_pos, robot_rot) 
00041         print wide_B_foot * foot_B_opti * opti_B_ant
00042         offset_robot_pos = (wide_B_foot * foot_B_opti)[:3,3]
00043         print offset_robot_pos, opti_pos
00044         robot_mat.append(offset_robot_pos.T.A[0].tolist())
00045         i += 1
00046         if i % 10 == 0:
00047             print i, "samples collected"
00048     return opti_mat, robot_mat
00049 
00050 def umeyama_method(A, B):
00051     ux = np.mean(A, 1)
00052     uy = np.mean(B, 1)
00053     A_demean = A - ux
00054     B_demean = B - uy
00055     U, D, VT = np.linalg.svd(A_demean * B_demean.T)
00056     R = VT.T * U.T
00057     t = uy - R * ux
00058     return t, R
00059 
00060 def save_params(pos, rot, filename):
00061     rot_homo = np.eye(4)
00062     rot_homo[:3,:3] = rot
00063     rot_quat = tf_trans.quaternion_from_matrix(rot_homo)
00064     optitrak_params = { "position" : pos.T.A[0].tolist(),
00065                         "orientation" : rot_quat.tolist() }
00066     print optitrak_params
00067     rosparam.upload_params("optitrak_calibration", optitrak_params)
00068     rospy.sleep(0.5)
00069     rosparam.dump_params(filename, "optitrak_calibration")
00070 
00071 def publish_transform():
00072     optitrak_params = rosparam.get_param("optitrak_calibration")
00073     remap_mat = PoseConverter.to_homo_mat(optitrak_params["position"], 
00074                                           optitrak_params["orientation"]) ** -1
00075     tf_list = tf.TransformListener()
00076     tf_broad = tf.TransformBroadcaster()
00077     small_dur = rospy.Duration(0.001)
00078     robot_mat = PoseConverter.to_homo_mat([0., 0., 0.], [0., 0., 0., 1.])
00079     opti_mat = PoseConverter.to_homo_mat([0., 0., 0.], [0., 0., 0., 1.])
00080     while not rospy.is_shutdown():
00081         try:
00082             now = rospy.Time(0.)
00083 
00084             (opti_pos, opti_rot) = tf_list.lookupTransform("/optitrak", 
00085                                                            "/pr2_antenna", now)
00086             opti_mat = PoseConverter.to_homo_mat(opti_pos, opti_rot)
00087             now = rospy.Time(0.)
00088 
00089             (robot_pos, robot_rot) = tf_list.lookupTransform("/wide_stereo_link", 
00090                                                              "/base_footprint", now)
00091             robot_mat = PoseConverter.to_homo_mat(robot_pos, robot_rot)
00092 
00093             odom_mat = opti_mat * remap_mat * robot_mat
00094             odom_pos, odom_rot = PoseConverter.to_pos_quat(odom_mat)
00095             tf_broad.sendTransform(odom_pos, odom_rot, rospy.Time.now(), "/base_footprint", "/optitrak")
00096             rospy.sleep(0.001)
00097         except Exception as e:
00098             print e
00099 
00100 
00101 def main():
00102     rospy.init_node("optitrak_odom_remap")
00103     
00104     from optparse import OptionParser
00105     p = OptionParser()
00106     p.add_option('-f', '--file', dest="filename", default="",
00107                  help="YAML file to save parameters in.")
00108     p.add_option('-l', '--load', dest="is_load",
00109                  action="store_true", default=False,
00110                  help="Load parameters from file.")
00111     p.add_option('-t', '--train', dest="is_train",
00112                  action="store_true", default=False,
00113                  help="Train by moving the head to different poses and capturing the relative positions.")
00114     p.add_option('-p', '--publish', dest="is_pub",
00115                  action="store_true", default=False,
00116                  help="Publish the transformation from optitrak to base_footprint.")
00117     (opts, args) = p.parse_args()
00118     if opts.filename == "":
00119         print "Bad command line parameters"
00120         p.print_help()
00121         return
00122 
00123     if opts.is_load:
00124         print "hi"
00125         params = rosparam.load_file(opts.filename, "optitrak_calibration")[0][0]
00126         rosparam.upload_params("optitrak_calibration", params)
00127         rospy.sleep(0.1)
00128     if opts.is_pub:
00129         publish_transform()
00130         return
00131     if opts.is_train:
00132         opti_mat, robot_mat = capture_data()
00133         opti_mat = np.mat(opti_mat).T
00134         robot_mat = np.mat(robot_mat).T
00135         pos, rot = umeyama_method(opti_mat, robot_mat)
00136         print np.linalg.norm(robot_mat - (rot * opti_mat + pos))
00137         save_params(pos, rot, opts.filename)
00138         return
00139         
00140 
00141 if __name__ == "__main__":
00142     main()


kelsey_sandbox
Author(s): kelsey
autogenerated on Wed Nov 27 2013 11:52:04