process_dir_estimate.py
Go to the documentation of this file.
00001 #!/usr/bin/python
00002 
00003 # Basically a giant script.
00004 
00005 import roslib
00006 roslib.load_manifest( 'geometry_msgs' )  # the pickle files containe Point and Pose Stamped.
00007 import rospy
00008 
00009 from geometry_msgs.msg import PointStamped, PoseStamped
00010 
00011 
00012 import sys
00013 import glob
00014 import yaml
00015 import time
00016 import optparse
00017 import cPickle as pkl
00018 import numpy as np, math
00019 import pylab as pl
00020 import string
00021 from scipy.spatial import KDTree
00022 import matplotlib as mpl
00023 
00024 import friis
00025 import math_util as mu
00026 
00027 PLOT = False
00028 
00029 if __name__ == '__main__':
00030     p = optparse.OptionParser()
00031     p.add_option('--yaml', action='store', type='string', dest='yaml', default='',
00032                  help='yaml file that describes this run.')
00033     p.add_option('--plot', action='store_true', dest='plot',
00034                  help='Pop-up the resulting plot')
00035     opt, args = p.parse_args()
00036 
00037     yaml_fname = opt.yaml
00038     PLOT = opt.plot
00039 else:
00040     yaml_fname = '/home/travis/svn/robot1/src/projects/rfid_datacapture/src/rfid_datacapture/cap_360/dir_est_head_datacap.yaml'
00041     # yaml_fname = '/home/travis/svn/robot1/src/projects/rfid_datacapture/src/rfid_datacapture/cap_360/dir_est_shoulder_datacap.yaml'
00042     
00043 if not yaml_fname:
00044     print 'YAML file required!'
00045     exit()
00046 else:
00047     f = open( yaml_fname )
00048     yaml_config = yaml.load( f )
00049     f.close()
00050 
00051 def desired_ant( r ):
00052     if dict.fromkeys(yaml_config['filters']['antennas']).has_key( r[2][1] ):
00053         return True
00054     else:
00055         return False
00056 
00057 # def xy( reading ):
00058 #     # Model estimate of P^inc_tag.
00059 #     # r_rdr, theta_rdr, phi_rdr, r_tag, theta_tag, phi_tag, rssi, antname, tagid = reading
00060 #     d_rdr = reading[0]
00061 #     d_tag = reading[1]
00062 #     read = reading[2]
00063 #     d_rot = reading[3]
00064 #     ps = reading[4]
00065 
00066 #     tag_map, rdr_map, rot_map, base_map = ps
00067 #     return [ base_map.pose.position.x, base_map.pose.position.y ]
00068                                     
00069 
00070 class Scan():
00071     def __init__( self, d, tagid, fname ):
00072         self.d = d
00073         self.tagid = tagid
00074         self.fname = fname
00075         
00076         if not self.d.has_key( self.tagid ):
00077             print 'ERROR: %s does not have tagid \'%s\'' % (self.fname, self.tagid)
00078             exit()
00079             
00080         self.theta_rot_map = [ r[3][0] for r in self.d[ self.tagid ] if desired_ant( r )]
00081         self.theta_tag_map = [ r[3][1] for r in self.d[ self.tagid ] if desired_ant( r )]
00082         self.rssi = [ r[2][0] for r in self.d[ self.tagid ] if r[2][1] if desired_ant( r )]
00083 
00084         self.dat = np.row_stack([ np.array( self.theta_rot_map ),
00085                                   np.array( self.theta_tag_map ),
00086                                   np.array( self.rssi ) ])
00087 
00088         self.theta_tag_gt = np.mean( self.dat[1] )  # The actual estimates for gt will fluctuate per read due to tf
00089 
00090         # We want to know if the tag was inview and if there were positive reads
00091         self.h, self.bins = np.histogram( self.dat[0], 36, (-np.pi, np.pi )) # 10-deg width bins
00092         self.bin_centers = (self.bins[:-1] + self.bins[1:]) / 2.0
00093         self.ind_all = np.sum( self.dat[0][:,np.newaxis] > self.bins[:-1], axis = 1) - 1  # gives indices for each datapoint into corresponding bin
00094 
00095         self.ind_tag = np.sum( np.array([ self.theta_tag_gt ])[:,np.newaxis] > self.bins[:-1], axis = 1) - 1
00096         self.inview = np.sum( self.ind_all == self.ind_tag ) > 0  # was there at least one reading in the ground-truth bin?
00097         self.hasposreads = np.sum( self.dat != -1 ) > 0
00098 
00099         # Histmax estimate only uses positive readings
00100         self.m_rssi = [ np.mean( self.dat[2,np.intersect1d( np.where( self.ind_all == i )[0],
00101                                                             np.where( self.dat[2] != -1 )[0] )])
00102                         for i in xrange(len(self.h))]
00103         self.m_rssi = np.nan_to_num( np.array( self.m_rssi ))  # convert all the places with nan (mean of zero readings) to
00104 
00105         self.ind_max = np.argmax( self.m_rssi )
00106         self.max_m_rssi = self.m_rssi[ self.ind_max ]
00107         self.histmax_est = self.bin_centers[ self.ind_max ]
00108         self.histmax_err = mu.standard_rad( self.histmax_est - self.theta_tag_gt )
00109         
00110         # Static estimation: pick the midpoint angle.
00111         #    We assume theta_rot_map will be contiguous between [-pi,pi] --> choose a good rotation frame.
00112         self.static_est = np.min(self.dat[0]) + ( np.max(self.dat[0]) - np.min(self.dat[0]) ) / 2.0
00113         self.static_err = mu.standard_rad( self.static_est - self.theta_tag_gt )
00114 
00115         first_read = self.d[ self.tagid ][0]
00116         pose_robot = first_read[4][3]
00117         prx = pose_robot.pose.position.x
00118         pry = pose_robot.pose.position.y
00119         
00120         pose_tag   = first_read[4][0]
00121         ptx = pose_tag.pose.position.x
00122         pty = pose_tag.pose.position.y
00123 
00124         dist = np.sqrt( (prx-ptx)**2.0 + (pry-pty)**2.0 )
00125         
00126         self.stats = [ prx,
00127                        pry,
00128                        dist,
00129                        self.max_m_rssi,
00130                        self.histmax_est,
00131                        self.histmax_err,
00132                        self.static_est,
00133                        self.static_err ]
00134         return
00135 
00136         
00137 fnames = reduce( lambda x,y: x+y, [ glob.glob(i) for i in yaml_config['glob_files'] ], [] )
00138 
00139 # Load all pkl files into one huge dictionary.
00140 # d = { 'tagid1': [ PROC_READ1, PROC_READ2, ... ],
00141 #       ...
00142 #     }
00143 
00144 scans = []
00145 for i,fname in enumerate( fnames ):
00146     print 'Loading (%d of %d): %s' % (i+1, len(fnames), fname)
00147     f = open( fname, 'r' )
00148     d_new = pkl.load( f )
00149     f.close()
00150 
00151     for k in d_new.keys():
00152         if dict.fromkeys(yaml_config['filters']['tags']).has_key( k ):
00153             scans += [ Scan( d_new, k, fname ) ]
00154 
00155 skipped = 0
00156 stats = []
00157 
00158 for s in scans:
00159     if not s.inview or not s.hasposreads:
00160         skipped += 1
00161     else:
00162         if PLOT:
00163             f = pl.figure( figsize=(10,6) )
00164             pl.axes([0.1,0.1,0.65,0.8])
00165             pl.plot( s.dat[0] * 180.0 / np.pi, np.clip(s.dat[2],69,110), 'rx' )
00166             pl.hold( True )
00167             pl.plot( [ s.theta_tag_gt * 180.0 / np.pi ], [ np.max(s.dat[2])+2 ], 'bo' ) # tag groundtruth
00168             pl.plot( [ s.histmax_est  * 180.0 / np.pi ], [ np.max(s.dat[2])+1 ], 'ko' ) # histmax estiamte
00169             pl.ylim( (68,105) )
00170             pl.xlim( (-180,180) )
00171             pl.xlabel( 'Rotation Angle (degrees)')
00172             pl.ylabel( 'RSSI')
00173             pl.title( 'RSSI versus rotation angle' )
00174             pl.legend(['RFID reads', 'Groundtruth', 'ARGMAX Est'], loc=(1.03,0.2))
00175 
00176             f = s.fname
00177             sr = string.rfind( f, '/' )
00178             pl.savefig( yaml_config['outimage'] + f[sr+1:sr+string.find(f[sr:],'.')] + '_pincrdr.png' )
00179             pl.close()
00180 
00181         stats.append( s.stats )
00182 
00183 npstats = np.array( stats ).T
00184 
00185 print 'Skipped (not in view or no positive reads): ', skipped
00186 
00187 print 'ARGMAX Stats:'
00188 herr = npstats[5]
00189 magherr = np.abs( herr )
00190 print '\tmean err: ', math.degrees(np.mean( herr ))
00191 print '\tstd err: ',  math.degrees(np.std(  herr ))
00192 print '\tRMS err (should be same as stderr): ', math.degrees( np.sqrt(np.mean(np.power(herr, 2.0))) )
00193 print '\tmean magerr: ',   math.degrees(np.mean( magherr ))
00194 print '\tstddev magerr: ', math.degrees(np.std(  magherr ))
00195 
00196 
00197 print 'STATIC Stats:'
00198 serr = npstats[7]
00199 magserr = np.abs( serr )
00200 print '\tmean err: ', math.degrees(np.mean( serr ))
00201 print '\tstd err: ',  math.degrees(np.std(  serr ))
00202 print '\tRMS err (should be same as stderr): ', math.degrees( np.sqrt(np.mean(np.power(serr, 2.0))) )
00203 print '\tmean magerr: ',   math.degrees(np.mean( magserr ))
00204 print '\tstddev magerr: ', math.degrees(np.std(  magserr ))
00205 
00206 
00207 
00208 # Setup for plots below
00209 dist = npstats[2]
00210 h_d,bins_d = np.histogram( dist, 8, range=(0.0,8.0)) # we want to consider distances out to 0m-8m
00211 ind_d = np.sum( dist[:,np.newaxis] > bins_d[:-1], axis=1) - 1
00212 num_d = np.array([ len( np.where( ind_d == i )[0] ) for i in xrange(len(h_d)) ])
00213 
00214 rssi = npstats[3]
00215 h_r,bins_r = np.histogram( rssi, 8, range=(71,101)) # we want to consider distances out to 0m-8m
00216 ind_r = np.sum( rssi[:,np.newaxis] > bins_r[:-1], axis=1) - 1
00217 num_r = np.array([ len( np.where( ind_r == i )[0] ) for i in xrange(len(h_r)) ])
00218 
00219 # Means (md) and StandardDev (sd) at Distance (in Degrees)
00220 magherr_md = np.array([ np.mean( magherr[ np.where( ind_d == i )[0] ]) for i in xrange(len(h_d)) ]) * 180.0 / np.pi 
00221 magherr_sd = np.array([ np.std(  magherr[ np.where( ind_d == i )[0] ]) for i in xrange(len(h_d)) ]) * 180.0 / np.pi
00222 magherr_sd[ np.where( num_d < 3 )[0] ] = 0 # Only put errorbars where we have sufficient data!
00223 
00224 magserr_md = np.array([ np.mean( magserr[ np.where( ind_d == i )[0] ]) for i in xrange(len(h_d)) ]) * 180.0 / np.pi 
00225 magserr_sd = np.array([ np.std(  magserr[ np.where( ind_d == i )[0] ]) for i in xrange(len(h_d)) ]) * 180.0 / np.pi
00226 magserr_sd[ np.where( num_d < 3 )[0] ] = 0 # Only put errorbars where we have sufficient data!
00227 
00228 # Means (mr) and StandardDev (sr) at MaxRSSI (in Degrees)
00229 magherr_mr = np.array([ np.mean( magherr[ np.where( ind_r == i )[0] ]) for i in xrange(len(h_r)) ]) * 180.0 / np.pi 
00230 magherr_sr = np.array([ np.std(  magherr[ np.where( ind_r == i )[0] ]) for i in xrange(len(h_r)) ]) * 180.0 / np.pi
00231 magherr_sr[ np.where( num_r < 3 )[0] ] = 0 # Only put errorbars where we have sufficient data!
00232 
00233 magserr_mr = np.array([ np.mean( magserr[ np.where( ind_r == i )[0] ]) for i in xrange(len(h_r)) ]) * 180.0 / np.pi 
00234 magserr_sr = np.array([ np.std(  magserr[ np.where( ind_r == i )[0] ]) for i in xrange(len(h_r)) ]) * 180.0 / np.pi
00235 magserr_sr[ np.where( num_r < 3 )[0] ] = 0 # Only put errorbars where we have sufficient data!
00236 
00237 
00238 # | Err | vs. distance (Bar Plot)
00239 
00240 f = pl.figure( figsize=(10,6) )
00241 pl.axes([0.1,0.1,0.65,0.8])
00242 pl.bar( bins_d[:-1], magherr_md, 1.0, color='g', yerr=magherr_sd )
00243 pl.xlim( (0.0,8.0) )
00244 pl.ylim( (-20.0,180) )
00245 pl.xlabel( 'Distance From Tag (m)')
00246 pl.ylabel( '|Angular Error| (degrees)')
00247 # pl.title( 'ARGMAX' )
00248 pl.savefig( yaml_config['outimage'] + '_magherr_vs_dist.png' )
00249 pl.close()
00250 
00251 f = pl.figure( figsize=(10,6) )
00252 pl.axes([0.1,0.1,0.65,0.8])
00253 pl.bar( bins_d[:-1], magserr_md, 1.0, color='r', yerr=magserr_sd )
00254 pl.xlim( (0.0,8.0) )
00255 pl.ylim( (-20.0,180) )
00256 pl.xlabel( 'Distance From Tag (m)')
00257 pl.ylabel( '|Angular Error| (degrees)')
00258 # pl.title( 'STATIC' )
00259 pl.savefig( yaml_config['outimage'] + '_magserr_vs_dist.png' )
00260 
00261 
00262 # | Err | vs. MaxRSSI (Bar Plot)
00263 
00264 f = pl.figure( figsize=(10,6) )
00265 pl.axes([0.1,0.1,0.65,0.8])
00266 pl.bar( bins_r[:-1], magherr_mr, bins_r[1] - bins_r[0], color='g', yerr=magherr_sr )
00267 pl.xlim( (69,105) )
00268 print 'Max RSSI (argmax):'
00269 print '\t', bins_r[:-1]
00270 print '\t', magherr_mr
00271 print '\t', magherr_sr
00272 pl.ylim( (-20.0,180) )
00273 pl.xlabel( r'Max $\mathsf{E}[P(RSSI|\tau)]$')
00274 pl.ylabel( '|Angular Error| (degrees)')
00275 # pl.title( 'ARGMAX' )
00276 pl.savefig( yaml_config['outimage'] + '_magherr_vs_mrssi.png' )
00277 pl.close()
00278 
00279 f = pl.figure( figsize=(10,6) )
00280 pl.axes([0.1,0.1,0.65,0.8])
00281 pl.bar( bins_r[:-1], magserr_mr, bins_r[1] - bins_r[0], color='r', yerr=magserr_sr )
00282 print 'Max RSSI (static):'
00283 print '\t', bins_r[:-1]
00284 print '\t', magserr_mr
00285 print '\t', magserr_sr
00286 pl.xlim( (69,105) )
00287 pl.ylim( (-20.0,180) )
00288 pl.xlabel( r'Max $\mathsf{E}[P(RSSI|\tau)]$')
00289 pl.ylabel( '|Angular Error| (degrees)')
00290 # pl.title( 'ARGMAX' )
00291 pl.savefig( yaml_config['outimage'] + '_magserr_vs_mrssi.png' )
00292 pl.close()
00293 
00294 
00295 # | Err | vs. location  (Surface Plot)
00296 
00297 XBINS = 9
00298 YBINS = 5
00299 XMIN = 0.0
00300 XMAX = 11.0
00301 YMIN = 0.0
00302 YMAX = 7.0
00303 
00304 xy = np.row_stack([ npstats[0],
00305                     npstats[1] ])  # xy as 2xN
00306                      
00307 H,xedges,yedges = np.histogram2d( xy[0], xy[1],
00308                                   bins=(XBINS,YBINS),
00309                                   range=[[XMIN,XMAX],
00310                                          [YMIN,YMAX]])
00311 XS,YS = np.meshgrid( xedges, yedges )
00312 
00313 bins_ind_x = np.sum( xy[0][:,np.newaxis] > xedges[:-1], axis = 1 ) - 1  # Tells the index for each of the reads
00314 bins_ind_y = np.sum( xy[1][:,np.newaxis] > yedges[:-1], axis = 1 ) - 1
00315 
00316 def get_mean( xi, yi, darr ):
00317     # Which indices (into 3xN data) correspond to this x-bin and y-bin?
00318     data_ind = np.intersect1d( np.where( bins_ind_x == yi )[0], np.where( bins_ind_y == xi )[0] )
00319     return np.mean( darr[ data_ind ]) * 180 / np.pi
00320 
00321 # import pdb
00322 # pdb.set_trace()
00323 
00324 magherr_Z = np.ma.array( np.copy(H.T), mask=(H.T < 1) )
00325 magserr_Z = np.ma.array( np.copy(H.T), mask=(H.T < 1) )
00326 
00327 # pdb.set_trace()
00328 
00329 for i, (xi,yi) in enumerate( zip( *np.where( magherr_Z.mask == False ))):
00330     magherr_Z[xi,yi] = get_mean( xi, yi, magherr )
00331     magserr_Z[xi,yi] = get_mean( xi, yi, magserr )
00332 
00333 # pdb.set_trace()
00334 
00335 f = pl.figure( figsize=(10,6) )
00336 pl.hold(True)
00337 pl.pcolor( XS, YS, magherr_Z, cmap=pl.cm.jet ) # or hot?
00338 pl.xlim( (-1,12) )
00339 pl.ylim( (-1,8) )
00340 pl.axis( 'equal' )
00341 pl.clim( 0.0, 180.0 )
00342 pl.colorbar()
00343 pl.xlabel( 'X-Coordinate (meters)' )
00344 pl.ylabel( 'Y-Coordinate (meters)' )
00345 pl.savefig( yaml_config['outimage'] + '_magherr_contour.png' )
00346 pl.close()
00347 
00348 
00349 f = pl.figure( figsize=(10,6) )
00350 pl.hold(True)
00351 pl.pcolor( XS, YS, magserr_Z, cmap=pl.cm.jet ) # or hot?
00352 pl.xlim( (-1,12) )
00353 pl.ylim( (-1,8) )
00354 pl.axis( 'equal' )
00355 pl.clim( 0.0, 180.0 )
00356 pl.colorbar()
00357 pl.xlabel( 'X-Coordinate (meters)' )
00358 pl.ylabel( 'Y-Coordinate (meters)' )
00359 pl.savefig( yaml_config['outimage'] + '_magserr_contour.png' )
00360 pl.close()


rfid_datacapture
Author(s): Travis Deyle
autogenerated on Wed Nov 27 2013 12:11:16