We’ve recently celebrated the release of ROS 2 Humble Hawksbill with a post detailing how to get started developing for the new release in containers. In addition, we shared an overview of the new features included with this new release, particularly its enhanced security features.
This week we are tackling the logical next step in software development: packaging. Indeed, once we’re done developing our super cool ROS 2 Humble application, we still have to get it out into the hands of our users.
In this post, we are going to see how to package a ROS 2 Humble application as a snap with an ‘hello world’-like example.
A ROS 2 Humble snap you said?
Snaps are app packages for desktop, cloud and IoT that are easy to install, secure, cross‐platform and dependency‐free.
Snaps are the ideal deployment solution for ROS-based applications in that they are a self-contained, sandboxed, cross distribution packaging solution. Not to mention that they natively support ROS to ease your packaging journey. You can find further information about all the features they offer on the dedicated robotics page!
Setting up snapcraft
Firstly, let’s get the tool that allows us to create snaps: snapcraft.
sudo snap install --classic snapcraft
We will also install LXD which snapcraft uses as a backend for clean, confined and reproducible packaging,
sudo snap install lxd
sudo lxd init --minimal
Note that we have initialized LXD with a bunch of default parameters. Head to the LXD documentation if you prefer to specify some of those parameters yourself.
We are all set up to package our first example, so let’s do just that.
A talker-listener example
For this example, we’ll take it easy as we won’t even need to write any code. Instead, we are going to package one of the ROS 2 demo from the GitHub repository. I’ve picked a demo from the ‘demo_nodes_cpp‘ package, more specifically the ‘talker_listener.launch.py‘ demo.
As its name suggests, this demo launches a ‘talker’ which publishes a string message on a ROS 2 topic. together with a ‘listener’ which reads said message. Both print the message sent/received to the console to easily follow along. And of course both are launched at once from a single launch file.
While this example may seem a little too simple, it is an ideal first contact with snaps. We will see how easy it is to package ROS 2 applications with snaps.
The snapcraft.yaml file
Snapcraft relies on the ‘snapcraft.yaml’ configuration file to drive the packaging process. So, let us create one,
mkdir -p ~/ros2_ws/first_snap/
cd ~/ros2_ws/first_snap/
touch snapcraft.yaml
and then populate it as follows,
name: ros2-talker-listener
version: '0.1'
summary: ROS 2 Humble talker/listener example
description: |
This example launches a ROS 2 Humble talker and listener.
base: core22
confinement: strict
apps:
ros2-talker-listener:
command: opt/ros/humble/bin/ros2 launch demo_nodes_cpp talker_listener.launch.py
plugs: [network, network-bind]
extensions: [ros2-humble]
parts:
ros-demos:
plugin: colcon
source: https://github.com/ros2/demos.git
source-branch: humble
source-subdir: demo_nodes_cpp
stage-packages: [ros-humble-ros2launch]
Believe it or not, this is all we need to create our snap. But let us inspect this file more closely.
Breaking it all down
We can identify 3 distinct blocks in the aforementioned snapcraft.yaml
file.
At the top of the file, there is some boiler-plate that is common to most snaps. The snap name
, version
etc. Nothing unusual here. Then comes base: core22
which is a base snap that will provide a runtime environment to our application based on Ubuntu 22.04. The last entry in this block is confinement: strict
which states that our application is strictly confined. In other words, it cannot access any resource on the host machine.
The second block, apps
, specifies the application(s) that’s exposed from the snap. Here, a single application is listed whose command
is very familiar. Furthermore, our application also lists some interfaces
in the plugs
section. Note that Interfaces allow our confined application to access specific resources of the host machine. In this case, our snap will have access to network-related interfaces that allow for the ROS 2 topics to flow. Finally, the extensions: [ros2-humble]
will automatically fill up some other fields which are common to ROS 2 Humble snaps. In case you are curious about what an extension does, note that you can ‘expand’ it. Reveal all of its secrets by issuing the following command,
SNAPCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS=1 snapcraft expand-extensions
At last we are taking a look at the third block: parts
. The parts
tag defines the different pieces that make up our final application. They include a source
entry for the source code such as local files, a tarball, or as in this example, a GitHub repository at a specific branch. What’s more, a ‘part’ can include build-packages
, which are only required at build time unlike stage-packages
which are only needed at runtime. Most importantly, each part is handled by a plugin
. Here we are using the colcon
plugin, which makes use of the familiar build tool in ROS 2. Then again this plugin has its own options, which you can review with the command,
snapcraft help colcon
You can find further information about the global metadata, the parts and their own metadata, the colcon plugin, extensions, and more in the documentation.
Now that the snapcraft.yaml
file is defined, it is time to build the snap.
Building the ROS 2 Humble snap
To build the snap, issue the command snapcraft
in a terminal,
$ SNAPCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS=1 snapcraft
Starting Snapcraft
…
* metallic sound of software being forged *
…
Created snap package
Snap, reveal yourself,
$ ls
ros2-talker-listener_0.1_amd64.snap snapcraft.yaml
Surely, there it is!
How about we install it now? To do so, type,
$ sudo snap install --dangerous ros2-talker-listener_0.1_amd64.snap
ros2-talker-listener 0.1 installed
The use of the
--dangerous
flag since we are installing a snap from disk instead of using the store.
Ok, but does it bite work?
$ ros2-talker-listener
[INFO] [launch]: All log files can be found below /home/ubuntu/snap/ros2-talker-listener/x6/ros/log/2022-05-24-15-24-50-823207-localhost-24895
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [talker-1]: process started with pid [24944]
[INFO] [listener-2]: process started with pid [24946]
[talker-1] 2022-05-24 15:24:51.341 [RTPS_TRANSPORT_SHM Error] Failed to create segment ac1bbb6c86049e8a: Permission denied -> Function compute_per_allocation_extra_size
[listener-2] 2022-05-24 15:24:51.346 [RTPS_TRANSPORT_SHM Error] Failed to create segment e75bbd4ac39608ab: Permission denied -> Function compute_per_allocation_extra_size
[talker-1] 2022-05-24 15:24:51.348 [RTPS_MSG_OUT Error] Permission denied -> Function init
[listener-2] 2022-05-24 15:24:51.348 [RTPS_MSG_OUT Error] Permission denied -> Function init
[talker-1] [INFO] [1653420292.379305200] [talker]: Publishing: 'Hello World: 1'
[listener-2] [INFO] [1653420292.380423139] [listener]: I heard: [Hello World: 1]
[talker-1] [INFO] [1653420293.379072149] [talker]: Publishing: 'Hello World: 2'
[listener-2] [INFO] [1653420293.379286698] [listener]: I heard: [Hello World: 2]
[talker-1] [INFO] [1653420294.379120962] [talker]: Publishing: 'Hello World: 3'
[listener-2] [INFO] [1653420294.379682258] [listener]: I heard: [Hello World: 3]
...
Yes it does! How great.
What’s even greater is that you could install and run this snap on another computer even if it doesn’t have ROS 2 installed! Heck, you could install and run this snap on another Linux distribution from 4 years ago!
Note that the error message from FastDDS, the underlying DDS library, does not prevent the application from running. In other words we can safely ignore that for now. If you want to know more about how shared-memory plays along with snap, we covered the topic at length in a dedicated blog: “How to use ROS 2 shared memory in snaps”.
What’s next?
We have seen in this post how to create a snap for a ROS 2 Humble application. While this demo is fairly trivial, packaging a more complex ROS stack isn’t much more complicated. To demonstrate that, have a look at the series “How to set up TurtleBot3 in minutes with snaps” where I detail how to snap the entire Turtlebot3.
Furthermore, we’ve seen how you can effectively and easily package your ROS 2 application. How about distributing it now? Have a look at how to do so with the store here.
Finally, do feel free to ask any questions on the snapcraft forum, or on ROS answers. I’d love to hear any feedback you have.
Discover more from Ubuntu-Server.com
Subscribe to get the latest posts sent to your email.