Warning
You're reading the documentation for a version of ROS 2 that has reached its EOL (end-of-life), and is no longer officially supported.
If you want up-to-date information, please have a look at Jazzy.
Packaging your ROS 2 application as a snap [community-contributed]
What are snaps?
Snaps are containers that bundle an application and all its dependencies. They offer several features that address important concerns as one gets closer to shipping a robotic platform:
Container solution: Snaps bundle your application along with all the necessary dependencies (including ROS 2) and assets in one package. Your application is then easily installable on dozens of Linux distributions and across distro versions.
Strict confinement: Snaps are designed to be secure and isolated from the underlying system and other applications, with dedicated interfaces to access the host machine.
Managing updates: Snaps can update automatically and transactionally, making sure your robot is never broken and always up-to-date.
Release management: Snaps’ multiple release channels allow you to have role-based access controls and application versioning, making A/B testing easy and releasing fixes faster.
Creating a snap
This tutorial will demonstrate how to use snapcraft to package your ROS 2 application as a snap, and then how to use it.
First, let us install snapcraft.
sudo snap install --classic snapcraft
(Note that the snapcraft debian package from the apt repositories is largely deprecated. One should use the snap package.)
Snapcraft has built-in support for Colcon
.
For your example, you will use the demo_nodes_cpp
package from the ros2_demos.
Initialize a new snapcraft project here:
mkdir ~/demo_nodes_cpp_snap
cd ~/demo_nodes_cpp_snap
snapcraft init
This will create a file in a subdirectory snap/snapcraft.yaml
.
The snapcraft file
Open the freshly created snap/snapcraft.yaml
file and copy over the following:
name: ros2-talker-listener
version: '0.1'
summary: ROS 2 Talker/Listener example
description: |
This example launches a ROS 2 talker and listener.
confinement: devmode
base: core20
parts:
ros-demos:
plugin: colcon
source: https://github.com/ros2/demos.git
source-branch: foxy
colcon-packages: [demo_nodes_cpp]
build-packages: [make, gcc, g++]
stage-packages: [ros-foxy-ros2launch]
apps:
ros2-talker-listener:
command: opt/ros/foxy/bin/ros2 launch demo_nodes_cpp talker_listener.launch.py
extensions: [ros2-foxy]
Let’s break it down.
Metadata
name: ros2-talker-listener
version: '0.1'
summary: ROS 2 Talker/Listener example
description: |
This example launches a ROS 2 talker and listener.
This is the basic metadata that all snaps require. These fields are fairly self-explanatory but note that the name must be globally unique across all snaps.
Base
base: core20
The base keyword defines a special kind of snap that provides a run-time environment with a minimal set of libraries that are common to most applications. Core20 is the current standard base for snap building and is based on Ubuntu 20.04 LTS. It is, therefore, the base used for foxy.
Security model
confinement: devmode
To get started, you won’t confine this application.
Unconfined applications, specified with devmode
,
can only be released to the edge
channel of the snapcraft store.
For more information about snaps Security model, please refer to the online documentation.
Parts
parts:
ros-demos:
plugin: colcon
source: https://github.com/ros2/demos.git
source-branch: foxy
colcon-packages: [demo_nodes_cpp]
build-packages: [make, gcc, g++]
stage-packages: [ros-foxy-ros2launch]
Parts define how to build the app.
In this case, you have one: ros-demos
.
Parts can point to local directories, remote git repositories, or tarballs.
Here, you specify your source as a GitHub repository at a specific branch.
You also specifically tell Colcon
to build the demo_nodes_cpp
package.
Furthermore you tell snapcraft that packages such as make
are necessary at build time while the package ros-foxy-ros2launch
is necessary at run time.
For more information about the plugin and its options, please refer to the online documentation.
Apps
apps:
ros2-talker-listener:
command: opt/ros/foxy/bin/ros2 launch demo_nodes_cpp talker_listener.launch.py
extensions: [ros2-foxy]
Apps are the commands exposed to end users.
Each key under apps is the command name that should be made available on users’ systems.
The command
keyword specifies the command to be run as its name suggests.
Finally, the extensions ros2-foxy essentially sets up the ROS 2 apt package repository together with the necessary environment variables.
Building the snap
Now that you are all set up, let’s build the snap:
cd ~/demo_nodes_cpp_snap
snapcraft --enable-experimental-extensions
Giving:
*EXPERIMENTAL* extensions enabled.
Launching a VM.
Launched: snapcraft-ros2-talker-listener
[...]
This part is missing libraries that cannot be satisfied with any available stage-packages known to snapcraft:
libnddsc.so
libnddscore.so
libnddscpp.so
librosidl_typesupport_connext_c.so
librosidl_typesupport_connext_cpp.so
librticonnextmsgcpp.so
Snapped ros2-talker-listener_0.1_amd64.snap
Note
The warnings regarding the missing libraries are false positives. These libraries are build time dependencies only. This will be fixed in a future release of snapcraft
.
That will take a few minutes.
From the logs, and among other things, you can see snapcraft using rosdep to pull the dependencies for your example but also Colcon
building the application.
Testing the snap
This snap is completely standalone: it includes ROS 2 and your application, meaning that one doesn’t even need to install ROS 2 on the host system. Let’s test it out:
sudo snap install ros2-talker-listener_0.1_amd64.snap --devmode
Note that you use --devmode
here because the snap confinement is set as devmode
.
The moment of truth, will it run?
ros2-talker-listener
[talker-1] [INFO] [1646934735.523191674] [talker]: Publishing: 'Hello World: 1'
[listener-2] [INFO] [1646934735.524428480] [listener]: I heard: [Hello World: 1]
[talker-1] [INFO] [1646934736.523025881] [talker]: Publishing: 'Hello World: 2'
[listener-2] [INFO] [1646934736.523614075] [listener]: I heard: [Hello World: 2]
It does! You see the expected output!
You can find more information about snap on the snapcraft documentation and ROS 2 snap page.