示例1

#!/usr/bin/env python3
# 导入launch基础模块
import launch
# 导入ros相关节点动作模块
import launch_ros

def generate_launch_description():
    """launch入口函数,固定函数名,ros2 launch自动调用"""
    # 声明启动参数:参数名 launch_max_speed,默认值'2.0'
    # DeclareLaunchArgument:定义外部可传入的launch启动参数
    action_declare_arg_max_spped = launch.actions.DeclareLaunchArgument(
        'launch_max_speed', 
        default_value='2.0'
    )

    # 启动第一个ROS节点 turtle_control
    action_node_turtle_control = launch_ros.actions.Node(
        package='demo_cpp_service',       # 包名,节点属于哪个ros2包
        executable="turtle_control",      # 可执行程序名(编译生成的程序)
        output='screen',                  # 日志输出:screen打印到终端
        # 给节点传参数,读取上面声明的launch参数 launch_max_speed
        parameters=[
            {
                'max_speed': launch.substitutions.LaunchConfiguration('launch_max_speed', default='2.0')
            }
        ],
    )

    # 启动第二个ROS节点 patrol_client
    action_node_patrol_client = launch_ros.actions.Node(
        package='demo_cpp_service',
        executable="patrol_client",
        output='log',   # log:日志写入日志文件,不在终端打印
    )

    # 启动第三个ROS节点 turtlesim_node(小乌龟仿真)
    action_node_turtlesim_node = launch_ros.actions.Node(
        package='turtlesim',
        executable='turtlesim_node',
        output='both',  # both:同时输出到终端 + 日志文件
    )

    # ========= LaunchDescription =========
    # LaunchDescription:启动描述对象,把所有动作(声明参数、启动节点)放到列表
    # 里面填写需要执行的所有动作,ros2 launch会按列表顺序依次执行
    launch_description = launch.LaunchDescription([
        action_declare_arg_max_spped,
        action_node_turtle_control,
        action_node_patrol_client,
        action_node_turtlesim_node
    ])

    # 返回启动描述对象,框架拿到对象后执行里面所有动作
    return launch_description

一、launch.LaunchDescription

作用:管理一组启动动作的容器。

  • 接收一个列表,列表内放各种 action(声明参数、启动节点、include 其他 launch、定时器等)
  • ros2 launch加载这个文件后,会自动执行generate_launch_description(),拿到这个对象,然后按列表顺序执行里面所有动作
  • 可以放不止 Node,还可以放:DeclareLaunchArgument、IncludeLaunchDescription、LogInfo等

一句话:LaunchDescription = 任务清单,清单里写好要做哪些事情

二、launch_ros.actions.Node

作用:用来启动一个 ROS2 节点,是 launch 里最常用的动作。

常用参数说明

launch_ros.actions.Node(
    package="包名",                 # 必须,节点所在的ROS2包
    executable="可执行文件名",       # 必须,编译出来的程序名字
    name="自定义节点名称",           # 可选,覆盖节点内部的node名字,用于重命名
    output="screen/log/both/none",  # 日志输出方式
    parameters=[{}],                # 传入节点参数,字典形式
    arguments=[],                   # 命令行参数
    remappings=[("/old_topic","/new_topic")] # 话题重映射
)

output 4 种取值:

1. `screen`:日志打印到终端(调试最常用)
2. `log`:只保存到日志文件,终端不显示
3. `both`:终端打印 + 写入日志文件
4. `none`:不输出日志

运行方法

ros2 launch demo_cpp_service xxx.launch.py launch_max_speed:=5.0

示例2

#!/usr/bin/env python3
# 导入launch基础库
import launch
# 导入ROS相关launch动作库
import launch_ros
# 工具函数:获取功能包share目录路径
from ament_index_python.packages import get_package_share_directory

def generate_launch_description():
    """
    ROS2 launch 固定入口函数,ros2 launch命令会自动调用这个函数
    返回LaunchDescription对象,里面存放所有要执行的动作
    """
    # 声明启动参数 startup_rqt,默认值'False'
    # DeclareLaunchArgument:定义可以从终端传入的启动参数
    action_declare_startup_rqt = launch.actions.DeclareLaunchArgument('startup_rqt', default_value='False')
    # LaunchConfiguration:读取上面定义的启动参数,作为launch内部变量
    startup_rqt = launch.substitutions.LaunchConfiguration('startup_rqt')

    # ========== 动作1:引入其他launch文件 ==========
    # get_package_share_directory('turtlesim') 获取turtlesim包的share目录绝对路径
    # 拼接路径: 包路径 + /launch/ + multisim.launch.py
    multisim_launch_path = [get_package_share_directory('turtlesim'), '/launch/','multisim.launch.py']
    # IncludeLaunchDescription:用来嵌套、包含并执行另一个launch文件
    action_include_launch = launch.actions.IncludeLaunchDescription(
        # PythonLaunchDescriptionSource:指定被包含的是python类型launch文件
        launch.launch_description_sources.PythonLaunchDescriptionSource(
            multisim_launch_path
        )
    )

    # ========== 动作2:终端打印日志信息 ==========
    # LogInfo:launch运行时在终端打印消息,调试launch脚本很有用
    action_log_info = launch.actions.LogInfo(msg=str(multisim_launch_path))

    # ========== 动作3:执行外部进程(命令行程序) ==========
    # ExecuteProcess:执行任意终端命令,这里执行 rqt
    action_topic_list = launch.actions.ExecuteProcess(
        # IfCondition:条件判断,只有 startup_rqt == True 才执行这个动作
        condition=launch.conditions.IfCondition(startup_rqt),
        cmd=['rqt'],
    )

    # ========== 动作4:GroupAction 动作组 ==========
    # GroupAction:把一堆动作打包成一组,可以统一加条件、命名空间
    action_group = launch.actions.GroupAction([
        # 动作5:TimerAction 定时器动作,延迟period秒后执行里面的actions
        # 延迟2秒,再执行action_include_launch(加载multisim.launch.py)
        launch.actions.TimerAction(period=2.0, actions=[action_include_launch]),
        # 延迟2秒,执行action_topic_list(启动rqt,受startup_rqt条件控制)
        launch.actions.TimerAction(period=2.0, actions=[action_topic_list]),
    ])

    # LaunchDescription:动作容器,列表内放入所有顶层动作,按顺序处理
    return launch.LaunchDescription([
        action_declare_startup_rqt,
        action_log_info,
        action_group
    ])

1. get_package_share_directory('包名')

作用:获取功能包 share 文件夹的绝对路径
ROS2 所有资源(launch、urdf、yaml)都放在包的share目录。

不用手写绝对路径,移植到别的电脑也能正常找到文件。

示例

get_package_share_directory("turtlesim")

2. launch.actions.DeclareLaunchArgument

作用:声明外部启动参数,让用户在终端传参

  • 定义参数名 + 默认值
  • 搭配LaunchConfiguration读取参数值
action_declare_startup_rqt = launch.actions.DeclareLaunchArgument('startup_rqt', default_value='False')

终端可以覆盖:xxx.launch.py startup_rqt:=True

3. launch.substitutions.LaunchConfiguration('参数名')

读取上面 DeclareLaunchArgument 定义的参数,只能在 launch 脚本构建阶段使用,用来做条件判断、传参。

4. launch.actions.IncludeLaunchDescription

嵌套调用其他 launch 文件,模块化开发。
比如把机器人模型、Gazebo 分开写多个 launch,主 launch 统一引入。
PythonLaunchDescriptionSource 指定是 python 格式的 launch 文件。

5. launch.actions.LogInfo(msg="xxx")

打印信息到终端,launch 脚本调试神器,查看变量、路径是否正确。

6. launch.actions.ExecuteProcess

执行任意系统命令,相当于在终端敲命令

  • cmd=[命令,参数]
  • condition:条件,满足才执行
    示例这里 cmd=['rqt'],就是执行rqt打开 rqt 工具

7. launch.conditions.IfCondition(变量)

条件动作:条件为 True 才执行这个动作

本例:只有startup_rqt:=True时,才启动 rqt

8. launch.actions.TimerAction(period=秒数, actions=[...])

延迟启动动作
period=2.0:等待 2 秒后,再执行里面的动作列表。

适用场景:先等 gazebo / 模型加载完成,再启动控制器、rqt 等,防止时序问题。

9. launch.actions.GroupAction([动作列表])

动作打包分组
把多个动作放到一组。
可以整组加条件、统一设置命名空间 (namespace)。本例只是单纯把两个定时器打包在一起。

10. launch.LaunchDescription([动作列表])

顶层容器,所有顶层动作放列表里,ros2 launch 会依次处理。

调用方式

假设这个文件名字叫 group_demo.launch.py,放在 demo 包的 launch 文件夹

方式 1:默认参数(不启动 rqt)
colcon build 
source install/setup.bash
ros2 launch demo_cpp_service group_demo.launch.py
方式 2:传参 startup_rqt:=True,启动时自动打开 rqt
ros2 launch demo_cpp_service group_demo.launch.py startup_rqt:=True

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐