Welcome to ROSMASTER A1 repository
19.ROS2 Launch startup file configuration
19. ROS2 Launch startup file configuration
1. Introduction to Launch
Until now, every time we launched a ROS node, we had to open a new terminal and run a command. With so many nodes in a robotic system, doing this every time is cumbersome. Is there a way to launch all nodes at once? The answer is, of course, a launch file, a script that launches and configures multiple nodes in the ROS system.
In ROS2, launch is used to launch multiple nodes and configure program parameters. ROS2 launch files are available in XML, YAML, and Python formats. This lesson uses a Python launch file as an example. Compared to the other two formats, the Python format is more flexible:
- Python has numerous function libraries that can be used in launch files;
- ROS2 general and specific launch features are written in Python, allowing access to launch features that may not be exposed in XML and YAML;
The key to writing ROS2 launch files in Python is to abstract each node, file, script, etc. into an action, launching them using a unified interface.
References:
- Launch System Design Document: ROS 2 Launch System
- Official Launch API Documentation: Architecture of launch — launch 0.4.0 documentation
- Preparation: Create a package to store program files
xxxxxxxxxxros2 pkg create learn_launch --build-type ament_python2. Writing a Single Node Launch Program
2.1. Creating a Launch File
Create a launch folder under the package, then create a file called [single_node_launch.py] within the launch folder. Copy the following content into the file:
xxxxxxxxxxfrom launch import LaunchDescriptionfrom launch_ros.actions import Nodedef generate_launch_description(): node = Node( package='pkg_helloworld_py', executable='helloworld', output='screen' ) return LaunchDescription([node])
2.2 Configuring the setup.py File
The launch file is often named "LaunchName_launch.py." LaunchName is customizable, while _launch.py is considered fixed. You need to modify the setup.py file in the package to add the files in the launch path and compile to generate the executable .py file.
xxxxxxxxxx#1. Import related header filesimport osfrom glob import glob#2. In the data_files list, add the launch path and the launch.py ••file under the path(os.path.join('share',package_name,'launch'),glob(os.path.join('launch','*launch.py')))
2.3. Compile the package
xxxxxxxxxxcolcon build --packages-select learn_launch
2.4. Run the program
- Refresh the environment variables and run the launch file
xxxxxxxxxxros2 launch learn_launch single_node_launch.py
2.5. Source Code Analysis
- Import related libraries
xxxxxxxxxxfrom launch import LaunchDescriptionfrom launch_ros.actions import Node
- Define a function called generate_launch_description and return a launch_description.
xxxxxxxxxxdef generate_launch_description(): node = Node( package='pkg_helloworld_py', executable='helloworld', ) return LaunchDescription([node])We define a variable called node as the return value of a node startup. We then call the Node function with two important parameters: package and executable.
- package: represents the package name.
- executable: represents the executable program name.
Finally, we call the LaunchDescription function, passing in the node parameter, and execute the function.
xxxxxxxxxxreturn LaunchDescription([node])
3. Writing a Launch Program for Multiple Nodes
3.1. Creating a Launch File
Create a new file called [multi_node_launch.py] and add the following content:
xxxxxxxxxxfrom launch import LaunchDescriptionfrom launch_ros.actions import Nodedef generate_launch_description(): publisher_node = Node( package='pkg_topic', executable='publisher_demo', output='screen' ) subscriber_node = Node( package='pkg_topic', executable='subscriber_demo', output='screen' ) return LaunchDescription([ publisher_node, subscriber_node ])
3.2. Compile the package
xxxxxxxxxxcolcon build --packages-select learn_launch
3.3. Run the program
- Refresh the environment variables and run the launch file.
xxxxxxxxxxros2 launch learn_launch multi_node_launch.py

If the terminal does not print anything, we can verify that the nodes have started successfully by checking which nodes have started. In the terminal, enter:
xxxxxxxxxxros2 node list

3.4 Source Code Analysis
Similar to simple_node_launch.py, except for one more node.
4 Topic Remapping Example
4.1 Creating a New Launch File
Create a new file called [remap_name_launch.py] in the same directory as multi_node_launch.py and add the following content:
xxxxxxxxxxfrom launch import LaunchDescriptionfrom launch_ros.actions import Nodedef generate_launch_description(): publisher_node = Node( package='pkg_topic', executable='publisher_demo', output='screen', remappings=[("/topic_demo", "/topic_update")] ) return LaunchDescription([ publisher_node ])
4.2. Compile the package
xxxxxxxxxxcolcon build --packages-select learn_launch
4.3. Run the program
Let's first see what topics the publisher_demo node publishes before remapping topics:
xxxxxxxxxxros2 launch learn_launch multi_node_launch.pyros2 topic list

The topic here is [/topic_demo]
- Refresh the environment variables again and run the program after remapping the topic to see the changes:
xxxxxxxxxxros2 launch learn_launch remap_name_launch.pyros2 topic list
As shown above, the topic name has been remapped to [/topic_update]
4.4 Source Code Analysis
The following sections have been added:
xxxxxxxxxxremappings=[("/topic_demo", "/topic_update")]
Here, the original /topic_demo topic is remapped to /topic_update
5. Example of Launching Another Launch File from a Nested Launch File
5.1. Creating a New Launch File
Create a new file, [include_launch.py], in the same directory as multi_node_launch.py and add the following content:
xxxxxxxxxxfrom launch import LaunchDescriptionfrom launch_ros.actions import Node import osfrom launch.actions import IncludeLaunchDescriptionfrom launch.launch_description_sources import PythonLaunchDescriptionSourcefrom ament_index_python.packages import get_package_share_directorydef generate_launch_description(): hello_launch = IncludeLaunchDescription(PythonLaunchDescriptionSource( [os.path.join(get_package_share_directory('learn_launch'), 'launch'), '/multi_node_launch.py']), ) return LaunchDescription([ hello_launch ])
5.2. Compiling the Function Package
xxxxxxxxxxcolcon build --packages-select learn_launch
5.3. Running the Program
- Refresh the environment variables and run the launch file
xxxxxxxxxxros2 launch learn_launch include_launch.py

5.4. Source Code Analysis
- Nested launch files require the use of the launch system's IncludeLaunchDescription and PythonLaunchDescriptionSource classes.
- os.path.join(get_package_share_directory('learn_launch')): Gets the package location, where 'learn_launch' is the package name;
- launch): Specifies the folder where the launch file is stored within the package;
- /multi_node_launch.py: Specifies the /multi_node_launch.py file within the launch folder of the package.
6. Comprehensive Launch File Example
This example primarily demonstrates how to write a complex launch file; the program's functionality is ignored.
6.1. Creating a New Launch File
Create a new file, [complex_launch.py], in the same directory as [multi_node_launch.py] and add the following content:
xxxxxxxxxximport osfrom ament_index_python import get_package_share_directoryfrom launch import LaunchDescriptionfrom launch.actions import DeclareLaunchArgumentfrom launch.actions import IncludeLaunchDescriptionfrom launch.actions import GroupActionfrom launch.launch_description_sources import PythonLaunchDescriptionSourcefrom launch.substitutions import LaunchConfigurationfrom launch.substitutions import TextSubstitutionfrom launch_ros.actions import Nodefrom launch_ros.actions import PushRosNamespacedef generate_launch_description(): # args that can be set from the command line or a default will be used background_r_launch_arg = DeclareLaunchArgument( "background_r", default_value=TextSubstitution(text="0") ) background_g_launch_arg = DeclareLaunchArgument( "background_g", default_value=TextSubstitution(text="255") ) background_b_launch_arg = DeclareLaunchArgument( "background_b", default_value=TextSubstitution(text="0") ) chatter_ns_launch_arg = DeclareLaunchArgument( "chatter_ns", default_value=TextSubstitution(text="my/chatter/ns") ) # include another launch file launch_include = IncludeLaunchDescription( PythonLaunchDescriptionSource( os.path.join( get_package_share_directory('demo_nodes_cpp'), 'launch/topics/talker_listener.launch.py')) ) # include another launch file in the chatter_ns namespace launch_include_with_namespace = GroupAction( actions=[ # push-ros-namespace to set namespace of included nodes PushRosNamespace(LaunchConfiguration('chatter_ns')), IncludeLaunchDescription( PythonLaunchDescriptionSource( os.path.join( get_package_share_directory('demo_nodes_cpp'), 'launch/topics/talker_listener.launch.py')) ), ] ) # start a turtlesim_node in the turtlesim1 namespace turtlesim_node = Node( package='turtlesim', namespace='turtlesim1', executable='turtlesim_node', name='sim' ) # start another turtlesim_node in the turtlesim2 namespace # and use args to set parameters turtlesim_node_with_parameters = Node( package='turtlesim', namespace='turtlesim2', executable='turtlesim_node', name='sim', parameters=[{ "background_r": LaunchConfiguration('background_r'), "background_g": LaunchConfiguration('background_g'), "background_b": LaunchConfiguration('background_b'), }] ) # perform remap so both turtles listen to the same command topic forward_turtlesim_commands_to_second_turtlesim_node = Node( package='turtlesim', executable='mimic', name='mimic', remappings=[ ('/input/pose', '/turtlesim1/turtle1/pose'), ('/output/cmd_vel', '/turtlesim2/turtle1/cmd_vel'), ] ) return LaunchDescription([ background_r_launch_arg, background_g_launch_arg, background_b_launch_arg, chatter_ns_launch_arg, launch_include, launch_include_with_namespace, turtlesim_node, turtlesim_node_with_parameters, forward_turtlesim_commands_to_second_turtlesim_node, ])
6.2. Compile the Workspace
xxxxxxxxxxcolcon build --packages-select learn_launch
6.3. Run the Program
- Refresh the environment variables in the terminal and run the launch file.
xxxxxxxxxxros2 launch learn_launch complex_launch.py