User Tools

Site Tools


gnu_radio_benchmark_example

**This is an old revision of the document!**

GNU Radio benchmark example

This tutorial executes an OFDM transmission between two nodes in CorteXlab, transmitting dummy packets between them.

We base this tutorial off the example digital OFDM benchmark transmitter and receiver code present in GNU Radio. For more info on the OFDM benchmark, please refer to the GNU Radio documentation.

Logging into the SSH front-end

Assuming your account has been correctly created, you can start by logging into the “srvairlock” SSH front-end:

you@yourpc:~$ ssh -X -v [-i path/to/the/key] -p 2269 username@gw.cortexlab.fr 

If this doesn't work, either you still don't have an account (you can get by going here) or your SSH keys aren't present in your computer, in which case you need to copy them from the computer you used to generated them. More information on the connection process, please check here.

If everything goes well you should get the CorteXlab welcome screen and an srvairlock prompt.

Inspecting the example task

Checkout the examples repository on GitHub :

you@srvairlock:~$ git clone https://github.com/CorteXlab/examples.git
you@srvairlock:~$ cd examples

Let's get inside and see what's all about:

you@srvairlock:~/examples$ cd my_task
you@srvairlock:~/examples/my_task$ ls
benchmark_rx.py  receive_path.py  transmit_path.py
benchmark_tx.py  scenario.desc    uhd_interface.py

Let go over each one of these files:

  • benchmark_tx.py: the GNU Radio python script for the OFDM transmitter
  • benchmark_rx.py: the GNU Radio python script for the OFDM receiver
  • transmit_path.py, receive_path.py and uhd_interface.py: are helper codes for both benchmark python scripts
  • scenario.desc: a scenario description file, which assigns the roles of “transmitter” and “receiver” to a set of nodes

Now, lets inspect the scenario description file, to understand what will happen during this experiment:

you@srvairlock:~/examples/my_task$ less scenario.desc

Which will give you this:

# Example scenario description file
#
#   All lines starting with "#" and empy lines are ignored


# Scenario textual description
#   simple string (a one liner)
desc base scenario for CorteXlab

# Experiment maximum duration
#   Time after which the experiment is forced to stop
#   integer (minutes)
durat 5

# Node list
#
#   format:
#
#   (machine):
#   entry (entry point script relative to the task root)
#   exit (exit point script relative to the task root. Use "none" for none)

node4:
   entry benchmark_rx.py
   params --antenna="TX/RX" --rx-gain=25 -v -W 2M -f 2.49G
   passive true

node6:
   entry benchmark_tx.py
   params --antenna="TX/RX" --tx-amplitude=0.2 -v -W 2M -f 2.49G

The file is self-explanatory, but for now lets ignore all the other lines, except the indented ones following node4: and node6:. You'll have the opportunity to understand them better later on.

Lets go over each one now:

  • node4:: This opens the node4 declaration of options
  • entry benchmark_rx.py: states that the benchmark_rx.py is the entry point of the experiment at node4. In other words, this will be the script executed at node4.
  • params –antenna=“TX/RX” –rx-gain=25 -v -W 2M -f 2.49G: these are the set of parameters that will be used for the benchmark_rx.py script at node4. This is particularly uselfull when you want to have the same code running differently on different nodes. The parameters are not dependent on CorteXlab but rather on the code give by the users. In this particular case they're almost self-explanatory, but lets go over them anyway:
    • –antenna=“TX/RX”: this indicates which antenna connector to use on the USRP radio platform connected to the node
    • –rx-gain=25: this sets the receive gain of the USRP radio platform
    • -v: this puts the script in verbose mode, printing debug information
    • -W 2M: this sets the bandwidth of the signal to 2 MHz
    • -f 2.49G: this sets the carrier frequency of the signal to 2.49 GHz
  • passive true: the node 4 will be passive, meaning it will stop when all active nodes are finished

Same reasoning follows for the section on node6. So this is the scenario at hand:

  • Node4 behaves as the OFDM receiver
  • Node6 behaves as the OFDM transmitter

For more info on where these nodes are located inside the platform, please check the node position map at the home of this wiki.

Creating the task file

Before submitting the task to the nodes, we need first to put the task into a format that can be readily understood by Minus. Minus is the experiment controller code, responsible for doing the dirty stuff for you:

  • Firing up the right nodes to be used
  • Copying the code onto the nodes
  • Starting everything at the same instant
  • Waiting until everything finishes, and stop stubborn code from running forever
  • Copying results, error and output messages to srvairlock, so that you can access it
  • Turning off everything and cleaning up

Let's prepare the task, but first we need to go back to the folder containing the task:

you@srvairlock:~/examples/my_task$ cd ..
you@srvairlock:~/examples$

And now, instruct Minus to create a task file:

you@srvairlock:~/examples$ minus task create my_task
you@srvairlock:~/examples$ ls
my_task  my_task.task

And now we have a new file called mytask.task which is ready to be submitted. Warning, do not leave a slash after the directory task name (i.e. mytask ) of the command will fail.

Submitting the task

Now we need to give the task to Minus, so that it can operate its magic.

First we need to reserve the CorteXlab room:

you@srvairlock:~/examples$ oarsub -l nodes=BEST,walltime=0:30:00 -I

This will run a 30 minutes job and open a subshell in which you can run minus tasks. This subshell will be killed after 30 minutes, and if you leave the shell earlier, it will terminate the corresponding oar job. More documentation on oar can be found here. You can also monitor the current jobs in the gantt web interface.

We then submit the minus task:

you@srvairlock:~/examples$ minus task submit my_task.task
Task with id 15 enqueued user <login>.

You'll see that Minus recognizes you as the submitter of the task and gives you a task number (15 in this example, it will be certainly different for you). You'll want to write down the number of the task as it will be important for checking the tasks status and aborting the task, if necessary.

Bear in mind that you task has been put on a queue and will await running tasks and other scheduled tasks to start, so it may take a while before it runs.

Minus can also help you check what is the status of the queue:

you@srvairlock:~/examples$ minus testbed status
Testbed status:
ID count so far: 15
Number of awaiting jobs: 0
ID of the running job: 15 (None means server is idle)

Three pieces of information are given back:

  • ID count so far: 15: This is the number of the last task created
  • Number of awaiting jobs: 0: This is the number of tasks currently awaiting in the queue
  • ID of the running job: 15: This indicated the number of the task currently being treated

Collecting and analysing the output

Generally the OFDM example task will take a few minutes to run. Once its finished, Minus will take care of copying the results and output messages back to your home folder in srvairlock, such that you can analyse it.

All results are stored by task number in the results folder, inside your home folder.

Lets go look for them:

you@srvairlock:~/examples$ cd ../results
you@srvairlock:~/results$ ls
task_15
you@srvairlock:~/results$ cd task_15
you@srvairlock:~/results/task_15$ ls
node4.tgz  node6.tgz
you@srvairlock:~/results/task_15$

So we see that we have a folder for each task and inside each folder one compressed file per participant node. Let's extract one of those files and see what's inside:

you@srvairlock:~/results/task_15$ tar -zxf node4.tgz
you@srvairlock:~/results/task_15$ ls 
node4  node4.tgz  node6.tgz
you@srvairlock:~/results/task_15$ cd node4
you@srvairlock:~/results/task_15/node4$ ls
benchmark_rx.py  receive_path.pyc  stdout.txt        uhd_interface.pyc
benchmark_tx.py  scenario.desc     transmit_path.py
receive_path.py  stderr.txt        uhd_interface.py

We see that all of the files we used to create the task are inside, but we have some new files. The *.pyc files are the python compiled files and we can safely ignore them. The other two are:

  • stdout.txt: all output messages from your GNU Radio python script are written here. These include GNU Radio messages as well as all “print”s you include in your code. Seeing the contents of this file is useful to assert its correct operation.
  • stderr.txt: all error messages are printed here. If you see strange things on the stdout.txt or nothing at all, it might be interesting to take a look at the stderr.txt to debug your code.

Lets take a look inside both, starting with the stdout.txt:

you@srvairlock:~/results/task_15/node4$ less stdout.txt

You should get a long file that looks more or less like this:

linux; GNU C++ version 4.7.2; Boost_104900; UHD_003.007.001-84-gd99ce4ef

-- Opening a USRP2/N-Series device...
-- Current recv frame size: 1472 bytes
-- Current send frame size: 1472 bytes
-- Detecting internal GPSDO.... Found an internal GPSDO
-- found
-- Setting references to the internal GPSDO
-- Initializing time to the internal GPSDO

UHD Receiver:
UHD Args:     
Freq:         2.49GHz
LO Offset:    0Hz
Gain:         25.000000 dB
Sample Rate:  2Msps
Antenna:      TX/RX
Subdev Sec:   None
Clock Source: None
Using Volk machine: avx_64_mmx_orc

OFDM Demodulator:
Modulation Type: bpsk
FFT length:      512
Occupied Tones:  200
CP length:       128
Warning: failed to enable realtime scheduling
ok: False 	 pktno: 169 	 n_rcvd: 1 	 n_right: 0
ok: False 	 pktno: 170 	 n_rcvd: 2 	 n_right: 0
ok: False 	 pktno: 171 	 n_rcvd: 3 	 n_right: 0
ok: False 	 pktno: 173 	 n_rcvd: 4 	 n_right: 0
ok: False 	 pktno: 174 	 n_rcvd: 5 	 n_right: 0
ok: False 	 pktno: 175 	 n_rcvd: 6 	 n_right: 0
ok: False 	 pktno: 176 	 n_rcvd: 7 	 n_right: 0
ok: False 	 pktno: 177 	 n_rcvd: 8 	 n_right: 0
ok: False 	 pktno: 178 	 n_rcvd: 9 	 n_right: 0
ok: False 	 pktno: 179 	 n_rcvd: 10 	 n_right: 0
ok: False 	 pktno: 180 	 n_rcvd: 11 	 n_right: 0
ok: False 	 pktno: 181 	 n_rcvd: 12 	 n_right: 0
ok: False 	 pktno: 182 	 n_rcvd: 13 	 n_right: 0
ok: False 	 pktno: 185 	 n_rcvd: 14 	 n_right: 0
ok: False 	 pktno: 186 	 n_rcvd: 15 	 n_right: 0
ok: False 	 pktno: 191 	 n_rcvd: 16 	 n_right: 0
ok: False 	 pktno: 192 	 n_rcvd: 17 	 n_right: 0
ok: False 	 pktno: 197 	 n_rcvd: 18 	 n_right: 0
ok: False 	 pktno: 203 	 n_rcvd: 19 	 n_right: 0
...

Lets try to understand it:

  • The first 9 lines correspond to the UHD messages
  • The next 16 lines correspond to the GNU Radio messages and radio configuration parameters
  • There might be a warning message about realtime scheduling that can be safely ignored
  • The lines starting with ok: False pktno: 169 n_rcvd: 1 n_right: 0 are the receiver trying to decode the OFDM packets. Lets further inspect these lines:
    • ok: False: means the packet was incorrectly decoded, i.e., it failed to pass the checksum
    • pktno: 169: is the sequence number seen at the receiver
    • n_rcvd: 1: is the number of received packets
    • n_right: 0: is the number of correctly received packets

As it can be seen, there's a local oscillator (LO) mismatch between both nodes that complicate the decoding process.

You can also look into the stderr.txt:

you@srvairlock:~/results/task_15/node4$ less stderr.txt

What next?

Congratulations! You have finished your first tutorial on CorteXlab. Please, feel free to change the example task and try out different configurations, carrier frequencies, bands, and so on. You can always resubmit this task to test out different kinds of configurations.

One good example of what to do is to nudge the carrier frequency of approximately +/- 20 KHz and see if the decoding process works better.

To learn mode advanced concepts around creating and managing tasks on CorteXlab, please continue the tutorials.

gnu_radio_benchmark_example.1481537568.txt.gz · Last modified: 2016/12/12 11:12 by onicolas