See also rosetta_launch for a number of examples.
Python-based launch files all pretty much follow the same structure.
Note
Prior to Foxy, the parameters name, namespace, and executable were prefixed with node_
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
name='node_runtime_name',
package='ros2_package_name',
executable='name_of_executable',
parameters=[{'name_of_int_param': 1,
'name_of_str_param': 'value'}],
remappings=[('from', 'to')],
output='screen',
),
# More Nodes!
])
Normally, launch files are run with:
ros2 launch pkg launch.py
But, sometimes you want an executable launch file (for instance to put in a systemd job). Assuming you follow the default pattern shown above, all you need to add:
#!/usr/bin/env python3
import sys
from launch import LaunchService
# define generate_launch_description() as above
if __name__ == '__main__':
desc = generate_launch_description()
service = LaunchService(argv=sys.argv[1:])
service.include_launch_description(desc)
return service.run()
Some nodes have many parameters, it's easier to put them in a YAML file:
node_name:
ros__parameters:
some_int_param: 1
some_str_param: "the_value"
To load this:
from ament_index_python.packages import get_package_share_directory
# Assuming you have a file called package_name/config/params.yaml
node_params = os.path.join(
get_package_share_directory('package_name'),
'config',
'params.yaml'
)
# Add this to your LaunchDescription
Node(
name='node_runtime_name',
package='ros2_package_name',
executable='name_of_executable',
parameters=[{'another_param': 42.0},
node_params]
)
import os
from ament_index_python.packages import get_package_share_directory
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
# Assuming you have a file called package_name/launch/my_launch.launch.py
my_launch_file = os.path.join(
get_package_share_directory('package_name'),
'launch',
'my_launch.launch.py'
)
# Add this to your LaunchDescription
IncludeLaunchDescription(
PythonLaunchDescriptionSource([my_launch_file])
),
Most robots need to load their URDF into the robot_state_publisher, and maybe other nodes as well:
import os
from ament_index_python.packages import get_package_share_directory
from launch_ros.actions import Node
# Load the URDF into a parameter
desc_dir = get_package_share_directory('robot_description_pkg')
urdf_path = os.path.join(desc_dir, 'robots', 'my_urdf.urdf')
urdf = open(urdf_path).read()
# Add this to your LaunchDescription
Node(
name='robot_state_publisher',
package='robot_state_publisher',
executable='robot_state_publisher',
parameters=[{'robot_description': urdf}],
)
If you are using a computer with a graphical system, it's pretty easy to have gdb launch in a new terminal, by adding the following:
Node(
# Configure the node as above
# Add a prefix so the node is started in GDB in a new xterm
prefix=['xterm -e gdb --args'],
)
However, many robots lack a graphical system. In this case, you can launch GDB in a server configuration:
Node(
# Configure the node as above
# Add a prefix so the node is started in a gdbserver
prefix=['gdbserver localhost:2345'],
)
Then, in a separate terminal you can connect to the target, and start
the node by running continue
:
$> gdb
(gdb) target remote localhost:2345
(gdb) continue