How Does the ROS2 Turtlebot4 Service Launch When the TurtleBot Boots Up?

If you’re like me, you probably bought your ClearPath Robotics TurtleBot4 online, got excited, ripped the box open, charged and then fired the thing up. Then you probably got confused a bit, then figured some things out, ran the tutorials and ended up at a point where you are saying, “OK. I get it. Now what am I going to do next?”

Well. Maybe those are some big assumptions, but if you’re here, maybe one thing you’re wondering about is “How exactly does ROS get launched on the TurtleBot4 when it boots up?”

This becomes a pretty important question as soon as you begin considering how you might want to modify the robot or architecture to suit your specific needs or curiosities. Ultimately, you’re probably going to want the robot to load and run your code, and ultimately, modifications you’ve made to the TurtleBot4 packages when it boots up.

I decided to do a bit of a deep dive on understanding how these things work so that I could comfortably make modifications to my TurtleBot4 without ruining the maintainability and intended ROS architecture on the device. These are my notes, and hopefully they will be useful to you if you undertake a similar journey.

ROS2 Launch Files and How They Work

I generally like to avoid re-writing or cut-and-paste from existing documentation because if things shift over time, then my articles become somewhat obsolete and frustrating. So, wherever possible below, I try to reference the actual ROS documentation instead of copy-and-paste of the information into this post.

ROS2 Launch File Documentation

So, to start with, the ROS2 Galactic Documentation (Galactic is currently the version the TurtleBot4 is based upon at time of writing) has a very detailed explanation of how launch files work.

https://docs.ros.org/en/galactic/Tutorials/Intermediate/Launch/Creating-Launch-Files.html

To follow along on the rest of this, you’re going to have to have at least a basic understanding of what’s happening in the launch files, even if you’re not a launch file ninja. You can always reference back to those docs later.

TurtleBot4 Specific Launch Files

The next stop on our journey is to understand where the ROS Launch Files for the TurtleBot4 come from. For the robot hardware itself, the turtlebot4_robot package contains the configuration and launch file info specific for how ROS interacts with the TurtleBot4 hardware and services.

https://github.com/turtlebot/turtlebot4_robot

Inside this metapackage, you will find that the turtlebot4_robot/turtlebot4_bringup/launch folder contains the launch files – standard.launch.py for the Standard Edition of the TurtleBot4, and lite.launch.py for the Lite Edition.

How Does the TurtleBot4 ROS Launch File Get Called When the Robot Boots Up? (Robot Upstart)

Ok. So, we know what files are being called to launch the robot. But, the question is where and when are these files getting called during the boot sequence when the robot fires up? Somewhere in the process of the Raspberry Pi 4 booting Linux, it’s also calling the ROS launch files, but how does that happen?

TurtleBot4 robot_upstart package

This took a little digging – I realize I probably read through it when I first read the User Manual for the TurtleBot4, but without context at the time, I didn’t entirely follow the significance of what was described.

Again – the reference to the source docs first: https://turtlebot.github.io/turtlebot4-user-manual/software/turtlebot4_packages.html#robot-upstart

Linux Services

The documentation above shows how the Linux services run and how they can be controlled with systemctl. This is fairly straight forward, particularly if you’ve run Linux services before (web servers or other such things).

If this is new to you, the basics are fairly straight forward – basically, a service is a background task that can be started and stopped using systemctl to enable or disable it within the OS.

On the TurtleBot4, a linux service aptly named “turtlebot4” is responsible for the launch and background execution of our ROS nodes.

Turtlebot4 Linux Service Cheat Sheet

The documentation above contains a lot more information about the service and is worth reading, but for our purposes the basic service operations will be what’s needed to start/stop and potentially replace the service with our own. So, we’ve “borrowed” the quick version of these things from the documentation below.

To check if the TurtleBot 4 service is running, use this command on the Raspberry Pi:

systemctl | grep turtlebot4

To read the most recent logs from the service, call:

sudo journalctl -u turtlebot4 -r

To stop the service, call:

sudo systemctl stop turtlebot4.service

To start the service again, call:

sudo systemctl start turtlebot4.service

What Exactly Is Going on Inside the Turtlebot4 Linux Services and How Could We Modify That Functionality?

Up to this point, things are still pretty “black box” – we know:

  • There is a Linux service called “turtlebot4” that is responsible for launching ROS and the nodes that control our robot.
  • We can interrogate, start, and stop that process using the Linux systemctl command

But, what can we do with this newfound knowledge, and where does this service come from in the first place? How does it set up the ROS environment? And, how might we change that if we wanted to override things a bit?

The Secrets Revealed by /usr/local/bin/install.py – Creating the TurtleBot4 Service Using the robot_upstart Package

While the documentation doesn’t specifically discuss the contents of the turtlebot4 service, it does show us that there’s a python script available to fast-track the installation of the service (called install.py) that is pre-installed on the Raspberry Pi.

After digging around a bit more for documentation on the robot_upstart, I found that it is a ClearPath module. It’s a bit sparsely documented in GitHub, but if you Google it, you can definitely find a lot more information about usage and how it works. You can find the repo here as a starting point: https://github.com/clearpathrobotics/robot_upstart/tree/foxy-devel

Honestly, it isn’t a huge deal, as we can easily have a look at the contents of the /usr/local/bin/install.py script that’s present on the Raspberry Pi, and figure out what’s going on, at least for the limited use case of the TurtleBot4 which is what we’re concerned with here.

Here is the install.py script:

#!/usr/bin/env python3
# Copyright 2022 Clearpath Robotics, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# @author Roni Kreinin (rkreinin@clearpathrobotics.com)

import sys

import robot_upstart

def help():
    print('TurtleBot 4 robot_upstart install script.')
    print('Usage: install.py [model] <ROS_DOMAIN_ID>')
    print('models: lite, standard')
    print('ROS_DOMAIN_ID: optional, defaults to 0')

argc = len(sys.argv)

if argc == 1:
    print('Model required.')
    help()
    sys.exit(1)

model = sys.argv[1]
if model != 'lite' and model != 'standard':
    print('Invalid model {0}'.format(model))
    help()
    sys.exit(2)

domain_id = 0
if argc == 3:
    try:
        domain_id = int(sys.argv[2])
    except ValueError:
        print('Invalid ROS_DOMAIN_ID {0}'.format(sys.argv[2]))
        help()
        sys.exit(3)

print('Installing TurtleBot 4 {0}. ROS_DOMAIN_ID={1}'.format(model, domain_id))

turtlebot4_job = robot_upstart.Job(name='turtlebot4',
                                 rmw='rmw_cyclonedds_cpp',
                                 rmw_config='/etc/cyclonedds_rpi.xml',
                       workspace_setup='/opt/ros/galactic/setup.bash', 
                                   ros_domain_id=domain_id)

turtlebot4_job.symlink = True
turtlebot4_job.add(package='turtlebot4_bringup', filename='launch/{0}.launch.py'.format(model))
turtlebot4_job.install()

Breaking Down How the install.py Script Works for Robot Upstart on the TurtleBot4

Most of the pre-amble is just parameter checking – the script takes the robot model (lite, or standard) as a parameter, as well as an optional override to the ROS_DOMAIN_ID and ensures the caller has made rational choices for those parameters.

The important stuff happens in the second half of the script:

turtlebot4_job = robot_upstart.Job(name='turtlebot4',
                                   rmw='rmw_cyclonedds_cpp',
                                   rmw_config='/etc/cyclonedds_rpi.xml',
workspace_setup='/opt/ros/galactic/setup.bash',
                                   ros_domain_id=domain_id)
turtlebot4_job.symlink = True
turtlebot4_job.add(package='turtlebot4_bringup', filename='launch/{0}.launch.py'.format(model))
turtlebot4_job.install()

We can see the following configurable parameters here in the calls to the robot_upstart package:

  • workspace_setup – Contains a reference to the ROS setup file sourced in order to establish the ROS Galactic Environment. Out of the box, this defaults to using the installation setup script. However, we could re-vector this set-up to point to our own script file that would potentially source overlays and other packages on top of the base Galactic install, thereby allowing us to override and add new packages that could be launched at upstart.
  • turtlebot4_job.add(package, filename) – Allows us to specify a launch file, (and presumably other jobs) to run on boot. We could add jobs, or override the launch file being used. The default is to call either the standard.launch.py or lite.launch.py scripts from the turtlebot4_bringup package, but its apparent how this can be augmented.

Next Steps

With Great Power Comes Great Responsibility

– Spider Man

So, what can we do with this new-found power to control the robot upstart on the TurtleBot4?

Well, for starters, we could definitely render the existing functionality of the robot fairly inoperable in a hurry if we made any mistakes, so it’s probably actually a good idea to leave all of the original scripts and install.py intact in case you need to go back to them at some point either as a recovery mechanism, or just to return the robot to it’s original state.

Therefore, I’d probably recommend the following procedure for any “experiments” you’re doing with the upstart sequence on the TurtleBot4:

  1. Stop the Default turtlebot4 service – Call sudo systemctl stop turtlebot4.service from the command line on the Raspberry Pi to do this, but to otherwise leave the service intact in case you want or need to restart it later.
  2. Copy /usr/bin/install.py to a different filename before modifying it – This can be done with a call to sudo cp /usr/local/bin/install.py /usr/local/bin/my-install.py
  3. Edit your new version of my-install.py to perform your custom installation steps, source a different environment script, and/or call a different launch file, etc. – Exactly what you need to do to customize your robot packages is your business.
  4. Call your new installation script to install and start your new service – call install.py model <ROS_DOMAIN_ID> (assuming you didn’t change the parameters to the python script).
  5. Follow the instructions provided by the install.py output to load and restart the system services.

That’s it! Good luck, and happy modifying.

Leave a Reply