Building a ROS2 Node in Rust!
This post shows how to build a Robot Operating System 2 node using Rust, a systems programming language built for safety, security, and performance.
Published Jan 10, 2024
In this post, I'll tell you about Rust - the programming language, not the video game! I'll tell you why I think it's useful in general, then specifically in robotics, and finally show you how to run a ROS2 node written entirely in Rust that will send messages to AWS IoT Core.
This post is also available in video form - check the video link below if you want to follow along!
The first thing to talk about is, why Rust in particular over other programming languages? Especially given that ROS2 has strong support for C++ and Python, we should think carefully about whether it's worth travelling off the beaten path.
There are much more in-depths articles and videos about the language itself, so I'll keep my description brief. Rust is a systems-level programming language, which is the same langauge as C and C++, but with a very strict compiler that blocks you from doing "unsafe" operations. That means the language is built for high performance, but with a greatly diminished risk of doing something unsafe as C and C++ allow.
Rust is also steadily growing in traction. It is the only language other than C to make its way into the Linux kernel - and the Linux kernel was originally written in C! The Windows kernel is also rewriting some modules in Rust - check here to see what they have to say:
The major tech companies are adopting Rust, including Google, Facebook, and Amazon. This recent 2023 keynote from Dr Wener Vogels, Vice President and CTO of Amazon.com, had some choice words to say about Rust. Take a look here to hear this expert in the industry:
That's a great question. Really, I've presented the best parts in this post so far. Some of the drawbacks include:
- Being a newer language means less community support and less components provided out of the box. For example, writing a desktop GUI in Rust is possible, but the libraries are still maturing.
- It's harder to learn than most languages. The stricter compiler means some normal programming patterns don't work, whcih means relearning some concepts and finding different ways to accomplish the same task.
- It's hard for a new language to gain traction! Rust has to prove it will stand the test of time.
Having said that, I believe learning the language is worth it for safety, security, and sustainability reasons. Safety and security comes from the strict compiler, and sustainability comes from being a low-level language that does the task faster and with fewer resources.
That's true for robotics as much as it is for general applications. Some robot software can afford to be slow, like high-level message passing and decision making, but a lot of it needs to be real-time and high-performance, like processing Lidar data. My example today is perfectly acceptable in Python because it's passing non-urgent messages, but it is a good use case to explore using Rust in.
With that, let's stop talking about Rust, and start looking at building that ROS2 node.
The node we're building replicates the Python-based node from this blog post. The same setup is required, meaning the setup of X.509 certificates, IoT policies, and so on will be used. If you want to follow along, make sure to run through that setup to the point of running the code - at which point, we can switch over to the Rust-based node. If you prefer to follow instructions from a README, please follow this link - it is the repository containing the source code we'll be using!
The first part of our setup is making sure all of our tools are installed. This node can be built on any operating system, but instructions are given for Ubuntu, so you may need some extra research for other systems.
Execute the following to install Rust using Rustup:
There are further dependencies taken from the ROS2 Rust repository as follows:
Assuming your existing ROS2 workspace is at
~/ros2_ws
, the following commands can be used to check out the source code:ROS2 Rust then uses
vcs
to import the other repositories it needs:That concludes checking out the source code.
The workspace can now be built. It takes around 10m to build ROS2 Rust, which should only need to be done once. Following that, changes to the code from this repository can be built very quickly. To build the workspace, execute:
The build output should look something like this:
Once the initial build has completed, the following command can be used for subsequent builds:
Now, any changes that are made to this repository can be built and tested with
cargo
commands, such as:The cargo build log will look something like:
The ROS2 Rust workspace takes a considerable amount of time to build, and often gets built as part of the main workspace when it's not required, slowing down development. A different way of structuring workspaces is to separate the ROS2 Rust library from your application, as follows:
This method means that the ROS2 Rust workspace only needs to be updated with new releases for ROS2 Rust, and otherwise can be left. Furthermore, you can source the setup script easily by adding a line to your
~/.bashrc
:The downside of this method is that you can only source further workspaces using the
local_setup.bash
script, or it will overwrite the variables needed to access the ROS2 Rust libraries.To run the example, you will need the
IOT_CONFIG_FILE
variable set from the Python repository.Open two terminals. In each terminal, source the workspace, thenr un one of the two nodes as follows:
Using a split terminal in VSCode, this looks like the following:
You should now be able to see messages appearing in the MQTT test client in AWS IoT Core. This will look like the following:
We've demonstrated that it's possible to build nodes in Rust just as with C++ and Python - although there's an extra step of setting up ROS2 Rust so our node can link to it. We can now build other nodes in Rust if we're on a resource constrained system, such as a Raspberry Pi or other small dev kit, and we want the guarantees from the Rust compiler that the C++ compiler doesn't have while being more secure and sustainable than a Python-based version.
Check out the repo and give it a try for yourself!