**This is an old revision of the document!**
Table of Contents
RIS Operation Tutorial
To Fill In
This Tutorial assumes that you have followed the basic CorteXlab operation tutorials (at least GNU Radio benchmark example, and Eyes and ears inside CorteXlab, but GNU Radio benchmark, interactive command execution and GNU Radio benchmark example with docker are recommended)
Here, we will go through an experiment using and operating the reflective intelligent surface (RIS) installed in the CorteXlab room, that should showcase all that is necessary to drive it for your own experiments.
We assume prior knowlegde of the concept of RIS and its uses. We focus on the technical operation of the one we have installed in the room. .
The RIS
The RIS currently installed in SLICES/CorteXlab is a prototype of a FR1 RIS by Greenerwave.
It is in the form of a flat square 40cm on a side and designed to operate on a wide 800MHz band centered around 3.7 GHz with a 120° field of view on both azimuth and elevation.
It contains 128 reflective elements (pixels), with one bit control (on/off), arranged in pairs in a 8×8 square. One element of the pair handling vertical polarisation, the other horizontal.
You can find more technical information about it and request their specsheet on their website.
The room setup
Please check with the CorteXlab Team for changes to that setup (and to check if it has changed)
The RIS is currently hanging off the ceiling railings, inbetween nodes 31 and 33, and pointing to the “east” of the room's map (see the crude pdf map).
It is connected to node 31 via USB for power and control, so we will have to use that node to drive it.
The RIS installation is designed to be easy to relocate so feel free to contact the CorteXlab team if you want to run experiments with the RIS in a different location (we may need to plug it in a different node).
To show a more interesting, non line-of-sight scenario, some wall panels with RF absorbing foam have been setup between nodes 35 and 39 (again, see the map). As for the RIS itself, they are designed to be relocated, so don't hesitate to tell us if you need them elsewhere.
How it works
The RIS itself can not be directly booked, and a low level driver is not made available interact with it. It is connected to a node via USB, so booking that node is necessary to have it power on and controlled.
We provide a ready to use docker image that need to run on the node to serve as driver:
registry.gitlab.inria.fr/cortexlab/measurements/ris-api/ris:1.1
When instantiated, it automatically starts a small web server on port 5000 serving a REST API for remote control and feedback from any of the other nodes, or even (through a proxy), your own computer.
The available controls are:
- Turn on/off with
/turn_onand/turn_off(The off state corresponds to setting all ones on the pixels) - Manually setting the pixel states with
/set_pixels, with a list 128 of 0 and/or 1 - Configuration algorithms:
/ref_optimizationthat tries many configurations and iterates on them based on feedback from a receiver/narrow_beamformingthat generates a configuration for a narrow_beam based on geometric parameters
- Managing configuration files with
/load_file_conf,/read_file_conf, and/write_file_confto replay, read, and write previously optimized pixel configurations stored on the control node
For more details on this API, the code and a detailed readme is hosted in this repository.
The scenario
In this example scenario to demonstrate basic operation, we will do the following based on the room setup:
- Setup node 38 to continuously transmit a known sequence over a 5MHz bandwidth
- Setup the RIS node with the provided docker image to allow for RIs control
- Setup node 18, on the other side of the wall, to receive the signal and display received power and channel frequency response information, as well as buttons to send command to the RIS node.
Running it
Get the files
The files we are going to use live inside the same repository as the REST API. Let's go to the tutorial folder to get those:
you@srvairlock:~$ mkdir -r Tutorials/Tuto_RIS you@srvairlock:~$ cd Tutorials/Tuto_RIS you@srvairlock:~/Tutorials/Tuto_RIS git clone https://gitlab.inria.fr/cortexlab/measurements/ris-api.git you@srvairlock:~/Tutorials/Tuto_RIS cd ris-api
We will be using the contents of the examples/power_feedback folder
you@srvairlock:~/Tutorials/Tuto_RIS/ris-api cd examples/power_feedback you@srvairlock:~/Tutorials/Tuto_RIS/ris-api/examples/power_feedback ls power_reader_epy_block_0.py power_reader.grc power_reader.py power_tx.grc power_tx.py scenario
Let's go over each one of the files in this folder:
power_tx.grc: the GNU Radio Companion flowgraph description for the transmitterpower_reader.grc: the GNU Radio Companion flowgraph description for the receiverpower_tx.py: the GNU Radio python script for the transmitterpower_reader.py: the GNU Radio python script for the receiverpower_reader_epy_block_0.py: Helper code for the receiver (code for communication with the RIS)scenario: The folder containing the scenario description file that we will edit
Edit the scenario file to point the commands to the user's folder
Let's open the existing scenario file using nano (or some installed text editor that you may prefer):
you@srvairlock:~/Tutorials/Tuto_RIS/ris-api/examples/power_feedback nano scenario/scenario.yaml
# Scenario textual description
description: Power monitoring tutorial for use with RIS
# Experiment maximum duration
duration: 1800
nodes:
node18:
container:
- image: ghcr.io/cortexlab/cxlb-gnuradio-3.10:1.5
exec:
- bash -lc "pip install flask && apt install curl"
command: bash -lc "python3 /cortexlab/homes/{YOUR USERNAME}/Tutorials/Tuto_RIS/ris-api/examples/power_feedback/power_reader.py -r 5e6"
node38:
container:
- image: ghcr.io/cortexlab/cxlb-gnuradio-3.10:1.5
command: bash -lc "python3 /cortexlab/homes/{YOUR USERNAME}/Tutorials/Tuto_RIS/ris-api/examples/power_feedback/power_tx.py -r 5e6"
node31:
container:
- image: registry.gitlab.inria.fr/cortexlab/measurements/ris-api/ris:1.1
passive: true
Make sure you edit the command paths for TX and RX to point to your own folder (replace with your username)
As you can see here, the scenario file is very similar to what was used in previous tutorials. For node 31, driving the RIS itself, the only thing required is to specify the ris-api docker image. No need for a command, server startup is automatic.
The only exotic element here would be for node 18:
exec:
- bash -lc "pip install flask && apt install curl"
This option allows for execution of extra commands in parallel of the main one. We use it to install flask and curl, two packages we want to use to communicate with the RIS, on the fly, without having to generate a dedicated docker image.
(Optional) Explore the GRC files
Show what's inside the TX and RX files. Quick for TX For RX, point to the feedback snippet and the http_helper block, showing how they work. Useful because these are the elements users would need to reuse for their own experiments
Run the task
We will use the usual commands to run the task:
you@srvairlock:~/Tutorials/Tuto_RIS/ris-api/examples/power_feedback minus task create scenario Creating the task file... Task file scenario.task created successfully. you@srvairlock:~/Tutorials/Tuto_RIS/ris-api/examples/power_feedback minus task submit scenario.task 25062
Connect browser to the display
In the previous tutorial about remote monitoring, Eyes and ears inside CorteXlab, we used a direct ssh connection to the node with port forwarding to be able to point our browser to the bokehgui server running inside of the platform.
Here, we'll show an other option, that requires a bit more setup, but allows for more flexibility once it's done: SOCKS proxy.
If you don't want to use that option, or if it doesn't work for you, you can always fall back to the port forwarding method. You would simply need to start an ssh deamon on node 18 to be able to connect to it. For that, you need to add an extra exec line on the node, like so:
...
nodes:
node18:
container:
- image: ghcr.io/cortexlab/cxlb-gnuradio-3.10:1.5
exec:
- /usr/sbin/sshd -p 2222 -D
- bash -lc "pip install flask && apt install curl"
command: bash -lc "python3 /cortexlab/homes/{YOUR USERNAME}/Tutorials/Tuto_RIS/ris-api/examples/power_feedback/power_reader.py -r 5e6"
...
Back to the SOCKS proxy method. We first need to open that SSH proxy with an extra option to the SSH command so, in a new terminal:
you@yourpc:~$ ssh username@gw.cortexlab.fr -D 4321
Proxy is now open on port 4321. What's left is to configure your browser to use it. Many websites explain how to do it for many browsers, better than we could do here, for instance, this one The port to setup is 4321, same as we specified with the ssh -D option. And the proxy is running locally, so the server address is 127.0.0.1
Extensions are also available to make the proxy configuration and switching easier, such as FoxyProxy
Once the configuration is done, provided the task is still running, you can connect to it by pointing your browser to the node's URL:
http://mnode18:5006/
It should show an interface similar to this with a bunch of controls on the left, a frequency response plot, and a Received power plot:
First turn on the RIS by clicking on the corresponding button. It's normal that the plots don't change at this point.
Then click on the Optimize RIS button.
You should see the plots moving up and down rapidly over a few seconds, eventually settling a few dB higher than where it started. You did your first RIS configuration, well done!
To see the difference, with the default state, either turn off the RIS (don't forget to turn it back on after that), or click on the Reset RIS button, it manually sets all the pixels to their default state without having to reboot the board.
With the Load Config button, you can reapply the previously optimised configuration without having to redo the optimisation process.
You can play with the Optim loops and Initial configs parameters to tell the optimisation algorithm to try more (or less) configurations, changing the time required for the process, but also affecting the end result.
On the right of each of the two plots, the toolbar contains a button to reset the max value line. It's the third one from the bottom, with a tooltip reading appropriately Reset Max.
Feel free to play with all the parameters such as the receive gain, TX/RX frequency or, to see more dramatic results, reverse the optimisation, telling the RIS to reduce the received power instead of increasing it.

