wiki:Tutorials/Wireless/MeasurementTool

Version 1 (modified by nilanjan, 5 years ago) ( diff )

Measurement tools

This tutorial will demonstrate data collection method using the OML interface.

Prerequisites

  1. Accounts, ssh keys
  2. Reservation
  3. Familiarity with USRPs.

Description

This tutorial utilizes an existing application provided by the UHD driver. The application used is rx_multi_sample which is a c++ application that configures and reads samples from multiple the USRPs. A c++ based OML-wrapper has been added to this application to store FFTed blocks of samples to an OML database server.

Set up

  1. First ssh into the console that you made a reservation.
  2. Use the omf stat to find all the experiment servers and SDRs that are seen by OMF.
    console> omf stat -t all
     INFO NodeHandler: OMF Experiment Controller 5.4 (git 861d645)
     INFO NodeHandler: Slice ID: default_slice (default)
     INFO NodeHandler: Experiment ID: default_slice-2019-05-14t10.58.59.167-04.00
     INFO NodeHandler: Message authentication is disabled
     INFO property.resetDelay: resetDelay = 200 (Fixnum)
     INFO property.resetTries: resetTries = 1 (Fixnum)
     INFO property.nodes: nodes = "system:topo:all" (String)
     INFO property.summary: summary = false (FalseClass)
     INFO Topology: Loaded topology 'system:topo:all'.
    
    Talking to the CMC service, please wait
    -----------------------------------------------
     Node: mob1.sb1.cosmos-lab.org           State: POWERON
     Node: mob2.sb1.cosmos-lab.org           State: POWERON
     Node: mob3.sb1.cosmos-lab.org           State: POWERON
     Node: sdr1-lg1.sb1.cosmos-lab.org       State: POWERON
     Node: sdr1-md1.sb1.cosmos-lab.org       State: POWERON
     Node: sdr2-lg1.sb1.cosmos-lab.org       State: POWERON
     Node: sdr2-md1.sb1.cosmos-lab.org       State: POWERON
     Node: srv1-lg1.sb1.cosmos-lab.org       State: POWERON
     Node: srv2-lg1.sb1.cosmos-lab.org       State: POWERON
    -----------------------------------------------
    
     INFO EXPERIMENT_DONE: Event triggered. Starting the associated tasks.
     INFO NodeHandler:
     INFO NodeHandler: Shutting down experiment, please wait...
     INFO NodeHandler:
     INFO run: Experiment default_slice-2019-05-14t10.58.59.167-04.00 finished after 0:5
    
  1. Load the baseline-sdr.ndz image onto the experiment server. This image has the UHD driver and other pertinent libraries pre-installed. For this tutoral we'll use srv1-lg1.sb1.cosmos-lab.org as the experiment server.
    console> omf load -i baseline-sdr.ndz -t srv1-lg1.sb1.cosmos-lab.org
    
  1. After loading is complete turn on the experiment server. We'll also use the sdr1-lg1.sb1.cosmos-lab.org which is an N310 USRP. So turn this on as well.
    console> omf tell -a on -t srv1-lg1.sb1.cosmos-lab.org,sdr1-lg1.sb1.cosmos-lab.org
    
  1. Use the omf stat command again to verify ON/OFF status of the devices.
    console> omf stat -t srv1-lg1.sb1.cosmos-lab.org,sdr1-lg1.sb1.cosmos-lab.org
    
  1. Configure interface
    ifconfig enp1s0 10.115.1.1 netmask 255.255.0.0 mtu 8000
    
  1. Next ssh into the experiment server and discover the USRP that we turned on. We'll need the ip address for this USRP; At the command line do a 'host sdr1-lg1.sb1.cosmos-lab.org' to find its ip address. Then run uhd_find_devices with the —args option to discovery the USRP.
    native@localhost:~$ host sdr1-lg1.sb1.cosmos-lab.org
    sdr1-lg1.sb1.cosmos-lab.org has address 10.113.2.1
    
    native@localhost:~$ uhd_find_devices --args="addr=10.113.2.1"
    
    <<some output here>>>
    

Explain rx_multi_receive application and how to use

Navigate to the ~/RX_MULTI_RECEIVE directory - this contains the files that build the rx_multi_receive application. This is a c++ application that can be run on the experiment server to collect a set of continuous samples.

Use the —help option to display all the variables rx_multi_receive accepts.

root@node20-1:~/RX_MULTI_RECEIVE# ./rx_multi_receive --help
linux; GNU C++ version 4.8.4; Boost_105400; UHD_003.010.001.001-0-unknown

UHD RX Multi Receive Allowed options:
  --help                        help message
  --args arg                    single uhd device address args
  --secs arg (=1.5)             number of seconds in the future to receive
  --nsamps arg (=10000)         total number of samples to receive
  --freq arg (=900000000)       RF center frequency in Hz for all channels
  --rate arg (=6250000)         rate of incoming samples for all channels
  --gain arg (=0)               gain for the RF chain for all channels
  --ant arg                     rx antenna selection for all channels
  --prefix arg                  enables file output with filename prefix
  --addr arg                    udp address: 10.10.0.10
  --port arg (=1337)            udp port: 1337
  --sync arg (=now)             synchronization method: now, pps, mimo
  --subdev arg                  subdev spec (homogeneous across motherboards)
  --dilv                        specify to disable inner-loop verbose
  --int-n                       tune USRP with integer-N tuning
  --channels arg (=0)           which channel(s) to use (specify "0", "1",
                                "0,1", etc)
  --oml-id arg                  OML sender ID - pass the hostname here
  --oml-domain arg (=omlcli)    file name for OML database
  --oml-collect arg (=oml:3003) Storage options:
                                 network: <server:port>
                                 local text file: <file:my_file_name>

To use rx_multi_receive standalone on an experiment server we can using the following options

root@node20-1:~/RX_MULTI_RECEIVE# ~/RX_MULTI_RECEIVE/rx_multi_receive --args="addr0=10.10.23.5" --freq 2440e6 --rate 20e6 --gain 3
 --nsamps 1024000 --channels "0" --dilv

—args="addr0=10.10.23.5" specifies the SDR's IP address. —freq 2440e6 sets the center freq —rate 20e6 sets sampling rate —gain 3 sets receive path gain —nsamps 1024000 number of samples to collect

Executing the application with only the above options will only configure the USRP's radio parameters and read in the specified nu mber of samples. However the samples will be lost once the application exits. You should see output similar to the following.

linux; GNU C++ version 4.8.4; Boost_105400; UHD_003.010.001.001-0-unknown


Creating the usrp device with: addr0=10.10.23.5...
-- X300 initialization sequence...
-- Determining maximum frame size... 7972 bytes.
-- Setup basic communication...
-- Loading values from EEPROM...
-- Setup RF frontend clocking...
-- Radio 1x clock:200

:
:
:

Using Device: Single USRP:
  Device: X-Series Device
  Mboard 0: X310
  RX Channel: 0
    RX DSP: 0
    RX Dboard: A
    RX Subdev: UBX RX
  TX Channel: 0
    TX DSP: 0
    TX Dboard: A
    TX Subdev: UBX TX
  TX Channel: 1
    TX DSP: 0
    TX Dboard: B
    TX Subdev: UBX TX

Number mboards        = 1
Number of rx channels = 1
Setting RX Rate: 20.000000 Msps...
Actual RX Rate: 20.000000 Msps...

Setting RX Freq: 2440.000000 MHz...
Actual RX Freq: 2440.000000 MHz...

Setting RX Gain: 3.000000 dB...
Actual RX Gain: 3.000000 dB...

Setting device timestamp to 0...
channel_nums.size() = 1

UHD Warning:
    For this connection, UHD recommends a send frame size of at least 8000 for best
    performance, but your system's MTU will only allow 7972.
    This will negatively impact your maximum achievable sample rate.

UHD Warning:
    For this connection, UHD recommends a receive frame size of at least 8000 for best
    performance, but your system's MTU will only allow 7972.
    This will negatively impact your maximum achievable sample rate.

Begin streaming 1024000 samples, 1.500000 seconds in the future...
samps_per_buff = 1024
num_buff_ptrs = 1000
mdbp_idx = 1000

Done!

To save the samples for post processing, specify the following OML arguments

—oml-id hostname this identifies the source of the data being store. —oml-domain rx_samples file name for the OML database —oml-collect oml:3003 network storage located on oml:3003

Rerun the application with these and we'll see a few additional lines of output at the end indicating a connection to the OML database server.

Writing FFT blocks into rx_samples.sq3 @ oml:3003
May 13 21:36:18 INFO    OML Client V2.10.1rc [Protocol V4] Copyright 2007-2013, NICTA
INFO    OmlNetOutStream: attempting to connect to server at tcp://oml:3003
INFO    tcp:oml:3003: Waiting for buffered queue thread to drain...

Instrumenting rx_multi_receive application with OML

The source file for this application is in ~/RX_MULTI_RECEIVE/main.cpp. Without going into the details off c++ and the enitire contents of the source file, we'll make note of the following blocks of code:

  1. Lines xxx creates a handle to the USRP at the specified IP address. This handle is used thoughout the source to make reference to the radio.
  2. Lines xxx uses the handle to configure the radio paramters passed in from the command line.
  3. The read loop on lines xxx to xxx. This block reads out the complex floating samples into a buffer that is used for post processi

ng samples.

  1. Lines xxx to xxx are OML additions made to send the FFTed sample data to the OML server for storage.

In side this block, we create an object that performs 1024pt FFTs.

   std::vector<std::complex<float> > time_buff( samps_per_buff );
   std::vector<std::complex<float> > freq_buff( samps_per_buff );
   std::vector<float>                signal_mag_instant( samps_per_buff );

   fftwf_plan fft_p = fftwf_plan_dft_1d( samps_per_buff,
                                         (fftwf_complex*)&time_buff.front(),
                                         (fftwf_complex*)&freq_buff.front(),
                                         FFTW_FORWARD,
                                         FFTW_ESTIMATE);

We also contruct an object for writing data to an OML server. Initialized the OML object with the OML options described above.

      // OML object for sending data
      CWriteOml oml;
      oml.init(oml_id, oml_domain, oml_collect );

Create keyed-values that will be sent for storage. Here we specify a string label with an OML type. After all the keyed-value pairs have been defined, we start a connection with the OML service.

      std::vector< std::pair<std::string, OmlValueT> > _omlKeys;
     //                                 string label        OML type
     _omlKeys.push_back( std::make_pair("mboard_id",        OML_STRING_VALUE));
     _omlKeys.push_back( std::make_pair("mboard_serial",    OML_STRING_VALUE));
     _omlKeys.push_back( std::make_pair("mboard_name",      OML_STRING_VALUE));
     _omlKeys.push_back( std::make_pair("rx_id",            OML_STRING_VALUE));
     _omlKeys.push_back( std::make_pair("rx_subdev_name",   OML_STRING_VALUE));
     _omlKeys.push_back( std::make_pair("rx_subdev_spec",   OML_STRING_VALUE));
     _omlKeys.push_back( std::make_pair("rx_ant",           OML_STRING_VALUE));

     _omlKeys.push_back( std::make_pair("channel",          OML_UINT32_VALUE));
     _omlKeys.push_back( std::make_pair("total_samps",      OML_UINT32_VALUE));
     _omlKeys.push_back( std::make_pair("sample_size",      OML_UINT32_VALUE));

     _omlKeys.push_back( std::make_pair("rx_freq",          OML_DOUBLE_VALUE));
     _omlKeys.push_back( std::make_pair("rx_rate",          OML_DOUBLE_VALUE));
     _omlKeys.push_back( std::make_pair("rx_gain",          OML_DOUBLE_VALUE));
     _omlKeys.push_back( std::make_pair("SizeFFT",          OML_UINT32_VALUE));
     _omlKeys.push_back( std::make_pair("Bins",             OML_BLOB_VALUE));

     oml.start( _omlKeys );

After the OML start has been issued we can set the keyed-value pairs with updated values from sensors. In this section the FFT is performed on chunk of 1024 comoplex samples and the magnitude is computed. These get stored in the OML as binary data (oml_blob). Once all the keyed-valued pairs are updated with set_key(), they are sented over to the OML server by issuing the insert command. This is done repeatedly until the entire buffer has been processed.

       oml.set_key("rx_id",            (void*)usrp_info["rx_id"].c_str() );
       oml.set_key("rx_subdev_name",   (void*)usrp_info["rx_subdev_name"].c_str() );
       oml.set_key("rx_subdev_spec",   (void*)usrp_info["rx_subdev_spec"].c_str() );
       oml.set_key("rx_ant",           (void*)usrp_info["rx_ant"].c_str() );

       d64 = (double)(usrp->get_rx_freq() / 1e6);
       oml.set_key("rx_freq", (void*)&d64);

       unsigned int nfftBlocks = MultiDeviceBuffer.at(ch).size() / samps_per_buff;
       for (unsigned int j = 0; j < nfftBlocks; j++)
       {
         // copy samples into time_buff for FFT
         memcpy((void*)time_buff.data(),
                (void*)(MultiDeviceBuffer.at(ch).data() + j*samps_per_buff ),
                samps_per_buff * sizeof(std::complex<float>) );

         // Execute FFT. This performs fft on time_buff samples and store results in freq_buff.
         fftwf_execute(fft_p); // FWD FFT is NOT normalized so div by N.

         // compute magnitude
         for(unsigned int z = 0; z < signal_mag_instant.size(); z++)
           signal_mag_instant.at(z) = abs(freq_buff.at(z));

         // save the magnitude values as an OML blob
         oml.set_key_blob("Bins",(void*)&signal_mag_instant.front(),
                          (unsigned int)signal_mag_instant.size() * sizeof(float) );

         // Send OML measurement to OML server
         oml.insert();
       }

       //oml.stop();  // Don't need this since it is called in the destructor.

Once this block completes the connection to the OML server is taken down and no more data can be stored into the database.

View results from OML database

The database is store in /var/lib/oml2 of the console. Use the command line front-end tool (sqlite3) to query the database direct ly especially for binary data. For a detailed overview on sqlite3 CLI please refer ​http://www.sqlite.org/cli.html.

An application has been made to parse this database. This application is very specific to this tutorial. If the format of the data base table changes, the application may no longer be able to parse the database file. Display all the tables in the database.

console> ./db_parse --file /var/lib/oml2/rx_multi_samples.sq3 --showtables

name = _senders

name = _experiment_metadata

name = _mp__rx_multi_samples

Use following command to retrieve contents of table.
./db_parse --file /var/lib/oml2/rx_multi_samples.sq3 --exec "SELECT * FROM <table>"

To retrieve contents of the blob:
./db_parse --file /var/lib/oml2/rx_multi_samples.sq3 --blob2bin ch0_data.bin --ch 0 --table  _mp__rx_multi_samples --key Bins

We can recover the contents of the FFT data for each channel and save them into a binary file for viewing in octave.

console> ./db_parse --file /var/lib/oml2/rx_multi_samples.sq3 --blob2bin ch0_data.bin --ch 0 --table  _mp__rx_multi_samples --key
Bins

Executing query statement
select LENGTH(Bins),Bins from _mp__rx_multi_samples where channel=0

In the console we should have a binary file by the name ch0_data.bin. This can be loaded and viewed in ocatve.

octave> mag0 = fReadBinaryFile('ch0_data.bin','single');
octave> mag0 = reshape(mag0, 1024, length(mag0)/1024);
octave> image(mag0*1000)

Upload image of mag0…

Attachments (6)

Note: See TracWiki for help on using the wiki.