When a robotics application is snapped, one might want to use it on multiple different robots.
Reusing the same snap means that we must be able to configure the snap to the specificity of a robot once installed on it.
We present in this guide the steps to distribute a snap with a configuration that is easily overwritable on the robot.
Our snap will be distributed with the default configuration, and will copy this default configuration into a location that is common across multiple revisions of the snap. This allows the user to manually modify the configuration file and keep it across updates.
For this how-to-guide, we use the example ubuntu-robotics/snap_configuration.
The repository consists of the snapcraft.yaml file from which the snap is built, as well as a launcher script.
The repository contains a standard snap package providing the key_teleop application from the teleop_tool ROS 2 package. The goal here is to be able to configure the application without having to update the snap. The
key_teleop node can be configured for its forward_rate, backward_rate and rotational_rate parameters. They are the parameters present in the configuration file that are overwritable.
This how-to-guide is assuming that we are familiar with robotics snaps. Please refer to our tutorials to learn more about robotics snaps.
An up and running Ubuntu (minimum 20.04) with snapcraft installed is also required.
At the beginning of this guide, we introduced the ubuntu-robotics/snap_configuration. We start from this snap and modify it so that it uses our shared configuration.
First, we clone the repository:
git clone https://github.com/ubuntu-robotics/snap_configuration.git
This repository already contains a snap package for the key_teleop package. There is a launcher script in
snap/local/teleop_launcher.bash and the
By default, our application doesn’t use any configuration file. It simply uses the default parameters hardcoded in the key_teleop.py. We then add our YAML file and import it in our snap!
First, we must create our default YAML file
snap/local/up-to-date-config.yaml with the following content:
forward_rate : 1.0
Then we modify our
snapcraft.yaml so it also imports the configuration file into our snap:
+ '*.yaml': etc/
Our default configuration file will now be available in the snap.
teleop_launcher.bash is currently not using any configuration file. Let’s modify the launcher so it uses the default configuration file that we added to our snap:
+echo "Using config file: $CONFIG_FILE_PATH."
-ros2 run key_teleop key_teleop
+ros2 run key_teleop key_teleop --ros-args --params-file $CONFIG_FILE_PATH
Our key_teleop ROS application is now using the default configuration file.
In the next section, we will see how to let the user customize this configuration file.
For the user to be able to customize the configuration file, it must be in a location that the snap can access and where a user can edit this configuration. We use
$SNAP_COMMON to store the editable YAML file.
The following diagram illustrates the configuration file workflow. Before starting the application, our snap checks if a configuration file is available in
$SNAP_COMMON. If not, we simply use the default configuration.
Let’s implement this workflow with our snap!
The first step is to implement the launching logic for the configuration file. We must check if the custom file exists and launch our application with the custom file if possible. To do so, we modify the
+if [[ -f $CUSTOM_CONFIG_FILE_PATH ]]; then
echo "Using config file: $CONFIG_FILE_PATH."
ros2 run key_teleop key_teleop --ros-args --params-file $CONFIG_FILE_PATH
Our launcher script is now picking the customized configuration when available.
To provide a good starting point to the user, we add a script, so the default configuration is copied and placed in the editable area at install.
Note that the
$SNAP_COMMON requires root privilege from the user for editing.
We create the script
snap/local/reset-overwritable-configuration.bash with the following content:
echo "Make sure to run this application with enough privilege."
cp $SNAP/etc/up-to-date-config.yaml $SNAP_COMMON/
echo "The configuration can now be edited in the file $SNAP_COMMON/up-to-date-config.yaml."
We make the script executable:
chmod +x snap/local/reset-overwritable-configuration.bash
Now that we have a script, we simply call it from the
install hook. This way, on the installation of the snap a default configuration is placed, so the user can directly edit the YAML.
We create the
We can then add the file
We make the hook executable:
chmod +x snap/hooks/install
The installation part of our snap is now done. Before testing, we add a last feature to our snap in case something goes wrong with our config.
By modifying the configuration, over time, one might want to retrieve the default behaviour.
To do so, we can add another application to our snap to reset the customizable configuration file. For this application, we reuse the
reset-overwritable-configuration.bash already present in the snap.
To add the application, we only modify the
plugs: [network, network-bind]
+ command: bin/reset-overwritable-configuration.bash
This application requires sudo if called by a non-privileged user.
We are now all set to test this snap!
We can now test the overwritable configuration. First, we build and install the snap:
sudo snap install my-ros2-teleop-test_*.snap --dangerous
The snap being installed, we can make sure that the customizable YAML was correctly placed:
We then see the default content of the file:
forward_rate : 1.0
We can edit (with root privileges) this file with a custom value (1.234 for forwar_rate).
Now we launch the application:
And by pressing the “up” arrow key, we can see that the custom configuration was used:
Additionally, we can reset to the default configuration with the following command:
With the application, snap properly using the custom YAML edited by the user. We can now update the configuration easily and independently of the snap.
We can now use the same snap on multiple robots and use a different configuration file for every device.
We can find the completed example of this how-to-guide on the branch howto/overwritable_configuration of the repository.