00001
00002
00003
00004
00005 import roslib
00006 roslib.load_manifest( 'geometry_msgs' )
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
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
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
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] )
00089
00090
00091 self.h, self.bins = np.histogram( self.dat[0], 36, (-np.pi, np.pi ))
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
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
00097 self.hasposreads = np.sum( self.dat != -1 ) > 0
00098
00099
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 ))
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
00111
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
00140
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' )
00168 pl.plot( [ s.histmax_est * 180.0 / np.pi ], [ np.max(s.dat[2])+1 ], 'ko' )
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
00209 dist = npstats[2]
00210 h_d,bins_d = np.histogram( dist, 8, range=(0.0,8.0))
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))
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
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
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
00227
00228
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
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
00236
00237
00238
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
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
00259 pl.savefig( yaml_config['outimage'] + '_magserr_vs_dist.png' )
00260
00261
00262
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
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
00291 pl.savefig( yaml_config['outimage'] + '_magserr_vs_mrssi.png' )
00292 pl.close()
00293
00294
00295
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] ])
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
00314 bins_ind_y = np.sum( xy[1][:,np.newaxis] > yedges[:-1], axis = 1 ) - 1
00315
00316 def get_mean( xi, yi, darr ):
00317
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
00322
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
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
00334
00335 f = pl.figure( figsize=(10,6) )
00336 pl.hold(True)
00337 pl.pcolor( XS, YS, magherr_Z, cmap=pl.cm.jet )
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 )
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()