You're reading the documentation for an older, but still supported, version of ROS 2. For information on the latest version, please have a look at Jazzy.

Using substitutions

Goal: Learn about substitutions in ROS 2 launch files.

Tutorial level: Intermediate

Time: 15 minutes

Background

Launch files are used to start nodes, services and execute processes. This set of actions may have arguments, which affect their behavior. Substitutions can be used in arguments to provide more flexibility when describing reusable launch files. Substitutions are variables that are only evaluated during execution of the launch description and can be used to acquire specific information like a launch configuration, an environment variable, or to evaluate an arbitrary Python expression.

This tutorial shows usage examples of substitutions in ROS 2 launch files.

Prerequisites

This tutorial uses the turtlesim package. This tutorial also assumes you are familiar with creating packages.

As always, don’t forget to source ROS 2 in every new terminal you open.

Using substitutions

1 Create and setup the package

First, create a new package with the name launch_tutorial:

Create a new package of build_type ament_python:

ros2 pkg create --build-type ament_python --license Apache-2.0 launch_tutorial

Inside of that package, create a directory called launch:

mkdir launch_tutorial/launch

Finally, make sure to install the launch files:

Add in following changes to the setup.py of the package:

import os
from glob import glob
from setuptools import find_packages, setup

package_name = 'launch_tutorial'

setup(
    # Other parameters ...
    data_files=[
        # ... Other data files
        # Include all launch files.
        (os.path.join('share', package_name, 'launch'), glob('launch/*'))
    ]
)

2 Parent launch file

Let’s create a launch file that will call and pass arguments to another launch file. This launch file can either be in YAML, XML, or in Python.

To do this, create following file in the launch folder of the launch_tutorial package.

Copy and paste the complete code into the launch/example_main_launch.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<launch>
  <let name="background_r" value="200" />
  <include file="$(find-pkg-share launch_tutorial)/launch/example_substitutions_launch.xml">
    <arg name="turtlesim_ns" value="turtlesim2" />
    <arg name="use_provided_red" value="True" />
    <arg name="new_background_r" value="$(var background_r)" />
  </include>
</launch>

The $(find-pkg-share launch_tutorial) substitution is used to find the path to the launch_tutorial package. The path substitution is then joined with the example_substitutions_launch.xml file name.

  <include file="$(find-pkg-share launch_tutorial)/launch/example_substitutions_launch.xml">

The background_r variable with turtlesim_ns and use_provided_red arguments is passed to the include action. The $(var background_r) substitution is used to define the new_background_r argument with the value of the background_r variable.

    <arg name="turtlesim_ns" value="turtlesim2" />
    <arg name="use_provided_red" value="True" />
    <arg name="new_background_r" value="$(var background_r)" />

3 Substitutions example launch file

Now create the substitution launch file in the same folder:

Create the file launch/example_substitutions_launch.xml and insert the following code:

<?xml version="1.0" encoding="UTF-8"?>
<launch>
  <arg name="turtlesim_ns" default="turtlesim1" />
  <arg name="use_provided_red" default="False" />
  <arg name="new_background_r" default="200" />

  <node pkg="turtlesim" namespace="$(var turtlesim_ns)" exec="turtlesim_node" name="sim" />
  <executable cmd="ros2 service call $(var turtlesim_ns)/spawn turtlesim/srv/Spawn '{x: 5, y: 2, theta: 0.2}'" />
  <executable cmd="ros2 param set $(var turtlesim_ns)/sim background_r 120" />
  <timer period="2.0">
    <executable cmd="ros2 param set $(var turtlesim_ns)/sim background_r $(var new_background_r)"
      if="$(eval '$(var new_background_r) == 200 and $(var use_provided_red)')" />
  </timer>
</launch>

The turtlesim_ns, use_provided_red, and new_background_r launch configurations are defined. They are used to store values of launch arguments in the above variables and to pass them to required actions. The launch configuration arguments can later be used with the $(var <name>) substitution to acquire the value of the launch argument in any part of the launch description.

The arg tag is used to define the launch argument that can be passed from the above launch file or from the console.

  <arg name="turtlesim_ns" default="turtlesim1" />
  <arg name="use_provided_red" default="False" />
  <arg name="new_background_r" default="200" />

The turtlesim_node node with the namespace set to the turtlesim_ns launch configuration value using the $(var <name>) substitution is defined.

  <node pkg="turtlesim" namespace="$(var turtlesim_ns)" exec="turtlesim_node" name="sim" />

Afterwards, an executable action is defined with the corresponding cmd tag. This command makes a call to the spawn service of the turtlesim node.

Additionally, the $(var <name>) substitution is used to get the value of the turtlesim_ns launch argument to construct a command string.

  <executable cmd="ros2 service call $(var turtlesim_ns)/spawn turtlesim/srv/Spawn '{x: 5, y: 2, theta: 0.2}'" />

The same approach is used for the ros2 param executable actions that change the turtlesim background’s red color parameter. The difference is that the second action inside of the timer is only executed if the provided new_background_r argument equals 200 and the use_provided_red launch argument is set to True. The evaluation of the if predicate is done using the $(eval <python-expression>) substitution.

  <executable cmd="ros2 param set $(var turtlesim_ns)/sim background_r 120" />
  <timer period="2.0">
    <executable cmd="ros2 param set $(var turtlesim_ns)/sim background_r $(var new_background_r)"
      if="$(eval '$(var new_background_r) == 200 and $(var use_provided_red)')" />
  </timer>

4 Build the package

Go to the root of the workspace, and build the package:

colcon build

Also remember to source the workspace after building.

Launching example

Now you can launch using the ros2 launch command.

ros2 launch launch_tutorial example_main.launch.yaml

This will do the following:

  1. Start a turtlesim node with a blue background

  2. Spawn the second turtle

  3. Change the color to purple

  4. Change the color to pink after two seconds if the provided background_r argument is 200 and use_provided_red argument is True

Modifying launch arguments

If you want to change the provided launch arguments, you can either update the background_r variable in the example_main.launch.yaml or launch the example_substitutions.launch.yaml with preferred arguments. To see arguments that may be given to the launch file, run the following command:

ros2 launch launch_tutorial example_substitutions.launch.yaml --show-args

This will show the arguments that may be given to the launch file and their default values.

Arguments (pass arguments as '<name>:=<value>'):

    'turtlesim_ns':
        no description given
        (default: 'turtlesim1')

    'use_provided_red':
        no description given
        (default: 'False')

    'new_background_r':
        no description given
        (default: '200')

Now you can pass the desired arguments to the launch file as follows:

ros2 launch launch_tutorial example_substitutions.launch.yaml turtlesim_ns:='turtlesim3' use_provided_red:='True' new_background_r:=200

Documentation

The launch documentation provides detailed information about available substitutions.

Summary

In this tutorial, you learned about using substitutions in launch files. You learned about their possibilities and capabilities to create reusable launch files.

You can now learn more about using event handlers in launch files which are used to define a complex set of rules which can be used to dynamically modify the launch file.