Running micro-ROS on Raspberry Pi Pico

In this post we will see how the Raspberry 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.

What is this all about?

Running ROS2 on microcontrollers.

The Raspberry Pi Pico

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. As usual 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, and allowing microcontrollers to ‘speak’ to a ROS2 graph (the usual talker/listener) using an optimized subset of the DDS protocol. A mouthful. 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 of terms, let us get started, step by step, with the official micro-ROS on Raspberry Pi Pico 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 an LXD container. You can refer to our previous post ‘ROS Development with LXC’ to help you get started setting up the container.

Installing dependencies

Let’s simply start by installing the 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/$USER/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 the project,

code .

Before running the CMake configuration and building 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 the 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,

cp build/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 of 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

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 improving 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 Raspberry Pi Pico is visible to ROS2 on the host machine. Yatta! #VictoryDance

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 Raspberry 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 Raspberry Pi Pico.

Of course this wouldn’t have been possible without the micro-ROS dev team and Cyberbotics engineer Darko Luki? (@lukicdarkoo) who 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 of ideas up my sleeves. Make sure to keep an eye on this blog to hear all about them.

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

This post first appeared at artivis.github.io

Similar Posts