ros_pf.py
Go to the documentation of this file.
00001 #!/usr/bin/python
00002 
00003 import rfid_model
00004 import lib_pfilter
00005 
00006 import roslib
00007 roslib.load_manifest('visualization_msgs')
00008 roslib.load_manifest('hrl_lib')
00009 roslib.load_manifest('pfilter')
00010 roslib.load_manifest('tf')
00011 roslib.load_manifest('rfid_behaviors')
00012 import rospy
00013 
00014 import visualization_msgs.msg as vm
00015 import hrl_lib.transforms as tr
00016 import hrl_lib.viz as viz
00017 vsm = viz.single_marker
00018 import pfilter.pfilter as pfilter
00019 import tf.transformations as tft
00020 from rfid_behaviors.msg import RecorderReads
00021 from display_particles import DisplayParticles
00022 from geometry_msgs.msg import Quaternion, Point
00023 
00024 import random as rd
00025 import cPickle as pkl
00026 import numpy as np, math
00027 import pylab as pl
00028 import time
00029 import glob
00030 
00031 rospy.init_node( 'ros_pf' )
00032 
00033 tdb = { 0: ['OrangeMedBot',[]],
00034         1: ['TravisTVremo',[]],
00035         2: ['RedBottle   ',[]],
00036         3: ['OnMetalKeys ',[]],
00037         4: ['WhiteMedsBot',[]],
00038         5: ['BlueMedsBox ',[]],
00039         6: ['TeddyBearToy',[]],
00040         7: ['CordlessPhon',[]],
00041         8: ['BlueHairBrus',[]]}
00042 
00043 pts = { 0: ['BehindTree',[3.757, 6.017, 0.036]],
00044         1: ['FireplaceMantle',[5.090, 4.238, 1.514]],
00045         2: ['CircleEndTable',[5.399, 2.857, 0.607]],
00046         3: ['Couch',[3.944, 1.425, 0.527]],
00047         4: ['RectEndTable',[3.302, 0.932, 0.534]],
00048         5: ['BehindKitchenTable',[-0.339, -2.393, 0.793]],
00049         6: ['NearDishwaser',[-1.926, -0.835, 0.946]],
00050         7: ['InCupboard',[-3.257, 1.294, 1.397]],
00051         8: ['OnFilingCabinet',[-0.083, 2.332, 0.670]]}
00052 
00053 
00054 def process_read( pf, p_start, m ):
00055     # Note: p_start is numpy array (Nx3) and it's weights ([:,2]) will be modified in-place!
00056     # m is form: RFIDread, PoseStamped (ant in map), PoseStamped (robot base in map)
00057     #   We assume it is a postive reading for the desired tagID!
00058 
00059     xy_map = np.copy( p_start[:,0:2].T )  # 2xN
00060     
00061     # Antenna is at position given by m.ps_ant_map.
00062     #   IMPORTANT NOTE: I'm assuming that the antenna XY plane is parallel to the map XY plane!
00063     o = m.ps_ant_map.pose.orientation
00064     d = m.ps_ant_map.pose.position
00065     
00066     roll, pitch, yaw = tft.euler_from_quaternion([ o.x, o.y, o.z, o.w ])
00067     dx, dy = d.x, d.y
00068 
00069     # Transform xy_map points into antenna frame
00070     t_new = tr.composeHomogeneousTransform( tr.rotZ( yaw ),
00071                                             np.matrix([dx,dy,0.0]).T )
00072     trans = tr.invertHomogeneousTransform( t_new )
00073 
00074     xy_new = (trans * tr.xyToHomogenous( xy_map ))[0:2]  # This is a matrix!  (2xN)
00075     xy_new = np.array( xy_new ) # Convert it back to array!
00076 
00077     # Build new particles using old weights (Nx3)
00078     p_new = np.column_stack([ xy_new.T, p_start[:,2] ])  # take weights from last iteration
00079 
00080     rv = pf.step( 0.0, m.read.rssi, p_new, should_resample_func = pfilter.retFalse )
00081 
00082     # Put back the new weights:
00083     p_start[:,2] = rv[:,2]
00084     return
00085 
00086 
00087 
00088 def resample( pf, p_set ):
00089     print 'RESAMPLING'
00090     rt0 = time.time()
00091 
00092     # Perform low-variance resampling.  Note: p_set is already normalized
00093     p_uss = np.matrix(np.column_stack([ p_set[:,0:2],  # x,y
00094                                         np.zeros( p_set.shape[0] ),
00095                                         np.ones( p_set.shape[0] ),
00096                                         p_set[:,2] ]).T)  # w  ---> now 5xN
00097 
00098     p_uss_new = pfilter.set_resample_uss( p_set.shape[0], p_uss )
00099 
00100     p_set[:,0:2] = np.array(p_uss_new[0:2].T)
00101     p_set[:,2] = np.ones( p_set.shape[0] )
00102 
00103     # The USS resampler will give repeated particles.  Re-distribute them according to Joho.
00104     xy_set = p_set[:,0:2]
00105 
00106     discount = 0.95
00107     a = ( 3.0 * discount - 1 ) / ( 2.0 * discount )
00108     hsquare = 1.0 - np.power(a,2.0)
00109 
00110     p_mean = np.mean( xy_set )
00111     p_cov = np.cov( xy_set.T )
00112 
00113     for i, xyi in enumerate( xy_set ):
00114         n_xyi = np.random.multivariate_normal( a * xyi + (1-a) * p_mean,
00115                                                hsquare * p_cov, 1 ).flatten()
00116         xy_set[i] = n_xyi
00117 
00118     p_set[:,0:2] = xy_set
00119     print '\tResampling took %2.1f' % (time.time() - rt0)
00120 
00121     # update_display()
00122     return
00123     
00124 
00125 
00126 
00127 def process_run( trial_num, obj_num ):
00128     # Setup
00129     obj_name = tdb[obj_num][0]
00130     tname = obj_name.replace( ' ', '' )
00131 
00132     loc = (trial_num + obj_num) % 9
00133     loc_name = pts[loc][0]
00134     loc_pos  = np.array(pts[loc][1])  # Tag ground-truth location
00135 
00136     print 'Trial %d with Object %d (%s) at Position %d (%s)' % (trial_num,
00137                                                                 obj_num,
00138                                                                 obj_name,
00139                                                                 loc,
00140                                                                 loc_name)
00141 
00142     # build particles
00143     X,Y = np.meshgrid( np.arange(-5,8,0.05),
00144                        np.arange(-5,8,0.05) )
00145     xyw = np.row_stack([ X.flatten(),  # Build Nx3
00146                          Y.flatten(),
00147                          np.ones( X.shape ).flatten() ]).T # weights (multiplicative)
00148 
00149     p_set = np.copy( xyw )
00150 
00151 
00152     # Build pfilter obj.
00153     pf = pfilter.PFilter( rfid_model.NoMotion(), rfid_model.RfidModel( rfid_model.yaml_fname ))
00154 
00155 
00156     # Load search reads
00157     fname_prefix = '/home/travis/svn/robot1/src/projects/rfid_datacapture/src/rfid_datacapture/search_cap/'
00158 
00159     search_fname = fname_prefix
00160     search_fname += 'search_aware_home/woot_150_'+str(trial_num)+'_reads.pkl'
00161 
00162     f = open( search_fname, 'r' )
00163     dat_search_all = pkl.load( f )
00164     f.close()
00165 
00166     print '\tLEN_ALL (pre): ', len(dat_search_all)
00167     dat_search = [ d for d in dat_search_all if d.read.rssi != -1 and d.read.tagID == obj_name ] # Only positive reads!
00168     print '\tLEN_ALL (post): ', len(dat_search)
00169 
00170 
00171     # Load servo reads (if applicable): woot_150_7_tag_TeddyBearToy_servo.pkl
00172     servo_fname = fname_prefix
00173     servo_fname += 'search_aware_home/'
00174     servo_fname += 'woot_150_'+str(trial_num)+'_tag_'+obj_name.replace(' ','')+'_servo.pkl'
00175 
00176     glob_r = glob.glob( servo_fname )
00177     if glob_r == []:
00178         print '\t No results for this instance.\n\n'
00179         return
00180     if len(glob_r) > 1:
00181         print '\t Multiple results...?! Weirdness.  Skipping.'
00182         return
00183 
00184 
00185     f = open( servo_fname, 'r' )
00186     dat_servo_all = pkl.load( f )
00187     f.close()
00188 
00189     print '\tLEN_SERVO (pre): ', len(dat_servo_all)
00190     dat_servo = [ d for d in dat_servo_all if d.read.rssi != -1 and d.read.tagID == obj_name ] # Only positive reads!
00191     print '\tLEN_SERVO (post): ', len(dat_servo)
00192     print ''
00193 
00194 
00195     # Apply the particle filter for search (only)
00196     print '\tApplying Search-Only Measurements (%d)' % (len(dat_search))
00197     t0 = time.time()
00198     for m in dat_search:
00199         process_read( pf, p_set, m )
00200 
00201         # print 'Min: ', np.min( p_set[:,2] )
00202         # print 'Max: ', np.max( p_set[:,2] )
00203 
00204         neff = 1.0 / np.sum( np.power( p_set[:,2], 2.0 ))
00205         npart = len( p_set[:,2] )
00206         neff_rat = 100.0 * neff / npart  # ratio of "effective" particles (as a percentage)
00207         # print 'Neff: %d of %d (%2.1f %%)' % ( neff, npart, neff_rat )
00208 
00209         # if opt.resamp and neff_rat < 15.0:
00210         #     resample( pf, p_set )
00211 
00212     # Save the Search (only) results
00213     pf_fname = servo_fname.replace('_servo.pkl', '_pf_search.pkl')
00214 
00215     f = open( pf_fname, 'w' )
00216     pkl.dump( np.copy( p_set ), f )
00217     f.close()
00218 
00219 
00220     # Apply the particle filter for rest of servoing reads
00221     print '\n\tApplying Subsequent Servo Measurements (+%d => %d)' % (len(dat_servo), len(dat_servo)+len(dat_search))
00222     for m in dat_servo:
00223         process_read( pf, p_set, m )
00224 
00225         # print 'Min: ', np.min( p_set[:,2] )
00226         # print 'Max: ', np.max( p_set[:,2] )
00227 
00228         neff = 1.0 / np.sum( np.power( p_set[:,2], 2.0 ))
00229         npart = len( p_set[:,2] )
00230         neff_rat = 100.0 * neff / npart  # ratio of "effective" particles (as a percentage)
00231         # print 'Neff: %d of %d (%2.1f %%)' % ( neff, npart, neff_rat )
00232 
00233         # if opt.resamp and neff_rat < 15.0:
00234         #     resample( pf, p_set )
00235 
00236     dt = time.time() - t0
00237     print '\n\tExecution time: %3.2f (sec). Average rate: %3.2f (Hz)\n' % ( dt, (len(dat_search) + len(dat_servo))*1.0 / dt )
00238 
00239     # Save the Search + Servo results
00240     pf_fname = servo_fname.replace('_servo.pkl', '_pf_servo.pkl')
00241 
00242     f = open( pf_fname, 'w' )
00243     pkl.dump( np.copy( p_set ), f )
00244     f.close()
00245 
00246     print 'DONE.\n\n\n'
00247     return
00248 
00249     
00250 
00251 
00252 
00253 if __name__ == '__main__':
00254     # for trial_num in [4]:  # trial
00255     #     for obj_num in [5]:  # object
00256     #         process_run( trial_num, obj_num )
00257 
00258 
00259     for trial_num in xrange( 9 ):  # trial
00260         for obj_num in xrange( 9 ):  # object
00261             process_run( trial_num, obj_num )
00262 
00263 
00264 
00265 
00266 # Test:
00267 
00268 # def create_fake_read( rssi, dx, dy, dt ):
00269 #     rr = RecorderReads()
00270 #     rr.read.rssi = rssi
00271 
00272 #     q = Quaternion( *tft.quaternion_from_euler( 0.0, 0.0, dt ))
00273 #     p = Point( dx, dy, 0 )
00274 
00275 #     rr.ps_ant_map.pose.orientation = q
00276 #     rr.ps_ant_map.pose.position = p
00277 #     return rr
00278 
00279 # dat = [ create_fake_read( 84, 0, 0, math.radians( 0 )) ]
00280 # dat += [ create_fake_read( 84, 2, -2, math.radians( 90 )),
00281 #          create_fake_read( 84, 2, 2, math.radians( -90 )),
00282 #          create_fake_read( 84, 4, 0, math.radians( 180 )) ]
00283 
00284 
00285 # import optparse
00286 # p = optparse.OptionParser()
00287 # p.add_option('--trial', action='store', type='int', dest='trial',
00288 #              help='trial number (0-8)')
00289 # p.add_option('--obj', action='store', type='int', dest='obj',
00290 #              help='object number (0-8)')
00291 # p.add_option('--resamp', action='store_true', dest='resamp',
00292 #              help='resample?', default = False)
00293 # opt, args = p.parse_args()
00294 
00295 
00296 


rfid_pf
Author(s): Travis Deyle
autogenerated on Wed Nov 27 2013 12:03:34