M5e_reader_sim.py
Go to the documentation of this file.
00001 import roslib
00002 roslib.load_manifest( 'rfid_people_following' )
00003 roslib.load_manifest( 'tf' )
00004 roslib.load_manifest( 'geometry_msgs' )
00005 roslib.load_manifest('hrl_rfid')
00006 import rospy
00007 
00008 from hrl_rfid.msg import RFIDread
00009 from hrl_rfid.msg import RFIDreadArr
00010 from hrl_rfid.srv import RfidSrv
00011 import tf
00012 from geometry_msgs.msg import PointStamped
00013 
00014 import sys, serial, time, string
00015 from threading import Thread
00016 import friis
00017 import pickle as pkl
00018 import numpy as np, math
00019 
00020 # A nice functional print function (Norvig)
00021 def prin(x): print x
00022 
00023 f = open( '/home/travis/svn/data_robot1/rfid_data/pan_captures/model_fit.pkl', 'r' )
00024 d = pkl.load( f )
00025 f.close()
00026 
00027 def calculate_angle( pt1 ):
00028     return np.arctan2( pt1.point.y, pt1.point.x )
00029     
00030 class M5e:
00031     "Interface to Mercury M5e and M5e-Compact"
00032     def __init__(self, portSTR='/dev/robot/RFIDreader', baudrate=9600, 
00033         TXport=1, RXport=1, readPwr=2300, protocol='GEN2', compact=True, verbosity_func=prin):
00034 
00035         # verbosity_func should alawys take string as an input.  Lets us choose a selective 
00036         #   print function (like rospy.logout) instead of built-in print.
00037 
00038         self.TXport = TXport        # Initialized transmit antenna
00039         self.RXport = RXport        # Initialized receive antenna
00040         self.readPwr = readPwr      # Initialized read TX power in centi-dBm
00041         self.protocol = protocol    # Initialized protocol
00042         self.compact = compact
00043         self.prin = verbosity_func
00044         self.ser = None
00045 
00046         try:
00047             rospy.init_node( 'RFID_Simulator_Friis' )
00048         except rospy.ROSException:
00049             pass
00050         
00051         self.prin( 'Initializing M5e (or M5e-Compact)' )
00052         self.listener = tf.TransformListener()
00053 
00054         rospy.logout('Simulated M5e: Waiting for odom_combined-antenna tf')
00055         self.listener.waitForTransform('/ear_antenna_left', '/odom_combined',
00056                                        rospy.Time(0), timeout = rospy.Duration(100) )
00057         self.listener.waitForTransform('/ear_antenna_right', '/odom_combined',
00058                                        rospy.Time(0), timeout = rospy.Duration(100) )
00059         self.listener.waitForTransform('/left_rotation_center', '/odom_combined',
00060                                        rospy.Time(0), timeout = rospy.Duration(100) )
00061         self.listener.waitForTransform('/right_rotation_center', '/odom_combined',
00062                                        rospy.Time(0), timeout = rospy.Duration(100) )
00063         self.listener.waitForTransform('/base_link', '/odom_combined',
00064                                        rospy.Time(0), timeout = rospy.Duration(100) )
00065         self.listener.waitForTransform('/tag_gt', '/odom_combined',
00066                                        rospy.Time(0), timeout = rospy.Duration(100) )
00067         rospy.logout('Simulated M5e: Transforms ready')
00068         self.prin( 'M5e Initialized' )
00069         
00070         
00071     def ChangeAntennaPorts(self, TXport, RXport):
00072         "Changes TX and RX ports"
00073         self.TXport = TXport
00074         self.RXport = RXport
00075         
00076     # Currently Unimplemented!
00077     def QueryEnvironment(self, timeout=50):
00078         rospy.sleep( timeout * 0.001 )
00079         return []
00080 
00081     # Relies on a single tag whose coord frame is '/tag_gt'
00082     #   Lots of hardcoding... boo!
00083     def TrackSingleTag(self, tagID, timeout=50):
00084         rospy.sleep( timeout * 0.001 )
00085 
00086         # 6DOF params -- Calculate these using tf
00087         ant_zp = PointStamped()
00088         ant_zp.header.stamp = rospy.Time(0)
00089 
00090         tag_zp = PointStamped()
00091         tag_zp.header.stamp = rospy.Time(0)
00092         tag_zp.header.frame_id = '/tag_gt'
00093         
00094         if self.TXport == 1 and self.RXport == 1: # 'EleLeftEar'
00095             ear_frame = '/ear_antenna_left'
00096         else: # 'EleRightEar'
00097             ear_frame = '/ear_antenna_right'
00098 
00099         ant_zp.header.frame_id = ear_frame
00100 
00101         # should probably catch exceptions and throw big warnings...
00102         tag_in_ant = self.listener.transformPoint( ear_frame, tag_zp )
00103         ant_in_tag = self.listener.transformPoint( '/tag_gt', ant_zp )
00104 
00105 
00106         tag_in_ant_sphere = np.array( friis.CartToSphere2( tag_in_ant.point.x,
00107                                                            tag_in_ant.point.y,
00108                                                            tag_in_ant.point.z ))
00109         ant_in_tag_sphere = np.array( friis.CartToSphere2( ant_in_tag.point.x,
00110                                                            ant_in_tag.point.y,
00111                                                            ant_in_tag.point.z ))
00112         
00113 
00114         # Determine Friis Powers
00115         Ptag = friis.pwr_inc_tag( tag_in_ant_sphere[0], # radius
00116                                   friis.patch.G, tag_in_ant_sphere[1], tag_in_ant_sphere[2],
00117                                   friis.dipole.G, ant_in_tag_sphere[1], ant_in_tag_sphere[2] )
00118         Prdr = friis.pwr_inc_rdr( tag_in_ant_sphere[0], # radius
00119                                   friis.patch.G, tag_in_ant_sphere[1], tag_in_ant_sphere[2],
00120                                   friis.dipole.G, ant_in_tag_sphere[1], ant_in_tag_sphere[2] )
00121         Prdr_dBm = friis.WattsToDBm( Prdr )
00122 
00123         # Calculate expectation (read/no-read and RSSI if applicable)
00124         sim_read = Ptag > friis.DBmToWatts( -18.0 )
00125         sim_rssi_ind = np.sum( Prdr_dBm > d['bins'][:-1] ) - 1
00126         sim_rssi_ind = np.clip( sim_rssi_ind, 0, sim_rssi_ind ) # if less than 0 (power lower than in previous data)
00127         sim_rssi = d['mean_rssi'][sim_rssi_ind]
00128 
00129         if sim_read:
00130             return int(sim_rssi) # be a little more accurate by returning int
00131         else:
00132             return -1
00133 
00134 
00135 
00136 
00137 # Modeled off lib_M5e.M5e_Poller
00138 class ROS_M5e( Thread ):
00139     QUERY_MODE = 'query'
00140     TRACK_MODE = 'track'
00141     
00142     def __init__(self, name = 'reader1', readPwr = 2300,
00143                  portStr = '/dev/robot/RFIDreader',
00144                  antFuncs = [], callbacks = []):
00145 
00146         Thread.__init__(self)
00147         self.should_run =  True
00148 
00149         try:
00150             rospy.init_node( 'rfid_m5e_' + name )
00151         except rospy.ROSException:
00152             pass
00153 
00154         self.mode = ''
00155         self.name = name + '_reader'
00156 
00157         rospy.logout( 'ROS_M5e: Launching RFID Reader' )
00158         rospy.logout( 'ROS_M5e: Please check out our related work @ http://www.hsi.gatech.edu/hrl/project_rfid.shtml' )
00159         rospy.logout( 'ROS_M5e: '+self.name+' Building & Connecting to reader' )
00160 
00161         def prin( x ): rospy.logout( 'ROS_M5e: lib_M5e: ' + x ) # use rospy.logout in underlying lib's output
00162 
00163         self.reader = M5e(readPwr=readPwr, portSTR = portStr, verbosity_func = prin)
00164         self.antFuncs = antFuncs
00165         self.callbacks = callbacks + [self.broadcast]
00166 
00167         rospy.logout( 'ROS_M5e: publishing RFID reader with type RFIDread to channel /rfid/'+name+'_reader' )
00168         self.channel       = rospy.Publisher('/rfid/'+name+'_reader', RFIDread)
00169         self.pub_arr = rospy.Publisher('/rfid/'+name+'_reader_arr', RFIDreadArr)
00170         self._mode_service_obj = rospy.Service('/rfid/'+name+'_mode',
00171                                                 RfidSrv, self._mode_service)
00172 
00173         rospy.logout( 'ROS_M5e: '+self.name+' Inialized and awaiting instructions' )
00174 
00175         self.start()  # Thread: calls self.run()
00176 
00177     def run( self ): 
00178         while self.should_run:
00179             if self.mode == self.QUERY_MODE:
00180                 for aF in self.antFuncs:
00181                     antennaName = aF(self.reader)    # let current antFunc make appropriate changes
00182                     results = self.reader.QueryEnvironment()
00183                     if len(results) == 0:
00184                         results = [[ '', -1 ]] # [[ tagid, rssi ], ...]
00185                         #datum = [antennaName, '', -1]
00186                         #[cF(datum) for cF in self.callbacks]
00187                     arr = []
00188                     t_now = rospy.Time.now()
00189                     for tagid, rssi in results:
00190                         rv = RFIDread( None, antennaName, tagid, rssi )
00191                         rv.header.stamp = t_now
00192                         arr.append( rv )
00193                         datum = [antennaName, tagid, rssi]
00194                         [cF(datum) for cF in self.callbacks]
00195                     rfid_arr = RFIDreadArr()
00196                     rfid_arr.header.stamp = t_now
00197                     rfid_arr.arr = arr
00198                     self.pub_arr.publish( rfid_arr )
00199             elif self.mode == self.TRACK_MODE:
00200                 for aF in self.antFuncs:
00201                     antennaName = aF(self.reader)    # let current antFunc make appropriate changes
00202                     tagid = self.tag_to_track
00203                     rssi = self.reader.TrackSingleTag(tagid, timeout=100)
00204                     t_now = rospy.Time.now()
00205                     rv = RFIDread( None, antennaName, tagid, rssi )
00206                     rv.header.stamp = t_now
00207                     rfid_arr = RFIDreadArr()
00208                     rfid_arr.header.stamp = t_now
00209                     rfid_arr.arr = [rv]
00210                     self.pub_arr.publish( rfid_arr )
00211                     #if rssi != -1:
00212                     datum = [antennaName, tagid, rssi]
00213                     [cF(datum) for cF in self.callbacks]
00214             else:
00215                 time.sleep(0.005)
00216 
00217         rospy.logout( 'ROS_M5e: '+self.name+' Shutting down reader' )
00218 
00219     def stop( self ):
00220         self.should_run = False
00221         self.join(3)
00222         if (self.isAlive()):
00223             raise RuntimeError("ROS_M5e: unable to stop thread")            
00224             
00225     def broadcast(self, data):
00226         antName, tagid, rssi = data
00227         rv = RFIDread( None, antName, tagid, rssi )
00228         rv.header.stamp = rospy.Time.now()
00229         self.channel.publish( rv )
00230     
00231     # For internal use only
00232     def _mode_service(self, data):
00233         val = data.data
00234         if len(val) == 0:
00235             rospy.logout( 'ROS_M5e: Mode Service called with invalid argument: ' + str(val) )
00236         elif len(val) == 1:
00237             if val[0] == self.QUERY_MODE:
00238                 rospy.logout( 'ROS_M5e: '+self.name+' Entering Query Mode' )
00239                 self.mode = self.QUERY_MODE
00240             else:
00241                 rospy.logout( 'ROS_M5e: '+self.name+' Stopping Reader' )
00242                 self.mode = ''
00243         elif len(val) == 2:
00244             if val[0] == self.TRACK_MODE and len(val[1]) == 12:
00245                 rospy.logout( 'ROS_M5e: '+self.name+' Entering Track Mode: ' + str(val[1]) )
00246                 self.mode = self.TRACK_MODE
00247                 self.tag_to_track = val[1]
00248             else:
00249                 rospy.logout( 'ROS_M5e: Mode Service called with invalid argument: ' + str(val) )
00250         else:
00251             rospy.logout( 'ROS_M5e: Mode Service called with invalid argument: ' + str(val) )
00252         return True
00253 
00254 
00255 
00256 # -----------------------------------------------
00257 # Likely Callbacks: (various antennas)
00258 # -----------------------------------------------
00259 
00260 def EleLeftEar(M5e):
00261     M5e.ChangeAntennaPorts(1,1)
00262     rospy.sleep(0.010)
00263     return 'EleLeftEar'
00264 
00265 def EleRightEar(M5e):
00266     M5e.ChangeAntennaPorts(2,2)
00267     rospy.sleep(0.010)
00268     return 'EleRightEar'
00269 
00270 def Hand_Right_1(M5e):
00271     # GPIO1 = 1, GPIO2 = 0
00272     M5e.TransmitCommand('\x02\x96\x01\x01')
00273     M5e.ReceiveResponse()
00274     M5e.TransmitCommand('\x02\x96\x02\x00')
00275     M5e.ReceiveResponse()
00276     return 'Hand_Right_1'
00277 
00278 def Hand_Right_2(M5e):
00279     # GPIO1 = 1, GPIO2 = 1
00280     M5e.TransmitCommand('\x02\x96\x01\x01')
00281     M5e.ReceiveResponse()
00282     M5e.TransmitCommand('\x02\x96\x02\x01')
00283     M5e.ReceiveResponse()
00284     return 'Hand_Right_2'
00285 
00286 def Hand_Left_1(M5e):
00287     # GPIO1 = 0, GPIO2 = 0
00288     M5e.TransmitCommand('\x02\x96\x01\x00')
00289     M5e.ReceiveResponse()
00290     M5e.TransmitCommand('\x02\x96\x02\x00')
00291     M5e.ReceiveResponse()
00292     return 'Hand_Left_1'
00293 
00294 def Hand_Left_2(M5e):
00295     # GPIO1 = 0, GPIO2 = 1
00296     M5e.TransmitCommand('\x02\x96\x01\x00')
00297     M5e.ReceiveResponse()
00298     M5e.TransmitCommand('\x02\x96\x02\x01')
00299     M5e.ReceiveResponse()
00300     return 'Hand_Left_2'
00301 
00302 def PrintDatum(data):
00303     ant, ids, rssi = data
00304     print data
00305 


rfid_people_following
Author(s): Travis Deyle (Healthcare Robotics Lab, Georgia Tech)
autogenerated on Wed Nov 27 2013 11:38:30