process_bags_friis.py
Go to the documentation of this file.
00001 #!/usr/bin/python
00002 
00003 import roslib
00004 roslib.load_manifest( 'tf' )
00005 roslib.load_manifest( 'rosbag' )
00006 roslib.load_manifest( 'hrl_rfid' )
00007 roslib.load_manifest( 'std_msgs' )
00008 roslib.load_manifest( 'geometry_msgs' )
00009 import rospy
00010 
00011 import tf
00012 import tf.transformations as tft
00013 import rosbag
00014 from hrl_rfid.msg import RFIDreadArr, RFIDread
00015 from geometry_msgs.msg import PointStamped, PoseStamped
00016 from std_msgs.msg import Empty
00017 
00018 import sys
00019 import glob
00020 import yaml
00021 import time
00022 import optparse
00023 import cPickle as pkl
00024 import numpy as np, math
00025 from multiprocessing import Process
00026 
00027 import friis
00028 import process_bags_utils as pbut
00029 import math_util as mu
00030 
00031 
00032 # yaml_config:
00033 #     rfid_arr_topic:
00034 #     glob_files: 'cap_360/datacap/*.bag'
00035 #     antennas:
00036 #         EleLeftEar: '/ear_antenna_left'
00037 #         EleRightEar: '/ear_antenna_right'
00038 #         PR2_Head: '/head_rfid'
00039 #     rotframes:
00040 #         EleLeftEar: '/ear_pan_left'
00041 #         EleRightEar: '/ear_pan_right
00042 #         PR2_Head: '/head_pan_link'
00043 #     tags:
00044 #         tagid1:
00045 #             child_frame: '/tagid1'
00046 #             parent_frame: '/map'
00047 #             x_pos:
00048 #             y_pos:
00049 #             z_pos:
00050 #             x_orient:
00051 #             y_orient:
00052 #             z_orient:
00053 #             w_orient:
00054 
00055 class ProcessReads_Friis():
00056     # Processes a bagfile to and returns a dictionary that is ready to calculate Friis values:
00057     # d = { 'tagid1': [ PROC_READ1, PROC_READ2, ... ],
00058     #       ...
00059     #     }
00060     def __init__( self, yaml_config, tf_listener ):
00061         # Assume tf will work fine... we'll catch errors later.
00062         # self.listener = tf.TransformListener()
00063         self.listener = tf_listener
00064 
00065         # Initialize Variables
00066         self.d = {}
00067         self.yaml_config = yaml_config
00068 
00069         # Start Processing Incoming Reads
00070         rfid_arr_topic = self.yaml_config['rfid_arr_topic']  # eg. '/rfid/ears_reader_arr'
00071         self.sub = rospy.Subscriber( rfid_arr_topic, RFIDreadArr, self.rfid_cb )
00072 
00073 
00074     def proc_read( self, rr ):  # rr is RFIDread.msg
00075         # Check for antenna_frame definition
00076         if not self.yaml_config[ 'antennas' ].has_key( rr.antenna_name ):
00077             rospy.logout( 'Antenna name %s undefined in yaml_config.  Skipping' % rr.antenna_name )
00078             return None
00079         rdr_frame = self.yaml_config[ 'antennas' ][ rr.antenna_name ] # eg. /ear_antenna_left
00080 
00081         rdr_ps = PointStamped()
00082         rdr_ps.header.frame_id = rdr_frame
00083         rdr_ps.header.stamp = rospy.Time(0) # Will want to transform the point right now.
00084         
00085 
00086         # Check for tag ground truth definition
00087         if not self.yaml_config[ 'tags' ].has_key( rr.tagID ):
00088             rospy.logout( 'TagID %s undefined in yaml_config.  Skipping' % rr.tagID )
00089             return None
00090         tag_frame = self.yaml_config[ 'tags' ][ rr.tagID ][ 'child_frame' ] # eg. /datacap  (these are being published in other thread)
00091 
00092         tag_ps = PointStamped()
00093         tag_ps.header.frame_id = tag_frame
00094         tag_ps.header.stamp = rospy.Time(0) # Will want to transform the point right now.
00095 
00096         try:
00097             tag_in_rdr = self.listener.transformPoint( rdr_frame, tag_ps )
00098             rdr_in_tag = self.listener.transformPoint( tag_frame, rdr_ps )
00099         except Exception, e:
00100             rospy.logout('Transform(s) failed: %s.  Skipping' % e.__str__() )
00101             return None
00102 
00103         r_rdr, theta_rdr, phi_rdr = friis.CartToSphere( tag_in_rdr.point.x,
00104                                                         tag_in_rdr.point.y,
00105                                                         tag_in_rdr.point.z )
00106 
00107         r_tag, theta_tag, phi_tag = friis.CartToSphere( rdr_in_tag.point.x,
00108                                                         rdr_in_tag.point.y,
00109                                                         rdr_in_tag.point.z )
00110 
00111 
00112         tag_pos = PoseStamped()
00113         tag_pos.header.frame_id = tag_frame
00114         tag_pos.header.stamp = rospy.Time(0) # Will want to transform the point right now.
00115         tag_pos.pose.orientation.w = 1.0
00116 
00117         rdr_pos = PoseStamped()
00118         rdr_pos.header.frame_id = rdr_frame
00119         rdr_pos.header.stamp = rospy.Time(0) # Will want to transform the point right now.
00120         rdr_pos.pose.orientation.w = 1.0
00121 
00122         rot_pos = PoseStamped()  # Note this is POSE stamped!
00123         rot_frame = self.yaml_config[ 'rotframes' ][ rr.antenna_name ] # eg. /ear_pan_left
00124         rot_pos.header.frame_id = rot_frame
00125         rot_pos.header.stamp = rospy.Time(0)
00126         rot_pos.pose.orientation.w = 1.0
00127 
00128         base_pos = PoseStamped()  # Note this is POSE stamped!
00129         base_pos.header.frame_id = '/base_link'
00130         base_pos.header.stamp = rospy.Time(0)
00131         base_pos.pose.orientation.w = 1.0
00132 
00133         static_rot_frame = self.yaml_config[ 'staticrotframes' ][ rr.antenna_name ] # eg. /ear_pan_left
00134         rdr_p = PointStamped()
00135         rdr_p.header.frame_id = rdr_frame
00136         rdr_p.header.stamp = rospy.Time(0) # Will want to transform the point right now.
00137         rdr_p.point.x = 1.0
00138 
00139         tag_p = PointStamped()
00140         tag_p.header.frame_id = tag_frame
00141         tag_p.header.stamp = rospy.Time(0) # Will want to transform the point right now.
00142 
00143         try:
00144             tag_map = self.listener.transformPose( '/map', tag_pos )
00145             rdr_map = self.listener.transformPose( '/map', rdr_pos )
00146             rot_map = self.listener.transformPose( '/map', rot_pos )
00147             base_map = self.listener.transformPose( '/map', base_pos )
00148             rdr_p_rot = self.listener.transformPoint( static_rot_frame, rdr_p )
00149             tag_p_rot = self.listener.transformPoint( static_rot_frame, tag_p )
00150             
00151         except Exception, e:
00152             rospy.logout('Transform(s) failed (#2): %s.  Skipping' % e.__str__() )
00153             return None
00154 
00155         # theta_rot_map_all = tft.euler_from_quaternion([ rot_map.pose.orientation.x,
00156         #                                                 rot_map.pose.orientation.y,
00157         #                                                 rot_map.pose.orientation.z,
00158         #                                                 rot_map.pose.orientation.w ])
00159         # theta_rot_map = theta_rot_map_all[2] # roll, pitch, yaw
00160 
00161         # F_x = rot_map.pose.position.x
00162         # F_y = rot_map.pose.position.y
00163 
00164         # T_x = tag_map.pose.position.x
00165         # T_y = tag_map.pose.position.y
00166 
00167         # theta_tag_map = np.arctan2( T_y - F_y, T_x - F_x )
00168 
00169         # Rotation relative to starting angle given by rotation frame
00170         theta_rot_map = np.arctan2( rdr_p_rot.point.y, rdr_p_rot.point.x )
00171         # Rotation of the ground-truth tag position
00172         theta_tag_map = np.arctan2( tag_p_rot.point.y, tag_p_rot.point.x )
00173 
00174         return [ [r_rdr, theta_rdr, phi_rdr],  # all floats
00175                  [r_tag, theta_tag, phi_tag],  # all floats
00176                  [rr.rssi, rr.antenna_name, rr.tagID ], # int, string, string
00177                  [theta_rot_map, theta_tag_map], # floats (radians)
00178                  [ tag_map, rdr_map, rot_map, base_map, rdr_p_rot, tag_p_rot ] ] # geometry_msgs/PoseStamped
00179 
00180 
00181     def add_val_dict( self, val ):
00182         if not self.d.has_key( val[2][-1] ):  # rr.tagID
00183             self.d[ val[2][-1] ] = []
00184         self.d[ val[2][-1] ].append( val )
00185         
00186         
00187     def rfid_cb( self, msg ):
00188         # Note: if any exceptions are thrown in proc_read, it will return value None.
00189         #       Otherwise: PROC_READ
00190         pr = [ self.proc_read( r ) for r in msg.arr ]
00191         [ self.add_val_dict( v ) for v in pr if v != None ]
00192         return
00193 
00194     def stop_processing( self, fname ):
00195         # Explicitly stop registering new reads.
00196         self.sub.unregister()
00197 
00198         rospy.logout( 'ProcessReads_Friis: Dumping' )
00199         for k in self.d.keys():
00200             rospy.logout( '\tTag \'%s\':%d Reads' % ( k, len(self.d[k]) ))
00201 
00202         fn = fname
00203         fn_root = fn[ : fn.rfind( '/' )+1 ]  # eg. cap_360/datacap/
00204         fn_file = fn[ fn.rfind( '/' )+1 : ]  # eg. 1304590000_0_datacap2.bag
00205         fn_pkl = fn_file[ : fn_file.rfind( '.' ) ] + '_friis.pkl' # eg. 1304590000_0_datacap2_friis.pkl
00206         out_fn = fn_root + fn_pkl
00207 
00208         f = open( out_fn, 'w' )
00209         pkl.dump( self.d, f )
00210         f.close()
00211 
00212 
00213         return True
00214 
00215 
00216 def order_bagfiles( fnames ):
00217     # I'm too lazy to figure out how to reset time and prevent "TF_OLD_DATA" errors / warnings.
00218     #   Instead, we're just going to order the bag playback in wall-clock order.
00219 
00220     rospy.logout( 'Ordering the bagfiles in increasing order of start time.' )
00221     def gettime( fname ):
00222         # returns the timestamp of the first message
00223         b = rosbag.Bag( fname )
00224         msg = b.read_messages().next()
00225         tt = msg[-1].to_sec()
00226         b.close()
00227         return tt
00228 
00229     start_times = [ gettime( f ) for f in fnames ]
00230     rospy.logout( 'Done ordering.' )
00231     return [ fnames[ind] for ind in np.argsort( start_times ) ]
00232 
00233             
00234 if __name__ == '__main__':
00235     p = optparse.OptionParser()
00236     p.add_option('--yaml', action='store', type='string', dest='yaml', default='',
00237                  help='yaml file that describes this run.')
00238     opt, args = p.parse_args()
00239 
00240     if not opt.yaml:
00241         print 'YAML file required!'
00242         exit()
00243 
00244     rospy.set_param('use_sim_time',True)  # just to make sure!
00245     rospy.init_node( 'friis_bag_processor' )
00246 
00247     f = open( opt.yaml )
00248     yaml_config = yaml.load( f )
00249     f.close()
00250 
00251     # Start tf frame publishers for tag ground truth
00252     tf_threads = [ pbut.TFthread( yaml_config['tags'][k] ) for k in yaml_config['tags'].keys() ]
00253     tf_listener = tf.TransformListener()
00254 
00255     fnames = reduce( lambda x,y: x+y, [ glob.glob(i) for i in yaml_config['glob_files'] ], [] )
00256     ordered_fnames = order_bagfiles( fnames )
00257     for i,fname in enumerate( ordered_fnames ):
00258         rospy.logout( 'Processing [ %d of %d ]: %s' % (i+1, len(fnames), fname) )
00259 
00260         # Start the new bagplay
00261         bp = pbut.bagplay( fname )
00262         bp.run()
00263 
00264         prf = ProcessReads_Friis( yaml_config, tf_listener )
00265 
00266         while not bp.is_finished():
00267             pbut.sim_safe_sleep( 1.0 )  # Cannot use rostime, since it will stall when bag stops
00268 
00269         # bp.kill()
00270 
00271         prf.stop_processing( fname ) # will dump results to fname_friis.pkl (less .bag)
00272 
00273     # After Loop end (later)
00274     [ t.stop() for t in tf_threads ]
00275 
00276     
00277 
00278 


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