UP | HOME

Launchfiles

Launchfiles and ROS

  • ROS programs consist of many nodes communicating over topics and services
  • For non-trivial programs, manually running nodes using ros2 run becomes tedious and hard to reproduce
  • Launchfiles provide a method for having a single command start the robot and enable specifying
    • Which nodes are run
    • What parameters they use
    • What topics are named
    • and more!
  • These Launchfile Tutorials will help get you started.

Documentation Note

  1. As of 10/2024 the API Documentation for launch files is not fully populated: this means links here point to empty documentation
  2. To build complete documentation locally:
    1. Clone https://github.com/ros2/launch
    2. Run rosdoc2 build --package-path launch/launch
    3. Open doc_output/launch/index.html in your browser

Types of Launchfiles

In ROS 2 (unlike ROS 1) there are multiple types of launchfiles:

  • Python launchfiles: these launchfiles are python scripts that use the ROS 2 Launch API to declare what actions should be taken on Launch
    • These launchfiles allow more complex launch descriptions than the alternatives
  • XML launchfiles: these are closer to ROS 1 launchfiles and they declare the nodes that should be running
    • Less flexible than python but easier for simple cases. However, in ROS 1 launchfiles often got complicated to the point of basically being programming without a real programming language. In these situations python launchfiles would be preferred.
  • YAML launchfiles: An alternative syntax to XML launchfiles

Using ros2 launch

  • The command-line tool for using launch files is ros2 launch
  • There are two ways of invoking a launchfile:
    1. ros2 launch package file.launch.{xml,py} [arg_name:=value]...
      • Here, the launch file must be installed into the install space (e.g., by setting up setup.py)
    2. ros2 launch package /path/to/launch/file.launch [arg_name:=value...]
      • Here, the launch file at the given location is directly used.
      • The main advantage is that you do not need to rebuild the workspace when you change the launchfile.
  • You can pass arguments to a launch file using the arg_name:=value syntax, which is shared with the remapping arguments syntax.

Ros2 launch options

  1. Use ros2 launch --help for a complete list of the options.
  2. -s or --show-arg You can pass arguments to a launchfile (using arg_name:=value) to change the behavior of the launchfile. This flag shows all the possible arguments and their documentation.
  3. --debug shows debugging information, which is useful if the launchfile is not working.

XML Launchfiles

  1. The ROS 1 Launchfile format relies on XML, along with a special enhanced substitution argument syntax.
    • Most easily understood in conjunction with ROS 2 Launchfile Migration Guide.
    • The launchfile system in ROS 2 is highly extendable
      • The basic launch functionality is implemented in the launch package. This repository contains generic tools for running processes on a system
      • ROS specific functionality is implemented in the launch_ros package.
        • For example, the Node launch action of launch_ros uses the ExecuteProcess launch action of launch.
      • The architecture of ROS 2 Launchfiles explains the concepts behind the design.
      • API Documentation contains XML examples for the python functions that have XML equivalents.
    • This Design Document lays out the format of ROS 2 XML launchfiles
  2. Launchfiles should be installed by adding them to the data_files section of setup.py.
    • Install the files to share/package_name/launch.
  3. Projects that use launchfiles should add ros2launch as an <exec_depend> in package.xml (because ros2 launch is required to use them).
  4. Launchfiles list nodes to be launched; however, the order in which they start is non-deterministic.
  5. Important Launchfile XML elements:
    • <launch> - the root element, every launchfile starts with this.
    • <node> - Used to run a node. Attributes:
      • pkg: the package the node is in.
      • exec (type in ROS 1): the name of the node executable file.
      • name: the basename of the node.
      • namespace (ns in ROS 1): the node's namespace.
      • output: determine where to send the output to (a log file or the screen).
      • required: if the node dies, the whole launch is terminated.
    • <include> - Lets you include a launchfile in another launchfile
    • <remap> - Used for Remapping arguments
    • <param> - Sets an individual parameter for a node (or on the parameter server in ROS 1).
      • In ROS 2 the "command" attribute does not exist. To set a parameter to the output of a command use the $(command) substitution.
    • <group> - Groups nodes together and allows you to easily apply common settings
    • <arg> - Used to specify arguments which can be used to change the behavior of the launchfile from the command-line.
      • You should always provide documentation for Launchfile arguments using the description attribute (called doc in ROS 1).
    • <let> - used to define a constant (ROS 2 only, handled by <arg> in ROS 1)
    • <env> - Used to set environment variables for the underlying node
  6. Conditionals:
  7. Substitution arguments:
    • The following items can be used within attribute values to perform a computation and expand into the result of that computation
    • The general syntax uses $() (just like bash substitution arguments).
    • Within XML, a substitution argument would be used like <tag attribute ="$()" />.
    • A list of some possible substitution arguments is below:
      1. $(env ENVIRONMENT_VARIABLE) Expands into the value of the environment variable or is an error if that variable is not set.
      2. $(env ENVIRONMENT_VARIABLE default) Expands into the value of an environment variable or default if it is not set. (In ROS 1 this was $(optenv))
      3. $(find-pkg-share)$ expands to the location of a given package's share directory. Useful for finding configuration and data files associated with the package
      4. $(find-pkg-prefix)$ expands
      5. $(var myarg) expands into the value of myarg, as specified by an <arg> element and passed in on the call to roslaunch
      6. $(eval <expression>) Runs python code <expression> and expands to the result of the code evaluation
        • This does not yet behave exactly like the ROS 1 version:
          1. <expression> should be a single-quoted string
          2. If the expression itself uses single-quotes, those need to be escaped (e.g., 'mystring' becomes \'mystring\')
          3. Some ROS 1 shortcuts for accessing launchfile arguments are not supported: instead the substitution must be used: (e.g., $(var argname) will literally transform into the value of argname
      7. $(command '<expression>') runs a command and returns the output (ROS 2 only).
  8. Loading Parameters from a file:
    1. In <pkg>/config, create a <myconfig>.yaml file

      • Each key at the top level is the name of a node (or a wildcard pattern for a node name)
      • The next subkey is ros__parameters (note the double _)
      • Then the next keys are parameters and their values
      node_name_here:
         ros__parameters:
             param1: value
             pram2: value
      
    2. ros2 param load can load these files

      1. You must install the data by editing setup.py and adding it to data_files in setup.py

      3.In an xml launchfile use <param from="$(find-pkg-share pkgname)/installed/path/to/configfile>

  9. More information on how ROS handles .yaml files can be found in the rcl_yaml_param_parser library

Python Launchfiles

General Concepts

  • In ROS 2, launch was first implemented as a python API. Ultimately the XML and YAML launch files use this API.
  • python launchfiles are therefore the most feature-complete version of launch files
  • Overall, you should view python launch files as a template language for generating a description of what happens when ros2 launch <yourlaunchfile> is executed.
    • Theoretically (though not in actuality) you can view the description that you write in a python launchfile as generating a file that contains instructions for ros2 launch
  • Launchfile tutorials
  • Read the Launch API Documentation to gain a better understanding of how launch files work and the details of their API.
    • This documentation is for the launch package, which explains both the design and low-level launch API.
  • Comments in the Launch ROS source code is currently the best place to find API documentation for most of the ROS 2 Launch API calls you will actually use.
  • The launch package contains generic launchfile components for working with processes
  • The launch_ros package contains ros-specific launchfile components.

Theory of Launchfiles

  • Python launchfile programming is meant to be declarative rather than imperative.
    • What this means is that generally you should be declaring what will be happening when ros2 launch yourlaunchfile is called rather than directly executing the commands
  • Launchfiles are based on an object-oriented design pattern called the Visitor Pattern
    • Ultimately, a python launchfile returns a collection of objects (itself a LaunchDescription object) that describe what will happen during the launch
    • A program (like ros2 launch) can iterate over the LaunchDescription and perform various tasks, for example:
      • Return a list of arguments that the launchfile accepts
      • Return a list of nodes that the launchfile will run
      • Actually run the nodes
  • Any python code that is not inside the hierarchy of objects is imperative code that will execute immediately whenever ros2 launch loads the launchfile description.
    • This means that any actions taken are not tracked by the launch system and cannot be introspected or queried
    • Overall it is best to do as much as possible in the declarative style, as this opens everything up to launchfile introspection methods and also is less prone to bugs, however there are some things that can only be done in python and others (when launchfiles get more complicated) that can only be done in python.
    • See Which Should I Use python or xml or yaml?

Declarative Python Launchfiles

Here are some properties of purely declarative Python launchfiles. These launchfiles represent a subset of the potential functionality available in python but following these principles generally makes it easier to understand what a launchfile is doing (for experienced ROS users), enables the full power of ROS 2 introspection tools to be used on the Launchfile, and makes the launchfile more similar and translatable to XML.

  1. generate_launch_description consists of a single return statement returning a LaunchDescription object.
    • No variables are used.
  2. The only imports are to launch (and submodules) launch_ros (and submodules) and other python packages that implement launch objects (e.g., Actions, Substitutions, etc).
    • In particular, importing and using functionality from os, yaml, and other packages makes breaks declarative purity.
    • For example, you do not explicitly read a yaml file: instead you compute the path to the file using substitutions and pass that path to a Node action
  3. Substitution and Conditions are used rather than python control-flow (e.g., if, while) statements

There are cases where using imperative code makes a launchfile more clear: particularly if the goal is to provide generic functionality to multiple LaunchFiles. In many of these cases, such code could be converted into a custom Action or Substitution, which would then enhance the functionality of declarative launchfiles and also make that functionality available to XML and YAML launchfiles.

Description

  • launch.LaunchDescription is the object that describes what LaunchActions should be taken when running the Launchfile
  • All python launchfiles have a generate_launch_description() function that returns a launch.LaunchDescription Object
  • The LaunchDescription object takes a list of LaunchActions that should be executed by the launchfile
  • The launch.LaunchDescription object is roughly equivalent to the <launch> tag in an xml launchfile

Actions

  • When executing ros2 launch, all of the Actions listed in the LaunchDescription object returned by generate_launch_description() are executed
    • The launch_ros.actions.Node action causes a Node to run. Roughly corresponds to a <node> tag
      • When creating a launch_ros.actions.Node, parameters can be specified using the parameters keyword argument
      • Equivalent to the <node> tag in XML.
    • The launch.actions.DeclareLaunchArgument action causes the launchfile to look for an argument to be specified (optionally with a default value). Roughly corresponds to an <arg> tag
      • Equivalent to the <arg> tag in XML.
      • Always fill in the description to provide documentation for the argument
    • The launch.actions.IncludeLaunchDescription enables including one launchfile in another
      • This action includes a launchfile as described by a launch.LaunchDescriptionSource object or a string
      • Equivalent to the <include> tag in XML
      • There is also IncludePythonLaunchDescription. This is entirely unnecessary to use: IncludeLaunchDescription will load any launchfile regardless of type.
    • The launch.actions.ExecuteProcess enables running a (non-node) process in the launchfile
      • Equivalent to the <executable> tag in XML (ROS 2 only)
    • The launch.actions.RegisterEventHandler enables the launch file to respond to events (see Events)
      • There are not methods for handling events in XML or YAML launchfiles.
    • The launch.actions.EmitEvent enables the launch file to trigger an event
      • There are not methods for emitting events in XML or YAML launchfiles.

Substitutions

Conditions

  • Conditions allow branching during ros2 launch time
  • launch.conditions.IfCondition when passed as a condition keyword argument to certain actions (e.g., Node), the action will execute if the provided expression is True or 1 (roughly equivalent to the if="" attribute)
  • launch.conditions.UnlessCondition when passed as a condition keyword argument to certain actions, the action will execute if the provided expression is False or 0 (roughly equivalent to the unless="" attribute)
  • In ros2 rolling launch.substitutions.EqualsSubstitution allows testing conditions for equality by doing IfCondition(EqualsSubstitution(LaunchConfiguration("config"), "comparison"))

Events

  • Python Launchfiles provide access to certain events in the lifecycle of a node
  • Launchfiles can respond to events (via the RegisterEventHandler action)
  • Launchfiles can trigger events (via the EmitEvent action)
  • The launch.events.Shutdown event is emitted when the launch system is terminated
  • See the Event Handler Tutorial for details
  • To have a node terminate the whole launchfile when it exits: Set on_exit to the Shutdown() action.

Parameter Files

  • Parameter files can be created using launch_ros.parameter_descriptions.ParameterFile
    • These objects represent a yaml file and can be passed directly to the parameters keyword of the launch.action.Node
    • Setting the keyword argument allow_susbt to true lets you use substitution rules in the .yaml file.
      • For example $(var launchvar) will substitute the value of the variable in the launchfile

Best Practices

Launchfile best practices in ROS 2 are still up in the air, the only "official" guidance I've found is here: Which Launch Format to Use?. So here are some opinions:

  1. Prefer XML launch files in most cases
    • Closer to ROS 1 (so it will help you with ROS 1, which is still very much in use)
    • More declarative (that is no changing state) so it is easier to see what is going on and harder to make mistakes
    • Since ROS 2 Iron, we can do everything we do in this class with XML launchfiles
  2. Use python launch files either when
    • Features are not yet in XML launch files (such as storing the value of a command in a parameter)
    • You begin doing lots of logic substitutions and if attributes in XML and need more code-reuse and more complex actions
  3. In python launchfiles, stick to a declarative style unless what you are trying to accomplish would be impossible or significantly more cumbersome.
  4. Remember that python launchfiles can include XML launchfiles and vice versa
  5. Yaml launch files seem to be rare in practice. As far as I can tell it has no features that XML does not have, other than it's not XML (and yaml is typically used as an alternative to XML). It is mainly a syntactic stylistic preference between the two.

References

Author: Matthew Elwin.