tracker.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002  #
00003  # A ROS interface for the Cortex Motion Capture System Network Stream
00004  #
00005  # Copyright 2011 by Daniel Maier, University of Freiburg
00006  # based on the robular implementation by Joerg Mueller
00007  #
00008  # This program is free software: you can redistribute it and/or modify
00009  # it under the terms of the GNU General Public License as published by
00010  # the Free Software Foundation, version 3.
00011  #
00012  # This program is distributed in the hope that it will be useful,
00013  # but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  # GNU General Public License for more details.
00016  #
00017  # You should have received a copy of the GNU General Public License
00018  # along with this program.  If not, see <http://www.gnu.org/licenses/>.
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): # process all n tracked objects
00047             m = markerArray.markers[i]
00048             name = m.ns
00049             nMarkers = len(m.points)
00050             #print "Found obj %s with %d markers"%(name,nMarkers)
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                     #print "NaN found!"
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                 #pos = np.array([pt.x,pt.y,pt.z]).transpose()
00062                 #ptG[:,i] = pos.transpose()
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             # estimate pose of object
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             # publish pose
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             #print "br %s-->%s"%(m.header.frame_id,name)
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             #end processing object i
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     #print myargs
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()
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


cortex_stream
Author(s): Daniel Maier
autogenerated on Wed Oct 31 2012 08:22:56