Software orchestration is the method of integrating purposes collectively to automate and synchronise processes. In robotics, that is important, particularly on complicated techniques that contain lots of completely different processes working collectively. However, ROS purposes are often launched unexpectedly from one top-level launch file.
With orchestration, smaller launch information could possibly be launched and synchronised to start out one after the opposite to verify every thing is in the fitting state. Orchestration may maintain processes and insert some course of logic. That is what ROS orchestration ought to be about.
This fashion, as an example, you would make your localisation
node begin solely as soon as your map_server
made the map obtainable.
Snaps supply orchestration options which may come useful to your ROS orchestration.
On this publish, we are going to exhibit how you can begin a snap routinely at boot and how you can monitor it. Then, by way of some examples, we are going to discover the completely different orchestration options that snaps supply. We thus assume that you’re aware of snaps for ROS; for those who aren’t, or want a refresher, head over to the documentation web page.
Let’s get began
Allow us to first construct and set up the snap we are going to use on this step-by-step tutorial
git clone https://github.com/ubuntu-robotics/ros-snaps-examples.git -b ros_orchestration_with_snaps_blog
cd ros-snaps-examples/orchestration_humble_core22
SNAPCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS=1 snapcraft
sudo snap set up talker-listener_0.1_amd64.snap --dangerous
Observe that each one the steps described hereafter are already carried out on this git repository. Nevertheless, they’re commented so that you can simply comply with alongside.
Begin a ROS software routinely at boot
After you have examined and snapped your robotics software program, you can begin it from the shell. For an autonomous robotic, beginning your purposes routinely at boot is preferable than beginning manually each single time. It clearly saves time and most significantly makes your robotic actually autonomous.
Snaps supply a easy method to flip your snap command into companies and daemons, in order that they may both begin routinely at boot time and finish when the machine is shut down, or begin and cease on demand by way of socket activation.
Right here, we are going to work with a easy ROS 2 Humble talker-listener that’s already snapped (strictly confined). If you wish to know the way the talker-listener was snapped, you’ll be able to go to the The right way to construct a snap utilizing ROS 2 Humble weblog publish.
Flip your snap command right into a daemon
After you have snapped your software, you cannot solely expose instructions, but in addition create daemons.
- Daemons are instructions that may be began routinely at boot, which is a must have to your robotic software program.
For now, our snap is exposing two instructions – talker
and listener
. They respectively begin the node publishing message and the node subscribing and listening to the message.
You possibly can check the snap by launching every of the next instructions in their very own terminal:
$ talker-listener.talker
$ talker-listener.listener
So as to begin them each routinely within the background, we should flip them into daemons. Snap daemons may be of various varieties, however the commonest one is “easy
”. It’ll merely run so long as the service is enabled.
To show our software into daemons, we solely have so as to add ‘daemon: easy
’ to each our snap purposes:
apps:
listener:
command: decide/ros/humble/bin/ros2 run demo_nodes_cpp listener
+ daemon: easy
plugs: [network, network-bind]
extensions: [ros2-humble]
talker: command: decide/ros/humble/bin/ros2 run demo_nodes_cpp talker
+ daemon: easy
plugs: [network, network-bind]
extensions: [ros2-humble]
All there’s left to do is to rebuild and re-install the snap. Upon set up, each daemons are going to be routinely began in no explicit order
Now we are able to construct and set up this snap.
Test your daemons
Now our talker
and listener
are working within the background. Snaps supply a method to monitor and work together together with your snap daemons.
Snap daemons are literally plain SystemD daemons so in case you are aware of SystemD instructions and instruments (systemctl, journalctl, and so forth.
) you should use them for snap daemons too.
For this publish, we’re going to concentrate on snap
instructions to work together with our daemons and monitor them.
Test our service standing
The very very first thing could be to confirm the standing of our daemons, ensuring they’re working. The snap data command provides us a abstract of the standing of our daemons,
$ snap data talker-listener
title: talker-listener
abstract: ROS 2 Talker/Listener Instance
writer: –
license: unset
description: |
This instance launches a ROS 2 talker and listener.
Companies:
talker-listener.listener: easy, enabled, lively
talker-listener.talker: easy, enabled, lively
refresh-date: right now at 18:00 CEST
put in: 0.1 (x35) 69MB -
Right here we see our two companies listed. They’re each easy
, enabled
and lively
.
Easy
is the kind of daemon we specified. Enabled
, implies that our service is supposed to start out routinely (at boot, upon snap set up and so forth). Lively
, implies that our service is presently working.
So right here, each our talker
and listener
companies are up and working. Let’s browse the logs.
Searching the logs
The snap command additionally presents a method to browse our service logs.
Since our companies are already working within the background, we are able to sort:
$ sudo snap logs talker-listener
2022-08-23T11:13:08+02:00 talker-listener.listener [2833606]: [INFO] [1661245988.120676423] [talker]: Publishing: 'Howdy World: 123'
[...]
2022-08-23T11:13:12+02:00 talker-listener.talker[2833607]: [INFO] [1661245992.121411564] [listener]: I heard: [Hello World: 123]
This command will fetch the logs of our companies and show the final 10 strains by default. In case you need the command to repeatedly run and print new logs as they arrive in, you should use the “-f
” possibility:
sudo snap logs talker-listener -f
Observe that to date we have now been fetching the logs of our complete snap (each companies). We will additionally get the logs of a particular service. To repeatedly fetch the listener
logs, sort:
sudo snap logs talker-listener.listener -f
Work together with snap daemons
The snap command additionally presents methods to regulate companies. As we noticed, our companies are presently enabled
and lively
.
Enabled
, means our service will begin routinely at boot. We will change this by “disabling” it, so it received’t begin routinely any extra
sudo snap disable talker-listener.talker
Observe that disabling the service received’t cease the present working course of.
We will additionally cease the present course of altogether with:
sudo snap cease talker-listener.talker
Conversely, we are able to allow/begin a service with:
sudo snap allow talker-listener.talker
sudo snap begin talker-listener.talker
Make sure that to re-enable every thing to maintain following this publish alongside:
sudo snap allow talker-listener
ROS orchestration
To this point, our talker and listener begin up with none particular orchestration; or in layman’s phrases, in no particular order. Thankfully, snaps supply alternative ways to orchestrate companies.
To boost our expertise, let’s add some script to our snap to showcase the orchestration options:
Elements:
[...]
+ # copy native scripts to the snap usr/bin
+ local-files:
+ plugin: dump
+ supply: snap/native/
+ set up: '*.sh': usr/bin/
This can be a assortment of bash scripts which have been conveniently ready to exhibit orchestration hereafter.
We will even add one other app:
Apps:
[...]
+ listener-waiter:
+ command: usr/bin/listener-waiter.sh
+ daemon: oneshot
+ plugs: [network, network-bind]
+ extensions: [ros2-humble]
+ # Crucial for python3 ROS app
+ atmosphere: "LD_LIBRARY_PATH": "$LD_LIBRARY_PATH:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/blas:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/lapack"
This app is solely ready for the node /listener
to be current. This daemon is created as a “oneshot
”, one other sort of daemon that’s meant to solely be run as soon as at begin after which exit after completion.
After and earlier than for ROS orchestration
The very very first thing we are able to do is to vary the beginning order. The after/earlier than
key phrases are legitimate just for daemons and permit us to specify if a particular daemon ought to be began after
or earlier than
one (or a number of) different service(s). Observe that for oneshot
daemons, the earlier than/after
key phrases are ready for the completion of the oneshot
service.
The state of affairs right here goes as follows: begin the listener
, make certain it’s correctly began, then and solely then, begin the talker
. To ensure our listener
is correctly began, we are going to use the listener-waiter
app we launched within the earlier part. Keep in mind, it waits for a node to be listed.
Right here, we outline the orchestration solely on the listener-waiter
software stage to maintain it easy. So, we would like it to start out after the listener
and earlier than the talker
so the talker
will begin solely as soon as the listener
is prepared.
To take action, let’s use the earlier than/after
key phrases:
listener-waiter:
command: usr/bin/listener-waiter.sh
daemon: oneshot
+ after: [listener]
+ earlier than: [talker]
plugs: [network, network-bind]
extensions: [ros2-humble]
That is somewhat specific, it have to be began after
the listener
however earlier than
the talker
. After rebuilding the snap, we are able to reinstall it and have a look at the log once more. Here’s a shortened model of the output logs:
systemd[1]: Began Service for snap software talker-listener.listener.
systemd[1]: Beginning Service for snap software talker-listener.listener-waiter... talker-listener.listener-waiter[76329]: Ensuring the listener is began
systemd[1]: snap.talker-listener.listener-waiter.service: Succeeded.
systemd[1]: Completed Service for snap software talker-listener.listener-waiter. systemd[1]: Began Service for snap software
talker-listener.talker. [talker]: Publishing: 'Howdy World: 1'
talker-listener.listener[76439]: [INFO] [1661266809.685248681] [listener]: I heard: [Hello World: 1]
We will see on this log that every thing went as anticipated. The talker
has been began solely as soon as the listener
was obtainable.
On this instance, we specified the earlier than/after
area throughout the listener-waiter
for the sake of simplicity. Nevertheless, any daemon can specify a earlier than/after
so long as the desired purposes are from the identical snap, permitting for fairly complicated orchestration.
Cease-command for ROS orchestration
One other fascinating characteristic for snap orchestration is the stop-command
. It permits one to specify a script, or a command, to be known as proper earlier than the cease sign is shipped to a program when working snap cease
. With this, we may make certain, as an example, that every thing is synchronised or saved earlier than exiting. Let’s have a look at a fast instance: working an echo of a string.
A script known as stop-command.sh
has already been added to the snap usr/bin
.
All we have to do right here is to specify the trail to the stated script as a stop-command
.
talker:
command: decide/ros/humble/bin/ros2 run demo_nodes_cpp talker
plugs: [network, network-bind]
daemon: easy
+ stop-command: usr/bin/stop-command.sh
extensions: [ros2-humble]
After rebuilding and reinstalling the snap, we are able to set off a cease manually with the snap cease
command:
sudo snap cease talker-listener # cease all of the companies of this snap
sudo snap logs talker-listener -f # visualize the logs
We must always see an output much like:
systemd[1]: Stopping Service for snap software talker-listener.listener...
systemd[1]: snap.talker-listener.listener.service: Succeeded.
systemd[1]: Stopped Service for snap software talker-listener.listener.
systemd[1]: Stopping Service for snap software talker-listener.talker...
talker-listener.talker[86863]: About to cease the service
systemd[1]: snap.talker-listener.talker.service: Succeeded. 2022-08-23T17:23:57+02:00 systemd[1]: Stopped Service for snap software talker-listener.talker.
From the logs, we are able to see that earlier than exiting the service talker
, the stop-command
script was executed and printed a message: “About to cease the service
”. Then, solely after the stop-command
script completed, was the talker
terminated.
Put up-stop-command for ROS orchestration
Equally to the stop-command
entry, the post-stop-command
can be calling a command, however this time, solely after the service is stopped.
The use case could possibly be to run some knowledge clean-up and even notify a server that your system simply stopped. Once more, allow us to do that characteristic with a conveniently pre-baked script logging a message
talker:
command: decide/ros/humble/bin/ros2 run demo_nodes_cpp talker
plugs: [network, network-bind]
daemon: easy
stop-command: usr/bin/stop-command.sh
+ post-stop-command: usr/bin/post-stop-command.sh
extensions: [ros2-humble]
Rebuild, re-install, and with out a lot shock, we get the next output:
systemd[1]: Stopping Service for snap software talker-listener.talker...
talker-listener.talker[90660]: About to cease the service
talker-listener.talker[90548]: [INFO] [1661269138.094854527] [rclcpp]: signal_handler(signum=15)
talker-listener.talker[90710]: Goodbye from the post-stop-command!
systemd[1]: snap.talker-listener.talker.service: Succeeded.
systemd[1]: Stopped Service for snap software talker-listener.talker.
From the logs we are able to see that our talker
software executed the stop-command
script then acquired the termination sign and solely after our post-command
script logged the message: ”Goodbye from the post-stop-command!
”.
Command-chain
To this point, we have now seen how you can name further instructions across the second we cease our service. The command-chain
key phrase permits us to record instructions to be executed earlier than our important command. The attribute use case is to arrange your atmosphere. The ros2-humble
extension that we’re utilizing in our snap instance is definitely utilizing this mechanism. Due to it, we don’t have to fret about sourcing the ROS atmosphere within the snap. If you’re curious, right here is the stated command-chain script. The very best half is that the command-chain
entry will not be solely obtainable for daemons, but in addition for companies and common instructions.
The scripts listed within the command-chain
should not known as one after the other routinely. As a substitute, they’re known as as arguments of every others, leading to a closing command much like:
./command-chain-script1.sh command-chain-script2.sh main-script.sh
So you have to guarantee that your command-chain-scripts
are calling handed arguments as executables. For instance, right here, command-chain-script1.sh
is chargeable for calling command-chain-script2.sh
.
Let’s see what our command-chain-talker.sh script appears to be like like
#!/usr/bin/sh
echo "Howdy from the talker command-chain!"
# Crucial to start out the principle command
exec $@
The one factor to concentrate to is the exec $@
which is solely calling the following command. If we don’t specify this, our important snap command received’t be known as.
Let’s add yet one more script to our talker
command-chain
:
talker:
+ command-chain: [usr/bin/command-chain-talker.sh]
command: decide/ros/humble/bin/ros2 run demo_nodes_cpp talker
plugs: [network, network-bind]
daemon: easy
stop-command: usr/bin/stop-command.sh
post-stop-command: usr/bin/post-stop-command.sh
extensions: [ros2-humble]
After constructing and putting in, we are able to see that now the logs are:
systemd[1]: Beginning Service for snap software talker-listener.listener-waiter... talker-listener.listener-waiter[96438]: Ensuring the listener is began
systemd[1]: snap.talker-listener.listener-waiter.service: Succeeded.
systemd[1]: Completed Service for snap software talker-listener.listener-waiter.
systemd[1]: Began Service for snap software talker-listener.talker.
talker-listener.talker[96538]: Howdy from the talker command-chain!
talker-listener.talker[96594]: [INFO] [1661271361.139378609] [talker]: Publishing: 'Howdy World: 1'
We will see from the logs that after our listener
was obtainable, the talker
half was began. The command-chain-talker.sh
script was known as and printed the message: “Howdy from the talker command-chain!
”, and solely after that our talker began publishing.
Conclusion
I hope that studying this text helps you perceive the snap daemon incorporates a bit extra and evokes you to make use of them for ROS orchestration. For now, orchestration can solely be completed throughout the similar snap, since strictly confined snaps should not allowed to launch different purposes exterior their sandbox. In fact, you would additionally mix the snap orchestration options with different orchestration software program. Most notably, ROS 2 nodes lifecycle means that you can management the state of your nodes, as a way to orchestrate your node’s initialisation, as an example.
In case you have any suggestions, questions or concepts relating to ROS snap orchestration with snaps, please be part of our discussion board and tell us what you assume. Moreover, take a look on the snap documentation if you wish to be taught extra about snaps for robotics purposes.