Getting started with micro-ROS on the Pi Pico

On running ROS2 on microcontrollers

In this post we will see how the Pi Pico can natively speak to a ROS2 graph using micro-ROS. We will set up a project in VSCode, compile and upload it to the microcontroller. We thus assume that you are somewhat familiar with ROS2 development and VSCode.

The Raspberry Pi Pico, announced in late January 2021, is the newest release of the Raspberry Pi Foundation which received a ton of attention (a quick search on Google and/or Youtube will convince you). And that’s for a good reason. Compared to its well known predecessors, this new board differs in two major ways: it is an in-house designed open-hardware microcontroller! Yes, the chip itself is designed by the Pi’s engineers and it is fully open-hardware. And as usually with the Pi foundation, it is incredibly affordable at just 4$. The details concerning the board itself, the differences between microprocessor and microcontroller, the 101 getting started or what can the Pi Pico do; all of that is beyond the scope of this post. But I strongly encourage you having a look for yourself, whether you are familiar with microcontrollers or not. micro-ROS In the ROS (1) realm, microcontrollers have always been sort of second class citizens. They can’t interact directly with the ROS graph and developers have to rely on libraries such as rosserial. But ROS2 is a whole new world and things are changing. micro-ROS puts ROS 2 onto microcontrollers, making them first class participants of the ROS 2 environment. The micro-ROS project is an effort led by big industrial names such as Bosch, eProsima, Fiware Foundation, notably through the OFERA H2020 project, and a myriad of partners and collaborators including e.g. Amazon and Canonical. So what is it? It is essentially a thin wrapper (see its design document) on top of ‘DDS for eXtremely Resource Constrained Environments’ (DDS-XRCE), running on a real-time OS, allowing microcontrollers to ‘speak’ to a ROS2 graph (the usual talker/listener) using an optimized subset of the DDS protocol. It relies on a ‘bridged’ communication architecture with a ‘broker’ named the ‘micro-ros-agent’. The agent is in charge of the interfacing between the ROS2 graph and one or several micro-ROS devices. More details can be found on the micro-ROS website including how it compares/differs from rosserial (see here and here). Getting started Alright, so now that we have clarified a couple terms, let us get started, step by step, with micro-ROS on Pi Pico with the official example available on github. Note that for this tutorial I am running Ubuntu 20.04 with the VSCode snap. If you are not running Ubuntu 20.04 yet, you could consider using a LXD container. You can refer to my previous post ‘ROS Noetic development workflow in LXC’ to help you get started setting up the container. Installing dependencies Let’s start simple by installing the couple necessary dependencies, sudo apt install build-essential cmake gcc-arm-none-eabi libnewlib-arm-none-eabi doxygen git python3  Fetching the sources We will now create a workspace and fetch all the sources, mkdir -p ~/micro_ros_ws/src cd ~/micro_ros_ws/src git clone --recurse-submodules https://github.com/raspberrypi/pico-sdk.git git clone https://github.com/micro-ROS/micro_ros_raspberrypi_pico_sdk.git  The first repository is the Pi Pico SDK provided by the Pi foundation. The second contains a precompiled micro-ROS stack together with a hello-world-like example. Setting up VSCode Let us now open the example in VSCode and set it up. To follow along, you will need two VSCode extensions that are rather common for C++ development. These extensions are the C++ extension and CMake tools for VSCode. After installing them, we will create a configuration file for CMake tools and set a variable so that our project knows where to find the Pi Pico SDK. To do so, simply type, cd ~/micro_ros_ws/src/micro_ros_raspberrypi_pico_sdk mkdir .vscode touch .vscode/settings.json  Open the newly created file with your favorite editor, vi .vscode/settings.json  and add the following, { "cmake.configureEnvironment": { "PICO_SDK_PATH": "/home/artivis/micro_ros_ws/src/pico-sdk", }, }  This variable is an environment variable that is only passed to CMake at configuration time. See the CMake-Tools documentation for more info. Let us now open it, code .  Before running the CMake configuration and build it, we must select the appropriate ‘kit’ (maybe VSCode has already asked you to do so). Open the palette (ctrl+shift+p) and search for 'CMake: Scan for Kits' and then 'CMake: Select a Kit' and make sure to select the compiler we’ve installed above, that is 'GCC for arm-non-eabi'. We’re all set, let us build the example! Open the palette again and hit 'CMake: Build'. Running the example Wait a minute. What does it do? Right, let’s break down very briefly what the example does. It sets up a node called 'pico_node', then a publisher publishing a 'std_msgs/msg/int32.h' message on topic 'pico_publisher', a recurring timer and an executor to orchestrate everything. Every 0.1 second, the executor spins. But only every second, the timer will have the publisher publish a message and increase the message data by 1. Simple. So let’s try it out. Uploading to the Pi Pico If everything went fine during compilation, you should see a new 'build' folder in your project view. In this folder, you will find the file that we should now upload to the Pi Pico, it is named here 'pico_micro_ros_example.uf2'. To upload it, simply connect the board with a USB cable while pressing the tiny white button labelled 'BOOTSEL'. Doing so, the Pi Pico will mount similarly to a flash drive allowing us to very easily copy/paste the ‘.uf2’ file. Head to a terminal and type, cd build cp pico_micro_ros_example.uf2 /media/$USER/RPI-RP2


Once the file is copied, the board will automatically reboot and start executing the example.

Easy-peasy.

Installing the micro-ros-agent

We have seen in the introduction that micro-ROS has a bridged communication architecture. We thus have to build that bridge. Well, fortunately the development team has built it already and distributes it both as a Snap or a Docker image. Here we’ll make use of the former. If you are using Ubuntu 16.04 or later, snap is already pre-installed and ready to go. If you are running another OS, you can either install snap or make use of the Docker image.

To install the micro-ros-agent snap, type,

sudo snap install micro-ros-agent


After installing it, and because we are using a serial connection, we need to configure a couple things. First we need to enable the 'hotplug' feature,

sudo snap set core experimental.hotplug=true


and restart the snap demon so that it takes effect,

sudo systemctl restart snapd


After making sure the Pi Pico is plugged, execute,

$snap interface serial-port name: serial-port summary: allows accessing a specific serial port plugs: - micro-ros-agent slots: - snapd:pico (allows accessing a specific serial port)  What we see here is that the micro-ros-agent snap has a serial ‘plug’ while a ‘pico'slot' magically appeared. As per the semantic, we probably should connect them together. To do so run, snap connect micro-ros-agent:serial-port snapd:pico  We are now all set to finally run our example. Actually running the example With the Pi Pico plugged through USB, we will start the micro-ros-agent as follows, micro-ros-agent serial --dev /dev/ttyACM0 baudrate=115200  and wait a couple seconds for the Pi Pico’s LED to light up indicating that the main loop is running. In case it does not light up after a few long seconds (count up to 10 mississippi), you may want to unplug/replug the board in order to reboot it. The initialization procedure of the example lacks a few error checking. Hey, could fixing that be your first project? So now the LED should shine a bright green. That’s cool. Do you know what’s cooler? Running on your host machine, $ source /opt/ros/dashing/setup.bash
$ros2 topic echo /pico_publisher data: 41 --- data: 42 ---  Awesome! And hitting a $ ros2 node list
/pico_node


proves that the micro-ROS node running on the Pi Pico is visible to ROS2 on the host machine.

Yatta!

What’s next?

For a long time it wasn’t convenient to mix microcontrollers and ROS. But this is about to seriously change as we’ve just seen. No doubt that both micro-ROS and the Pi Pico will bolster great robotics applications (and more!).

In this tutorial we’ve reached a great starting point with a ROS2-based project ready to spin on the suppa-cool suppa-affordable Pi Pico.

Of course this wouldn’t have been possible without the micro-ROS dev team and Cyberbotics engineer Darko Lukić (@lukicdarkoo) who has put together the initial example we’ve just used. As often, there are super smart people out there making complicated stuff very accessible, shout out to them.

I’m personally going to keep playing with micro-ROS on Pi Pico, first because it is fun and second because I have a couple ideas up my sleeves. Be sure that if they become reality you’ll hear about them on this blog.

What about you? Do you have some cool projects already in mind?