CSCE 452/752 Robotics and Spatial Intelligence, Fall 2025

Notes on ROS2 launch files

This document contains a quick overview of the concept of launch files in ROS2 along with some of the specifics for certain things that may be less clear from the documentation. More details are in the official documentation.
The main idea of these kinds of files is to describe how to start a complex ROS system consisting of multiple nodes. This is important because, as we discussed, one of the main advantages of ROS is that we can compose complex systems from collections of small nodes that communicate by passing messages. You could start each of these nodes individually in separate terminals, but that approach becomes more tedious and more error-prone as the complexity increases. By creating a launch file, you can use a single command to start all of the nodes needed to make your system work.
An important note: The ROS2 documentation describes three related kinds of launch files: a Python format, an XML format, and a YAML format. These three formats conceptually similar to each other. All three tend to be a bit wordy and syntax-heavy. However, the Python format is, in principle, more powerful, since the launch file is in fact just a Python program, which means it can do anything a real program can. So, if you are getting started with launch files, my recommendation is to use the Python format.
Given that context, here are the basic steps to create a launch file that starts one or more nodes that you've created.
  1. First, you should be sure that your programs are part of a fully-formed ROS package. This is necessary because the most direct way to use the launch system is it specify which nodes to run based on the package that contains them.
    As a refresher, you may want to consult the notes on creating ROS2 packages. You should finish the usual package creation and package configuration steps before moving on to the process of creating the launch file itself.
  2. Now that you have a package created, you can add a launch file to the package. The recommended place for launch files is a subdirectory called
    launch
    within the package
    src
    directory. Here's an example launch file name:
    ros_ws/src/package_name/launch/launch.py
          
    This should be a (usually short) Python module containing a function called
    generate_launch_description
    which returns an object of type
    LaunchDescription
    .
    Here's a very simple example that launches one node:
    from launch import LaunchDescription
    from launch_ros.actions import *
    
    def generate_launch_description():
        node = Node(package='turtlesim',
                    executable='turtlesim_node')
        ld = LaunchDescription([ node ])
        return ld
          
    The basic ideas are:
    • Create a
      Node
      object describing the node you want to launch, specifying the package name and the executable within that package. (Note that this
      Node
      class is different from the similarly-named class that you use within your
      rclpy
      ROS client programs.)
    • Create a
      LaunchDescription
      object, passing a list of “actions” that should be executed. Nodes are the most common type of action. There are also other types of actions, some of which we'll discuss below.
    • Return the
      LaunchDescription
      object.
  3. Next, you need to configure the package to include the launch files when you build. To do this, you should mention your launch directory in the
    data_files
    section of your package's
    setup.py
    .
    Here's an example, showing one option for the line that you need to add:
    data_files=[
        ('share/ament_index/resource_index/packages', ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
        ('share/' + package_name, glob.glob('launch/*'))
    ],
          
    You may also need to add this line near the top of
    setup.py
    :
    import glob
          
    These changes are meant to ensure that when you run
    colcon build
    , your launch files are included the built package.
  4. To use this launch file, be sure to rebuild your package and then use the
    ros2 launch
    command. Here's an example:
    ros2 launch package_name launch.py
          
  5. Finally, you may be interested in a few additional wrinkles in your launch file.
    1. Launch files can have launch arguments. Each launch argument is a nugget of additional information, provided on the
      ros2 launch
      command line, that is used to configure or modify the behavior of the launch file or the nodes it launches.
      To provide values to launch arguments on the command line, use
      :=
      , like this:
      ros2 launch package_name launch_file_name.py arg_name:=arg_value
              
      Within the launch file itself, launch arguments are actions just like the
      Node
      actions we've already seen. You can create a launch argument using a
      DeclareLaunchArgument
      object:
      arg = DeclareLaunchArgument('arg_name')
              
      Then include this object in the list of actions when you create the
      LaunchDescription
      . For example, if you have one argument and one node, you might use something like this:
      ld = LaunchDescription([ arg, node ])
              
      To access the specific value assigned to this argument, you can use a
      Launch Configuration
      object, in places where you might otherwise use a hard coded value:
      LaunchConfiguration('arg_name')
              
      This
      LaunchConfiguration
      is technically an object called a substitution within the launch system, so you'll need a import like this to access it:
      from launch.substitution import *
              
    2. In some cases, you'll want your launch file to run commands that don't fit exactly within the mold required for
      Node
      actions. That is, things for which you cannot specific a package name and an executable within that package. For example, this is the case if you want to include
      ros2 bag play
      or
      ros2 bag record
      in your launch file.
      In these kinds of cases, you can use an
      ExecuteProcess
      action instead of a
      Node
      . Here's an example that plays a hard coded bag file:
      ep = ExecuteProcess(cmd=['ros2', 'bag', 'play', 'bags/example1'])
              
      The
      cmd
      argument here is just a list of the arguments you'd supply on the command line for the command you'd like to run, Then you would include this action in the list of actions when you create your
      LaunchDescription
      .
    3. One last thing: You may want your launch file to stop the entire system when the playback of the original bag file has completed. This requires us to create an event handler and attach that event handler to an action in our launch description.
      First, import modules both for the definitions of various events and for handlers that respond to those events:
      from launch.event_handlers import *
      from launch.events import *
              
      Then, within the main code of the launch file, create an event handler:
      event_handler = OnProcessExit(target_action=your_action,
                                    on_exit=[EmitEvent(event=Shutdown())])
              
      In this example, we are creating an event handler that waits for
      your_action
      to complete, and responds by initiating an overall shutdown when that occurs.
      Then construct an action from that event handler:
      terminate_at_end = RegisterEventHandler(event_handler)
              
      Be sure to include this action in the action list that you supply to the constructor of your
      LaunchDescription
      .