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 you a method for having a single command start your robot. You can specify
    • Which nodes are run
    • What parameters they use
    • What topics are named
    • and more!
  • These Launchfile Tutorials will help get you started.

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.
  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. 6. 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
  5. Conditionals:
  6. 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
        • Single quotes must be escaped with a backslash (ROS 2 only).
      7. $(command '<expression>') runs a command and returns the output (ROS 2 only).
  7. 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>

  8. 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?

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.
    • The launch.actions.IncludeLaunchDescription enables including one launchfile in another
    • 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

  • Substitutions allow values that are computed during ros2 launch time to be used, inspected, and substituted when the launchfile is running.
  • Remember, when declaring the launchfile several values are not yet known:
    • Locations of package install directories.
    • Output of commands that are run.
    • The value of arguments specified by the user.
  • Roughly, substitutions are similar in use to the $() syntax in XML launch files.
  • A few useful substitutions are:
  • Substitutions can be concatenated by putting them all in a list (i.e., a list of substitutions is a substitution containing the concatenation of each element of the list)

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 as much as possible
    • generate_launch_description should ideally be a single return statement
    • No variables are used
    • Prefer substitution rules to python logic (for example FindPackageShare substitution rule rather than importing a function that finds the package share directory)
    • This declarative style makes it easier to see what the launchfile is doing (to experienced launchfile users) than needing to follow launchfile logic
    • The declarative style is also more directly translatable to an XML format, if the required features become available.
  4. Remember that python launchfiles can include XML launchfiles and vice versa
  5. I have yet to see a yaml launch file in the wild. 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).

References

Author: Matthew Elwin