ROS2 on microcontrollers with RIOT

Hello !

I am studying the possibility of porting ros2 to RIOT.

To begin wiith, I have seen a (very old) fork of RIOT on the ros2 organisation.
Is there someone who works (or worked) on that ?

Cheers !

1 Like

Hi @astralien3000,

The fork you referred to is available here.

RIOT was indeed considered as one of the candidates to build up a prototype of a ROS 2 microcontroller-oriented framework however the prototype was finally built on top of NuttX instead. The resulting prototype is available here.

The amount of time/effort put into that prototype was relevant so I’d encourage you to review the NuttX one before jumping straight to a new RTOS.

1 Like

Hi @vmayoral,

Thanks for your answer.
After reviewing the NuttX-based repository, I have found that you were implementing a very light rcl interface compared to the “normal” one. The interfaces are even not compatible.
Is that a choice ? Or is it an early proof of concept interface that will tend to look like the “normal” interface ? Or am I completely wrong and this is not the code you are using ?

hi @astralien3000,

that was the case. At the time of writing, ROS 2 rcl was still being written and only a minimal set of interfaces were implemented.

The code is not actively maintained anymore but it should provide a good starting point for anyone with relevant interest in the topic of ROS 2 running in microcontrollers.

Hello !

I’m here to give you some news about my project of porting ROS2 to RIOT.
I have a working proof-of-concept !

While porting the ROS2 code to RIOT, I implemented 2 new RMW which are not based on DDS :

  • using NDN
  • using MQTT-SN

To make it work on microcontrollers (they don’t support the C++ standard used in rclcpp), I also implemented a part of rclc.

As a result, I was able to make it work on a real robot.

The hardware running the ROS2 nodes are two ARM Cortex-M0+ boards, with wireless communication. The microcontroller, ATSAMR21G18A, is quite small, with only 32Kb RAM and 256Kb Flash, compared to the 192Kb RAM and 1Mb Flash STM32F407IG used for the previous NuttX-based example.

4 Likes

That’s really cool!

Did you have any trouble with code size? I recently looked the code sizes on a desktop machine and they were not huge, but still big for the micro you’re using. There were some low hanging things we could optionally turn off to help with that. E.g. since all of our error strings are set through a macro we could compile them out. They actually account for a non-trivial portion of the code size at this point.

Did you have any trouble with rcl? I guess that there are some features creeping in that won’t work on a micro (use of env variables and/or filesystem checks). This is mostly due to the security features which can be turned off at compile time, but I’m curious what else you might have needed to change to make it work.

Also, I don’t see mention of rcutils anywhere, so I’m guess you’re using an older release of ROS 2 rather than beta 2 or master?

1 Like

Thanks ! ^^

Not so much. But of course this proof of concept is far from having all the features. Here are the current sizes :

  • For the NDN version :
    RAM : ~12Kb
    Flash : ~60Kb

  • For the MQTT-SN version :
    RAM : ~18Kb
    Flash : ~62Kb

For the whole OS, ROS2, and user application.
The RAM is not counting the heap used, but it takes in account the stack of the different threads.

I’m based on beta1, mainly because I could not use the ROS2 build system (microcontrollers + RIOT having it’s own build system, hard time), and I needed some generated files (from rosidl) that were not compatible with the master branch at this time (February). It was more secure to base my work on a stable branch.

Not so much. I just had to change the time.c implementation to use RIOT, and some warnings made my build system unhappy (mostly old-style function definition), but the rest was ok.

The most hard part I (still) have is with the rosidl/typesupport things, which prevent me to support any type but Strings.

1 Like

Very interesting, thanks for sharing!

For the RAM and flash does that include a comms stack? (you mention wireless communications - is that serial?) We are looking at using Ethernet so we would need a TCP/IP stack. I noticed in the RIOT documentation it seems to be at least marginally supported, is there anything missing?

Which did you prefer using between the NDN and MQTT-SN protocols, ie: which would you use in the future?

Merci

Yes, that include the comms stacks.
The wireless communication is IEEE 802.15.4. In the user application point of view, RIOT provides a net interface similar to the interfaces you can find with Linux. RIOT have a fully working UDP/IPv6 stack (I use it in my project). I think TCP is also working, but I never used it, same for IPv4. About Ethernet, it depends on how you would use it.

Before choosing between NDN and MQTT, let me quickly list the pros and cons

  • NDN
    :heavy_check_mark: replace the full TCP/UDP/IP stack
    :heavy_check_mark: is topic-oriented by design
    :white_check_mark: is decentralized by design
    :white_check_mark: can be used on top of TCP/UDP/IP as well as directly on the MAC Layer (ethernet, 802.15.4, …)
    :x: is still an active research topic and not standardized
    :x: currently don’t provide the ROS2 communication patterns (Pub/Sub, Services)
    (but I implemented a beginning of Pub/Sub)

  • MQTT-SN
    :heavy_check_mark: is based on UDP/IP
    :heavy_check_mark: is topic-oriented by design
    :white_check_mark: provide a Pub/Sub communication that fits well ROS.
    :white_check_mark: is quite standardized
    :x: is centralized by design (needs a broker)
    :x: don’t provide the ROS’ Services communication pattern

For me, as a PhD student, NDN seems more interesting than MQTT, but harder to integrate in ROS2. But the thing is that I need to compare any of my implementation to something. Since I was not able to use DDS on my hardware, I just tried these 2 solutions, which may not be the only two I will try.

3 Likes

Hello !

Here are some news about the project :

I finally was able to integrate my modules with the “normal” ROS2 build system (now you can use “ament build”). The thing is that I needed to modify the build steps of some standards packages (rcl, std_msgs, builtin_interfaces, rosidl_generator_c) to make it work with RIOT’s build system. To make it short, instead of compiling the sources with ament/cmake, I just generate Makefiles used by RIOT to compile the final application. Any feedback on how I managed that would be appreciated ^^.

I also began to experiment with rosidl to generate some serialization code, and currently the project can handle messages composed of strings, (u)int32 and (u)int64 fields. Serialization is made with cbor.

Cheers !

4 Likes

Hello !

I haven’t posted news from the project for a long time now, but here is the summary of my last developments :

  • I have updated the ros2 packages I use from beta2 to arment !
  • I have improved the build system integration between Ament and RIOT, now the build process looks much more like the official crosscompilation for arm.
  • I don’t need to modify the official packages’ CMakeLists.txt anymore, so that future update will be easier.

In the other hand, I also removed some features that I have no time to maintain anymore (be understanding, I’m working alone on this project :sweat:) :

  • removed rmw_mqtt implementation
  • removed some examples

Also, my implementation of rclc (ROS Client Library for C) has recently been merged with the official rclc repository (many thanks to the reviewers). I could not reach the point where it would be included in the official ROS2 stack, but at least it is usable with the normal ROS2 stack and the RIOT-ROS2 stack ! You can check these examples for trying with the normal stack.

My roadmap for this year is :

  • to complete rclc so that it may be included in a future ROS2 version
  • to have a full implementation of topics, services and discovery with rmw_ndn.
  • to update to newer versions of RIOT
  • to write some example tutorials for using on a microcontroller (the main benefit of my project :smile:)
  • to build a complete autonomous robot with this project (and take part to the Eurobot competition)

Of course any contribution is welcome, even just saying that it does not work on your computer !

Cheers !

3 Likes

Hi @astralien3000

It’s great to have some news about that project!

I am following your work since the beginning because I am very interested in using ROS2 on microcontrollers.

I remember that you used to use the 802.15.4 wireless connectivity of the Atmel SAMR21 to communicate between 2 microcontrollers. Do you have a wired communication now or a least one with a computer? I have quickly looked at the repo and did not find the answer.

Because, as a Eurobot competitor, I am not used of the wireless communication between the components inside a robot.

1 Like

Hey @astralien3000! Pretty cool to hear about your updates. Very well done and thanks for sharing it and keeping all of us posted.

We are also looking at ROS 2 in microcontrollers as part of a European project and after a look at the structure of the code, I think we can inspire quite a bit from you. Our objective, is to end up with a “framework for microcontrollers” that should supports different alternatives for underlying RTOS, communication middlewares, etc. In particular, for the RTOS, we are looking at using NuttX (link to our fork). Given the maturity of your work (which to me seems much more advanced than ours) I think it’s worth to try re-using your structure and eventually converge if possible.

Provided that this sounds good to you, I’m up for spending some time researching your code and try putting together a prototype of your system with NuttX as the underlying RTOS. Would you be willing to support us if we do so? Ideally we could end up submitting a PR to your code with NuttX support (which from a hardware perspective, opens up your system to many more possibilities). How does this sound?

Cheers,

2 Likes

@rreignier, I currently haven’t managed to do it on wired communication yet. But, like you, I will need some wired communication for Eurobot. I plan to try at least USB/UART and CAN during the (few) remaining months before the competition. Normally, UART (over USB) between a board and a computer should be already possible thanks to RIOT’s module “ethos”, and it would be a great first tutorial if I manage to make it work, actually ! ^^ Even better than board to board communication.

@vmayoral, it sounds interesting, indeed. With my development of the 2 last months, I feel it’s possible to use different underlying OS quite easily now, I was even thinking about porting ROS2 to the Arduino framework (when I would have the time). I would try to help you ! I’m looking forward to have more information on your project.

1 Like

Fantastic! I’ll allocate time for it and have a look then in the following weeks.

I’m also eager to share more. I hope this will happen soon. Certainly, knowing attitudes like yours, I’ll advocate to try and establish paths for contributions as soon as possible.

Hello @rreignier,
After your question about board to computer communication, I made a proof of concept.
Now if you read the README, you should find a way to make a (RIOT) native ros2 node communicate with a node that is embedded on a microcontroller.
If you want to try this example on your hardware, I would be happy to help you if there is any problem.

Just a little warning : the microcontroller version seems to crash because of a bug I introduced recently. I need to work on that, so if the app complains about heap allocation problem or goes crazy (printing junk on stdout), it’s a known bug. Just don’t control your motors with that for the moment :wink: !

2 Likes

Hi @astralien3000

That’s very interesting! I will try it as soon as I find some time.

Thanks!

@astralien3000, please find at https://github.com/microROS/micro-ROS a few bits about the micro-ROS European project I mentioned. The following architecture should help describing our goal:

+-------------------------------------------------------------+
|               embedded application layer                    |
+-------------------------------------------------------------+
|             micro-ROS client library (urcl)                 |
                e.g.: tf, lifecycle, executors, etc.          |
+-------------------------------------------------------------+
|             micro-ROS middleware interface (urmw)           |
+-------------------+---------------------+-------------------+
|    middleware 1   |     middleware 2    |   middleware 3    |
| (e.g. micro-RTPS) |     (e.g. mqtt)     |                   |
+-------------------+---------------------+-------------------+
|      Real-Time Operating System (RTOS) abstractions         |
+------------------+------------------+-----------------------+
|         RTOS 1   |       RTOS 2     |        RTOS 3         |
|     (e.g. NuttX) |    (e.g. RIOT)   |    (e.g. Zephyr)      |
+------------------+------------------+-----------------------+
|                         hardware                            |
+-------------------------------------------------------------+

I will start looking at how to integrate (if possible) your work in ours (I’m happy interacting publicly here but let me know if you’d prefer a more private channel).

Regards,

3 Likes

Nice !

Yes, I think it would be better to use an other channel for some things we would discuss. I have sent you an email.

I have some comments on your diagram :

  • Does urcl refers to a language-specific client lib ? or to rcl, adapted to microcontollers ?
  • In the first case, I would say that it would be nice to use and complete rclc
  • In the second case, I would say that using rcl is better, even if the use of malloc is not the best choice for microcontollers, it is quite well designed, and the most important is that rcl would be the glue between normal ROS2 and ROS2 for microcontrollers.
  • Why defining a urmw interface ? What would be different from rmw ?
  • The problem with RTOS abstraction is that, beside well known standards (POSIX, socket, libc, …), there is no library that manage an application layer protocol (MQTT, HTTP, CoAP, etc…) that is ported to several RTOS : each RTOS has it’s specific solution/interface.
1 Like

Hello !

I’m here to bring some news of the project :

  • The version of RIOT used have been updated, enabling the support of new boards and features.
  • I have implemented rmw_ndn for the “real” ROS2 stack, so that it can be chosen in place of the default rmw_fastrtps. Here is the repository.
  • This new implementation is more advanced than the one based on ndn-riot. For instance, it supports pub/sub with multiple publishers (multiple subscribers was already supported) and discovery.
  • I have managed to make the two stacks (RIOT-ROS2 and ROS2 with rmw_ndn) communicate with eachother.

Also, with the contribution of @vmayoral :

  • A proof-of concept port of ROS2 for NuttX is developped.
  • A docker for compiling the project is provided.

Here is the updated roadmap :

  • rclc still need to be completed
  • the implementation of pub/sub and discovery need to be stabilized, and ported to microcontrollers
  • services implementation needs to be done
  • starting an Arduino port ? Did I say Arduino ?

Cheers !

4 Likes