process_radpat_plots.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 
00021 import friis
00022 
00023 PLOT = False
00024 
00025 # glob_files: '/home/travis/svn/robot1/src/projects/rfid_datacapture/src/rfid_datacapture/cap_360/datacap/*.pkl'
00026 # filters:
00027 #   antennas:
00028 #     PR2_Head: '/head_rfid'
00029 #   tags:
00030 #     'datacap     ':
00031 
00032 if __name__ == '__main__':
00033     p = optparse.OptionParser()
00034     p.add_option('--yaml', action='store', type='string', dest='yaml', default='',
00035                  help='yaml file that describes this run.')
00036     p.add_option('--plot', action='store_true', dest='plot',
00037                  help='Pop-up the resulting plot')
00038     opt, args = p.parse_args()
00039 
00040     yaml_fname = opt.yaml
00041     PLOT = opt.plot
00042 else:
00043     yaml_fname = '/home/travis/svn/robot1/src/projects/rfid_datacapture/src/rfid_datacapture/cap_360/rad_plot_combined.yaml'
00044 
00045 
00046 # SCRIPT:
00047 
00048 
00049 if not yaml_fname:
00050     print 'YAML file required!'
00051     exit()
00052 else:
00053     f = open( yaml_fname )
00054     yaml_config = yaml.load( f )
00055     f.close()
00056 
00057 # XBINS = yaml_config['rad_histbins']['xbins']
00058 # YBINS = yaml_config['rad_histbins']['ybins']
00059 XBINS = 50
00060 YBINS = 50
00061 XMIN = yaml_config['rad_histbins']['xmin']
00062 XMAX = yaml_config['rad_histbins']['xmax']
00063 YMIN = yaml_config['rad_histbins']['ymin']
00064 YMAX = yaml_config['rad_histbins']['ymax']
00065 
00066 
00067 def add_files( d, arg ):
00068     fname, fcount = arg
00069     print 'Loading (%d of %d): %s' % (fcount, len(fnames), fname)
00070     f = open( fname, 'r' )
00071     d_new = pkl.load( f )
00072     f.close()
00073 
00074     for k in d_new.keys():
00075         if not d.has_key( k ):
00076             d[k] = []
00077         d[k] += d_new[k]
00078 
00079     return d
00080 
00081 def planar_xy( reading ):
00082     # Model estimate of P^inc_tag.
00083     # r_rdr, theta_rdr, phi_rdr, r_tag, theta_tag, phi_tag, rssi, antname, tagid = reading
00084     d_rdr = reading[0]
00085     d_tag = reading[1]
00086     read = reading[2]
00087     d_rot = reading[3]
00088     ps = reading[4]
00089 
00090     r_rdr, theta_rdr, phi_rdr = d_rdr
00091     r_tag, theta_tag, phi_tag = d_tag
00092 
00093     x,y,z = friis.SphereToCart( r_rdr, theta_rdr, phi_rdr )
00094     return [x,y]
00095 
00096 
00097 fnames = reduce( lambda x,y: x+y, [ glob.glob(i) for i in yaml_config['glob_files'] ], [] )
00098 
00099 if len(glob.glob(yaml_config['use_combined'])) > 0:
00100     print 'Loading pickle: %s' % (yaml_config['use_combined'])
00101     f = open( yaml_config['use_combined'], 'r' )
00102     data = pkl.load( f )
00103     f.close()
00104     print 'Done.'
00105 else:
00106     f = open( yaml_config['use_combined'], 'w' )
00107     d = reduce( add_files, zip(fnames,range(len(fnames))), {} )
00108 
00109     # Apply Filters:
00110 
00111     # Start with just the desired tagids
00112     all_reads = reduce( lambda x,y: x+y,
00113                         [ d[k] for k in yaml_config['filters']['tags'] if d.has_key(k) ],
00114                         [] )
00115 
00116     print '*** File \'%s\' had a total of %d reads ***' % ( yaml_fname, len( all_reads ))
00117 
00118     # Filter based on antennas
00119     # return [ [r_rdr, theta_rdr, phi_rdr],  # all floats
00120     #          [r_tag, theta_tag, phi_tag],  # all floats
00121     #          [rr.rssi, rr.antenna_name, rr.tagID ], # int, string, string
00122     #          [theta_rot_map, theta_tag_map], # floats (radians)
00123     #          [ tag_map, rdr_map, rot_map ] ] # geometry_msgs/PoseStamped
00124 
00125     ant_dict = dict.fromkeys( yaml_config['filters']['antennas'] )
00126     filt_reads = [ r for r in all_reads if ant_dict.has_key( r[2][1] ) ]
00127 
00128     reads = filt_reads
00129 
00130     data = np.array([ planar_xy(r) + [ r[2][0] ] for r in reads ]).T  # 3xN: x,y,rssi
00131     print 'Dumping data into combined pickle file: %s ' % (yaml_config['use_combined'])
00132     pkl.dump( data, f, -1 )
00133     f.close()
00134     print 'Done.  Re-run.'
00135     exit()
00136 
00137 
00138 # data will be 3xN => x, y, RSSI
00139 
00140 
00141 # Calculate Useful Values
00142 
00143 xy = data[0:2,:]
00144 rssi = data[2]
00145 pos_mask = rssi != -1
00146 neg_mask = rssi == -1
00147 
00148 # *******************
00149 # Reads per location
00150 # *******************
00151 H,xedges,yedges = np.histogram2d( xy[0], xy[1],
00152                                   bins=(XBINS,YBINS),
00153                                   range=[[XMIN,XMAX],
00154                                          [YMIN,YMAX]])
00155 XS,YS = np.meshgrid( xedges, yedges )
00156 
00157 bins_ind_x = np.sum( xy[0][:,np.newaxis] > xedges[:-1], axis = 1 ) - 1  # Tells the index for each of the reads
00158 bins_ind_y = np.sum( xy[1][:,np.newaxis] > yedges[:-1], axis = 1 ) - 1
00159 
00160 d = np.copy( H.T ) # The H matrices are actually transposed from how we display
00161 d[ np.where( d > 100 ) ] = 100 # I just want to see which locations have few / no reads.
00162 dma = np.ma.array( d, mask=(d<yaml_config['points_per_loc']) )
00163 
00164 f = pl.figure( figsize=(10,6) )
00165 pl.hold(True)
00166 pl.pcolor( XS, YS, dma, cmap=pl.cm.jet ) # or hot?
00167 pl.clim( 0.0, 100.0 )
00168 pl.colorbar()
00169 pl.xlabel( 'X-Coordinate (meters)' )
00170 pl.ylabel( 'Y-Coordinate (meters)' )
00171 pl.title( 'Number of reads attempts at each location' )
00172 pl.savefig( yaml_config['outimage'] + '_datapoints_masked.png' )
00173 
00174 f = pl.figure( figsize=(10,6) )
00175 pl.hold(True)
00176 pl.pcolor( XS, YS, d, cmap=pl.cm.jet ) # or hot?
00177 pl.clim( 0.0, 100.0 )
00178 pl.colorbar()
00179 pl.xlabel( 'X-Coordinate (meters)' )
00180 pl.ylabel( 'Y-Coordinate (meters)' )
00181 pl.title( 'Number of reads attempts at each location' )
00182 pl.savefig( yaml_config['outimage'] + '_datapoints_notmasked.png' )
00183 
00184 # *******************
00185 # Tag detection probability
00186 # *******************
00187 
00188 # Note... I'm still using H from above!
00189 
00190 # Need to rebuild dma to not be capped at 100 reads.
00191 dma = np.ma.array( np.copy(H.T), mask=(H.T<yaml_config['points_per_loc']) )
00192 H_pos,xedges,yedges = np.histogram2d( xy[0][pos_mask], xy[1][pos_mask],
00193                                       bins=(XBINS,YBINS),
00194                                       range=[[XMIN,XMAX],
00195                                              [YMIN,YMAX]])
00196 
00197 # Where was it actually detected.
00198 dma_det = np.ma.array( np.copy(H_pos.T), mask=(H.T<yaml_config['points_per_loc']) )
00199 
00200 # Compute the probability...
00201 dma_det[ np.where(dma.mask==False) ] = (1.0*dma_det[ np.where(dma_det.mask==False) ]) / (1.0*dma[ np.where(dma_det.mask==False) ])
00202 
00203 f = pl.figure( figsize=(10,6) )
00204 pl.hold(True)
00205 pl.pcolor( XS, YS, dma_det, cmap=pl.cm.jet ) # or hot?
00206 pl.clim( 0.0, 1.0 )
00207 pl.colorbar()
00208 pl.xlabel( 'X-Coordinate (meters)' )
00209 pl.ylabel( 'Y-Coordinate (meters)' )
00210 pl.title( 'Probability of Tag Detection' )
00211 pl.savefig( yaml_config['outimage'] + '_tag_detect_prob.png' )
00212 
00213 
00214 # *******************
00215 # Mean RSSI
00216 # *******************
00217 
00218 # Note... I'm still using H and H_pos from above!
00219 
00220 def get_mean( xi, yi ):
00221     # Which indices (into 3xN data) correspond to this x-bin and y-bin?
00222     data_ind = np.intersect1d( np.where( bins_ind_x == yi )[0], np.where( bins_ind_y == xi )[0] )
00223     rm = np.mean([ r for r in rssi[ data_ind ] if r != -1 ])
00224     return rm
00225 
00226 def get_std( xi, yi ):
00227     # Which indices (into 3xN data) correspond to this x-bin and y-bin?
00228     data_ind = np.intersect1d( np.where( bins_ind_x == yi )[0], np.where( bins_ind_y == xi )[0] )
00229     rm = np.std([ r for r in rssi[ data_ind ] if r != -1 ])
00230     return rm
00231 
00232 # To calculate the rssi mean...
00233 dma_rm = np.ma.array( np.copy(H_pos.T), mask=(H_pos.T<yaml_config['rssi_points_per_loc']) )
00234 
00235 means = np.ma.copy( dma_rm )
00236 for i, (xi,yi) in enumerate( zip( *np.where( dma_rm.mask == False ))):
00237     # Note: the bin indices are relative to H-matrices, which are transposed.  So we switch xi/yi
00238     means[xi,yi] = get_mean( xi, yi )
00239 
00240 stddev = np.ma.copy( dma_rm )
00241 for i, (xi,yi) in enumerate( zip( *np.where( dma_rm.mask == False ))):
00242     # Note: the bin indices are relative to H-matrices, which are transposed.  So we switch xi/yi
00243     stddev[xi,yi] = get_std( xi, yi )
00244     
00245 
00246 f = pl.figure( figsize=(10,6) )
00247 pl.hold(True)
00248 pl.pcolor( XS, YS, means, cmap=pl.cm.jet ) # or hot?
00249 pl.clim( 72,96 )
00250 pl.colorbar()
00251 pl.xlabel( 'X-Coordinate (meters)' )
00252 pl.ylabel( 'Y-Coordinate (meters)' )
00253 pl.title( 'Mean RSSI' )
00254 pl.savefig( yaml_config['outimage'] + '_tag_rssi_mean.png' )
00255 
00256 f = pl.figure( figsize=(10,6) )
00257 pl.hold(True)
00258 pl.pcolor( XS, YS, stddev, cmap=pl.cm.jet ) # or hot?
00259 pl.colorbar()
00260 pl.xlabel( 'X-Coordinate (meters)' )
00261 pl.ylabel( 'Y-Coordinate (meters)' )
00262 pl.title( 'Standard Deviation of RSSI' )
00263 pl.savefig( yaml_config['outimage'] + '_tag_rssi_std.png' )
00264 
00265 
00266 if PLOT:
00267     pl.show()
00268 
00269 
00270 
00271 # SAVE SENSOR MODEL
00272 
00273 fname = yaml_config['use_combined'].replace('.pkl','_MODEL.pkl')
00274 
00275 MODEL = { 'detect_model': np.ma.copy( dma_det ),
00276           'rssi_model': np.ma.copy( means ),
00277           'stddev_model': np.ma.copy( stddev ),
00278           'xedges': xedges, # These are necessary to define the boundaries of the bins.
00279           'yedges': yedges } 
00280 
00281 f = open( fname, 'w' )
00282 pkl.dump( MODEL, f, -1 )
00283 f.close()
00284 


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