00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 import roslib;
00023 roslib.load_manifest('cortex_stream')
00024 import rospy
00025 import tf
00026 import getopt,sys
00027 import argparse
00028 import numpy as np
00029 import math
00030 import ConfigParser, os
00031 from visualization_msgs.msg import MarkerArray
00032 from nav_msgs.msg import Odometry
00033 from prop import Prop,Marker
00034
00035 class Tracker():
00036 def __init__(self, publish_odom = False):
00037 self.props = dict()
00038 self.marker_sub = rospy.Subscriber("cortex_marker_array", MarkerArray, self.marker_callback)
00039 self.br = tf.TransformBroadcaster()
00040 self.publish_odom = publish_odom
00041 if self.publish_odom:
00042 self.odom_pub = rospy.Publisher("mocap_odom", Odometry)
00043
00044 def marker_callback(self, markerArray):
00045 n = len(markerArray.markers)
00046 for i in range(0,n):
00047 m = markerArray.markers[i]
00048 name = m.ns
00049 nMarkers = len(m.points)
00050
00051 p = self.props[name]
00052 ptG = []
00053 ptO = []
00054 for (pt,i) in zip(m.points,range(0,len(m.points))):
00055 if math.isnan(pt.x) or math.isnan(pt.y):
00056
00057 continue
00058 pos = p.Markers[i].position[:]
00059 ptO.append( [pos[0],pos[1],pos[2],1] )
00060 ptG.append( [pt.x, pt.y, pt.z, 1] )
00061
00062
00063
00064 if len(ptO ) <3 or len(ptG) <3:
00065 rospy.logwarn("too few valid marker positions for pose estimation. skipping.")
00066 continue
00067
00068
00069 x = np.matrix(ptO)[:,0:3].transpose()
00070 y = np.matrix(ptG)[:,0:3].transpose()
00071 mx = np.mean(x,1)
00072 my = np.mean(y,1)
00073 K = (y-my) * (x-mx).transpose()
00074 U,S,V = np.linalg.svd(K)
00075 SS = np.eye(3)
00076 if np.linalg.det(U) * np.linalg.det(V) < 0:
00077 SS[2,2] = -1.0
00078 else:
00079 SS[2,2] = 1.0
00080 R = U*SS*V
00081 D = np.eye(3)
00082 D[0,0] = S[0]
00083 D[1,1] = S[1]
00084 D[2,2] = S[2]
00085 T = my - R*mx
00086 tx = T[0]
00087 ty = T[1]
00088 tz = T[2]
00089 T = np.eye(4)
00090 T[0:3,0:3] = R
00091 T[0,3] = tx
00092 T[1,3] = ty
00093 T[2,3] = tz
00094
00095 try:
00096 q = tf.transformations.quaternion_from_matrix(T)
00097 except Exception as e:
00098 rospy.logerr( "caught quat exception" )
00099 rospy.logerr( e )
00100 rospy.logerr( "transform was: " + str(T) )
00101
00102 self.br.sendTransform((tx,ty,tz),
00103 q,
00104 m.header.stamp, name,
00105 m.header.frame_id)
00106 if self.publish_odom:
00107 odom_msg = Odometry()
00108 odom_msg.header.stamp = m.header.stamp
00109 odom_msg.header.frame_id = '/map'
00110 odom_msg.child_frame_id = name
00111 odom_msg.pose.pose.position.x = tx
00112 odom_msg.pose.pose.position.y = ty
00113 odom_msg.pose.pose.position.z = tz
00114 odom_msg.pose.pose.orientation.x = q[0]
00115 odom_msg.pose.pose.orientation.y = q[1]
00116 odom_msg.pose.pose.orientation.z = q[2]
00117 odom_msg.pose.pose.orientation.w = q[3]
00118 self.odom_pub.publish(odom_msg)
00119
00120 pass
00121
00122 def add_prop_from_file(self,file):
00123 prop = Prop()
00124 if prop.parse_prop_file(file):
00125 self.props[prop.Name] = prop
00126 rospy.loginfo( prop )
00127 else:
00128 rospy.logerr( "error adding prop from %s"%(file) )
00129
00130
00131
00132
00133 if __name__=='__main__':
00134 rospy.init_node('cortex_tacker')
00135 myargs = rospy.myargv(sys.argv)
00136 parser = argparse.ArgumentParser(description='Track Cortex rigid body from prop file(s).')
00137 parser.add_argument('file', metavar='PROPFILE', type=file, nargs='+',
00138 help='prop file(s)')
00139 myargs = myargs[1:]
00140
00141 args = parser.parse_args(myargs)
00142
00143 tracker = Tracker()
00144 for i in range(0,len(args.file)):
00145 print "parsing %s"%(args.file[i])
00146 tracker.add_prop_from_file(args.file[i])
00147
00148 rospy.spin()
00149 sys.exit()