How to set up TurtleBot3 in minutes with snaps (2/2)
by Jeremie Deray on 12 May 2020
Welcome to part two of our TurtleBot3 set up, namely the turtlebot3c
project. In part one, we rearranged the launch files and configuration files of the TurtleBot3 so that we have four entry points to our robot’s functionalities. One per application in our snap. Now it is time to build the snap so that it can be installed and run on the onboard computer.
Prerequisites
We will be creating a snap in this blog post, and we will assume that you understand the basics of how those work. If you need a refresher, you’ll find the details of creating a snap for your ROS application in this brief tutorial, as well as part 5 of the mini-series of posts entitled ‘Your first robot’. You may also find the documentation for the snapcraft Catkin plugin helpful. Finally, make sure to have read part one as we explain how and why we set up the TurtleBot3 launch files the way they are.
Deploying on the TurtleBot3
The TurtleBot3 onboard computer is a RaspberryPi 3b+, an ARM architecture. This essentially means that one cannot simply build a snap on a beefy desktop (likely x86 architecture) and copy it on the Pi3 as it resolves into an architecture incompatibility. And where would be the fun in doing that, it would be too simple. We will investigate our options hereafter.
Snapping directly on the Raspberry Pi
Snapcraft
is a tool for developers to package their programs in the snap format. By default, it uses multipass
to isolate the build process. However, multipass is not available for ARM platforms, so we will use LXD instead. And you are one lucky reader because since this work started, snapcraft support for LXD containers on ARM platforms has improved a lot. So much so that building a snap on the Pi3, in a LXD container, boils down to a single command,
snapcraft --use-lxd
Easy, right?
But let us take a step back and detail a little more how we get there.
Setting up the workspace
First, let’s create our ROS workspace on the Pi3. You can either use your own or use the following commands to clone the turtlebot3c project. In a terminal, open an SSH connection to the Pi3 and clone the following packages:
mkdir -p ~/tb3c_ws/src & cd ~/tb3c_ws/src
git clone https://github.com/ROBOTIS-GIT/turtlebot3 --branch melodic-devel
git clone https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git --branch melodic-devel
git clone https://github.com/canonical/turtlebot3c
Setting up snapcraft on the Raspberry Pi
Whether you are using Ubuntu 18.04 or Raspbian, chances are we have to either install or update your snapcraft version. To do so, the following steps should work regardless of the distro in use (note that they should be fairly similar on other Linux distro).
First we will install snapd
:
sudo apt update
sudo apt install snapd
Next we’ll install the snapcraft snap:
sudo snap install snapcraft
At the time of writing, the version of snapcraft installed by the above command is not recent enough for our use case since we require some bugfixes that landed in version 4.0. You can verify your current version with snapcraft --version
. If it is any lower than 4.0, update it as follows,
sudo snap refresh snapcraft --channel=latest/candidate
The turtlebot3c snap configuration file
Now that the ROS workspace and packaging process are ready, the next step is to write the snapcraft configuration file for the snap. We will skip many of the details of the snapcraft.yaml (see the prerequisites if you need the details), and simply highlight below the different apps and how they map to the reorganisation work we did in part one of this post.
apps:
core:
daemon: simple
command: roslaunch turtlebot3c_bringup turtlebot3c_bringup.launch
teleop:
daemon: simple
command: roslaunch turtlebot3c_teleop turtlebot3c_teleop.launch
mapping:
command: rosrun turtlebot3c_2dnav mapping_manager
navigation:
command: roslaunch turtlebot3c_2dnav turtlebot3c_navigation.launch
Although this is not a complete configuration file, there are still a few important features to note. First, you may have noticed that two of our apps are actually daemons. It means that both are automatically launched when the robot is turned on; one can start working with it right away!
It is all about the small details
The second noticeable thing happening here is that the ‘mapping’ app actually starts an unknown ‘mapping_manager’ node. Behind the pompous name actually lies a simple Python script whose main purpose is to launch the mapping and tear it down. But that’s not its only task. Before shutting down mapping, it also automatically saves the map to a predefined directory so that you, the user, don’t have to do it. Furthermore, the navigation app also loads the map from this predefined directory so that you, the user, don’t have to worry about it. Simple things that make the user experience so much better.
But how does that manager work? Well, without getting too deep in the details (although you can read the script), we rely on the roslaunch Python API which allows us to easily launch and stop ROS nodes given a launch file. It is very similar to calling the launch file directly from the terminal. However, when the user hits ctrl+c
to stop the mapping, our script also calls the map_saver
node to save to map before tearing the mapping down. The map is saved in $SNAP_USER_DATA/.tb3c/maps/<date><time>/
where $SNAP_USER_DATA
is the root directory for user data in snaps (find out more about snaps environment variables) and <date><time>
is the date and time at which the map is saved. In order for the navigation stack to find the latest map always at the same path, a softlink is create from $SNAP_USER_DATA/.tb3c/maps/<date><time>/
as $SNAP_USER_DATA/.tb3c/maps/config/
.
You can find the complete snapcraft configuration file for the turtlebot3c project online. Mind that it sets up the ROS workspace using a rosinstall file. If you wish to use it with the local workspace we have set up earlier, simply delete the line referring to the rosinstall file.
Time to package!
Alright, now that we are fully set up, let’s hit that enter button shall we?
cd ~/tb3c_ws
snapcraft --use-lxd
Snapcraft will pull a LXD container, update it, pull all the necessary ROS dependencies, build your workspace, install it and finalise the snap. This can be long. In the meantime let us discuss how to speed this process up by sending the workload to the cloud.
Snapping remotely
One may ask,
But are there no alternatives to building my snap on the Pi3? It is a nice board but not super powerful…
Fear not for we have options! And we will overview hereafter two of them that allow you to easily build your snap remotely, in the cloud.
Remote build
Remote build is a snapcraft feature which allows anyone to build a snap for multiple architectures on remote servers using Launchpad. To use it, you will need to create an account on Launchpad and set up an SSH key. Furthermore, it is important to note that using this feature will upload your project on Launchpad where it will be publicly available. If this is fine by you, after creating your account, you can send the workload to the cloud as follows,
snapcraft remote-build --launchpad-user <username> --build-on=<Pi3-arch>
where <username>
is obviously your username on Launchpad and <Pi3-arch>
is the architecture type of the Pi3. Note that it may be different whether you use Ubuntu Server (32 or 64 bit) or Raspbian (32 bit). To find out the architecture simply issue the command,
dpkg --print-architecture
snapcraft.io/build
This second option is probably the most interesting for Open Source project developers. It allows you to hook up your GitHub repository to snapcraft.io/build, and automatically builds your snap on commit pushes and publishes it to the snapstore. It couldn’t be easier! Find a quick start guide here.
After iterating the snap a couple times on the Pi3, we used this solution to speed up the process and automatically build the snap for all plausible architectures!
Installing the snap
Ding, ding, ding. The snap packaging process just finished and our snap is ready for installation. Let us finish the Turtlebot3 set up.
If you built locally or using the remote-build option, you’ll use the following command:
sudo snap install --dangerous turtlebot3c.1_<Pi3-arch>.snap
Note the --dangerous
flag. When a snap comes from a trusted place (e.g. the store) it comes along with signatures that prove that it is what it claims to be and that it’s created by who it claims created it. However, in our case, since we’re installing the snap from disk instead of from the store, we don’t have any of those signatures and need to use --dangerous
to say that, for this situation, it’s okay. Generally this is not something you should need to do outside of developing a snap.
If, however, you have used snapcraft.io/build, use the following command,
sudo snap install --edge <your snap name>
Using the turtlebot3c
The TurtleBot3 is set up, let the fun begin! Upon installation, the snap should start its daemons automatically, both the core and the teleop apps. Therefore we should be able to visualise the turtlebot3c in Rviz. In a terminal on your desktop, set the ROS master IP to point to the robot and open Rviz,
export ROS_MASTER_URI=http://<TURTLEBOT3-IP>:11311
rosrun rviz rviz
In Rviz, try adding for instance the TF visualisation or the laser scan one.
Next let us try to drive the robot. In a new terminal, export again the ROS master IP and open a keyboard-based teleoperation node, namely the key_teleop. But remember, as we have seen in part one, we also have to tell the mux node that we want it to forward the control command from the key_teleop node:
export ROS_MASTER_URI=http://<TURTLEBOT3-IP>:11311
rosservice call /mux/select "topic: 'key_vel'"
rosrun key_teleop key_teleop
Isn’t it easy? Driving the robot around using the keyboard’s arrow keys?!
mapping
Let’s get to the really interesting bit, autonomous navigation. And we will start by building a map. To do so, keep the teleoperation terminal open on your desktop and open a new terminal on the Pi3 and enter,
turtlebot3c.mapping
This command starts the whole mapping stack. All we have to do is to drive the robot around, trying to cover as well as possible the entire environment. Once done, simply terminate the mapping with ctrl+c
. As mentioned before, the map is automatically saved on the robot.
navigation
With our environment mapped, it is time to let go. That is, to let our turtlebot3c go all by itself around the place. First, we have to tell the mux node that we want it to forward commands from the navigation stack:
rosservice call /mux/select "topic: 'nav_vel'"
Again we will keep the visualisation open on our desktop and enter the following command on the Pi3,
turtlebot3c.navigation
From the Rviz window, set the robot initial position. It is now ready for its first autonomous walk. Well, autonomous drive. Set a goal through Rviz and watch it move around! If you aren’t sure how to do that, heads over to the Navigation tutorials on the ROS wiki for a quick overview.
Wrap up
In this series, we discussed the thought process and the different technologies involved in making a snap for a whole robotic system. While we didn’t dive too deeply into the details of each and every step, I hope I have provided you with enough insights, information and links to get you started packaging your own robot. As for me, the main objective of this work is complete: cutting hours of installation process to barely minutes, replacing tonnes of terminal commands by a consistent and secure way to repeatedly set up my TurtleBot3.
The snap is already available in the snapstore in case you want to try it right now. To install it, open a SSH connection in a terminal to the Pi3 and type,
sudo snap install turtlebot3c
This project is, again, completely open source. Please feel free to log an issue if you have any questions, or see any improvements that can be made. Have fun!