00001
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
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
00025
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()