Launchfiles
Launchfiles and ROS
- ROS programs consist of many nodes communicating over topics and services
- For non-trivial programs, manually running nodes using
ros2 runbecomes 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
- As of 10/2025 the API Documentation for jazzy launch files is not fully populated
- The kilted documentation is not posted at all
- For the best documentation, build it locally
- Clone https://github.com/ros2/launch
- Run
rosdoc2 build --package-path launch/launch(installpython3-rosdoc2) - Open
doc_output/launch/index.htmlin your browser - The API documentation for this also provides
xmlequivalents
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:
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)
- Here, the launch file must be installed into the install space (e.g., by setting up
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:=valuesyntax.
Ros2 launch options
- Use
ros2 launch --helpfor a complete list of the options. -sor--show-argThis flag shows all the possible arguments provided by the launchfile and their documentation.--debugshows debugging information, which is useful if the launchfile is not working.
XML Launchfiles
- 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 full
launchAPI documentation also has XML examples for each piece of the launchfile. - 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
Nodelaunch action oflaunch_rosuses theExecuteProcesslaunch action oflaunch.
- For example, the
- 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
- Launchfiles should be installed by adding them to the
data_filessection ofsetup.py.- Install the files to
share/package_name/launch.
- Install the files to
- Projects that use launchfiles should add
ros2launchas an<exec_depend>inpackage.xml(becauseros2 launchis required to use them). - Launchfiles list nodes to be launched; however, the order in which they start is non-deterministic.
- 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.
- In ROS 2 the
- <group> - Groups nodes together and allows you to easily apply common settings
- To put all nodes within a
groupin the same namespace use the <push_ros_namespace namespace="ns"> tag
- To put all nodes within a
- <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
descriptionattribute (calleddocin ROS 1).
- You should always provide documentation for Launchfile arguments using the
- <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
- Conditionals:
- Conditional Attributes All elements have attributes
ifandunlessto be conditionally included.
- Conditional Attributes All elements have attributes
- 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:
$(env ENVIRONMENT_VARIABLE)Expands into the value of the environment variable or is an error if that variable is not set.$(env ENVIRONMENT_VARIABLE default)Expands into the value of an environment variable ordefaultif it is not set. (In ROS 1 this was$(optenv))$(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$(find-pkg-prefix)$expands$(var myarg)expands into the value ofmyarg, as specified by an<arg>element and passed in on the call toroslaunch$(eval <expression>)Runs python code<expression>and expands to the result of the code evaluation- This does not behave exactly like the ROS 1 version:
<expression>should be a single-quoted string- If the expression itself uses single-quotes, those need to be escaped (e.g., 'mystring' becomes \'mystring\')
- 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 ofargname
- This does not behave exactly like the ROS 1 version:
$(command '<expression>')runs a command and returns the output (ROS 2 only).
- Loading Parameters from a file:
In
<pkg>/config, create a<myconfig>.yamlfile- 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: valueros2 param loadcan load these files- You must install the data by editing
setup.pyand adding it todata_filesinsetup.py
3.In an xml launchfile use
<param from="$(find-pkg-share pkgname)/installed/path/to/configfile>- You must install the data by editing
- More information on how ROS handles
.yamlfiles can be found in the rcl_yaml_param_parser library
Python Launchfiles
General Concepts
- In ROS 2,
launchwas first implemented as a python API. Ultimately the XML and YAML launch files use this API. pythonlaunchfiles 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
pythonlaunchfile as generating a file that contains instructions forros2 launch
- Theoretically (though not in actuality) you can view the description that you write in a
- 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
launchpackage, which explains both the design and low-level launch API.
- This documentation is for the
- 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
launchpackage contains generic launchfile components for working with processes - The
launch_rospackage 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 yourlaunchfileis called rather than directly executing the commands
- What this means is that generally you should be declaring what will be happening when
- 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 launchloads 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.
generate_launch_descriptionconsists of a single return statement returning aLaunchDescriptionobject.- No variables are used.
- 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
yamlfile: instead you compute the path to the file using substitutions and pass that path to a Node action
- In particular, importing and using functionality from
- 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.LaunchDescriptionis the object that describes what LaunchActions should be taken when running the Launchfile- All python launchfiles have a
generate_launch_description()function that returns alaunch.LaunchDescriptionObject - The
LaunchDescriptionobject takes a list of LaunchActions that should be executed by the launchfile - The
launch.LaunchDescriptionobject is roughly equivalent to the<launch>tag in anxmllaunchfile
Actions
- When executing
ros2 launch, all of the Actions listed in theLaunchDescriptionobject returned bygenerate_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 theparameterskeyword argument - Equivalent to the
<node>tag in XML.
- When creating a
- 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
descriptionto provide documentation for the argument
- Equivalent to the
- 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:IncludeLaunchDescriptionwill load anylaunchfileregardless 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)
- Equivalent to the
- 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.
- The launch_ros.actions.Node action causes a Node to run. Roughly corresponds to a
Substitutions
- Substitutions allow values that are computed during
ros2 launchtime to be used, inspected, and substituted when thelaunchfileis 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:
- launch.substitutions.LaunchConfiguration accesses the value of a DeclareLaunchArgument. Roughly equivalent to
$(var Varname)in xml - launch_ros.substitutions.FindPackageShare locates the packages
share/directory in the install space. Roughly equivalent to$(find-pkg-share package)in xml - launch_ros.substitutions.ExecutableInPackage locates an executable file within a package. Roughly equivalent to
$(exec-in-pkg package exec)in xml - launch.substitutions.PathJoinSubstitution concatenates paths (accounting for differences between platforms)
- launch.substitutions.TextSubstitution wraps a string in the substitution system (see Why substitutions?)
- launch.substitutions.IfElseSubstitution conditionally expands to text depending on a condition.
- launch.substitutions.TextSubstitution wraps a string in the substitution system (see Why substitutions?)
- launch.substitutions.Command runs a command (e.g.,
xacro) and substitutes in the output of the command. Roughly equivalent to$(command cmd)in xml.
- launch.substitutions.LaunchConfiguration accesses the value of a DeclareLaunchArgument. Roughly equivalent to
- 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 launchtime - launch.conditions.IfCondition when passed as a
conditionkeyword argument to certain actions (e.g., Node), the action will execute if the provided expression is True or 1 (roughly equivalent to theif=""attribute) - launch.conditions.UnlessCondition when passed as a
conditionkeyword argument to certain actions, the action will execute if the provided expression is False or 0 (roughly equivalent to theunless=""attribute) - In ros2 rolling launch.substitutions.EqualsSubstitution allows testing conditions for equality by doing
IfCondition(EqualsSubstitution(LaunchConfiguration("config"), "comparison"))- In humble or earlier, use the deprecated launch.conditions.LaunchConfigurationEquals instead of
IfCondition(EqualsSubstitution(LaunchConfiguration("config"), "comparison"))
- In humble or earlier, use the deprecated launch.conditions.LaunchConfigurationEquals instead of
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_exitto theShutdown()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
parameterskeyword of thelaunch.action.Node - Setting the keyword argument
allow_susbtto true lets you use substitution rules in the.yamlfile.- For example
$(var launchvar)will substitute the value of the variable in the launchfile
- For example
- These objects represent a yaml file and can be passed directly to the
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:
- 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
- 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
ifattributes in XML and need more code-reuse and more complex actions
- In python launchfiles, stick to a declarative style unless what you are trying to accomplish would be impossible or significantly more cumbersome.
- Remember that python launchfiles can include XML launchfiles and vice versa
- 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
- ROS 2 Launchfile Tutorials
- Migrating from ROS1
- Contains useful information about ROS 2 Launchfiles that I have not found elsewhere.
- Launchfile XML Specification