Configure a snap: Make the snap configuration overwritable
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.
Requirements
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.
Distribute a default configuration
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 snap/snapcraft.yaml
.
Import the default configuration
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:
key_teleop:
ros__parameters:
forward_rate : 1.0
backward_rate: 0.5
rotation_rate: 1.0
Then we modify our snapcraft.yaml
so it also imports the configuration file into our snap:
local-files:
plugin: dump
source: snap/local/
organize:
'*.bash': bin/
+ '*.yaml': etc/
Our default configuration file will now be available in the snap.
Use the default configuration
The 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:
#!/usr/bin/bash
+CONFIG_FILE_PATH="$SNAP/etc/up-to-date-config.yaml"
+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.
Add the overwritable 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!
Provide the customizable configuration file
Launcher script
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 teleop_launcher.sh
:
#!/usr/bin/bash
+CUSTOM_CONFIG_FILE_PATH="$SNAP_COMMON/up-to-date-config.yaml”
CONFIG_FILE_PATH="$SNAP/etc/up-to-date-config.yaml"
+if [[ -f $CUSTOM_CONFIG_FILE_PATH ]]; then
+ CONFIG_FILE_PATH=$CUSTOM_CONFIG_FILE_PATH
+fi
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.
Install the customizable configuration at install
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:
#!/usr/bin/bash -e
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 install
hook:
mkdir snap/hooks
We can then add the file snap/hooks/install
:
#!/usr/bin/bash
$SNAP/bin/reset-overwritable-configuration.bash
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.
Add an application to reset the configuration
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 snapcraft.yaml
:
apps:
my-ros2-teleop-test:
command: bin/teleop_launcher.bash
plugs: [network, network-bind]
extensions: [ros2-humble]
environment:
"LD_LIBRARY_PATH": "$LD_LIBRARY_PATH:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/blas:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/lapack"
+ reset-overwritable-configuration:
+ 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!
Testing
We can now test the overwritable configuration. First, we build and install the snap:
snapcraft
sudo snap install my-ros2-teleop-test_*.snap --dangerous
The snap being installed, we can make sure that the customizable YAML was correctly placed:
cat /var/snap/my-ros2-teleop-test/common/up-to-date-config.yaml
We then see the default content of the file:
key_teleop:
ros__parameters:
forward_rate : 1.0
backward_rate: 0.5
rotation_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:
my-ros2-teleop-test
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:
sudo my-ros2-teleop-test.setup-overwritable-configuration
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.