| name | ros2-launch-advanced |
| description | ROS2 Launch 进阶技能 - Python Launch、多 launch 嵌套、事件处理、条件启动、参数替换 |
| user-invocable | true |
| argument-hint | launch 文件 OR launch advanced OR python launch OR 事件处理 OR 条件启动 |
ROS2 Launch Advanced Skill
Python Launch 文件和高级启动模式完整指南
何时使用
当需要以下帮助时使用此技能:
- Python 高级 Launch 文件
- 多个 Launch 文件嵌套
- 事件驱动的启动逻辑
- 条件启动和参数替换
- Launch 文件参数化
快速参考
Launch 文件结构
launch/
├── my_launch.launch.py # 主 Launch
├── bringup.launch.py # 启动入口
├── params/
│ ├── robot.yaml # 参数文件
│ └── sensors.yaml
└── nodes/
├── camera.launch.py # 子 Launch
└── navigation.launch.py
Launch 文件格式
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
def generate_launch_description():
return LaunchDescription([
])
高级 Launch 特性
Launch 参数声明
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node
def generate_launch_description():
robot_model = DeclareLaunchArgument(
'robot_model',
default_value='robot_s',
description='Robot model name'
)
speed = DeclareLaunchArgument(
'speed',
default_value='1.0',
description='Max speed'
)
use_sim = DeclareLaunchArgument(
'use_sim',
default_value='true',
description='Use simulation'
)
robot_node = Node(
package='robot_control',
executable='robot_node',
name='robot_node',
parameters=[{
'robot_model': LaunchConfiguration('robot_model'),
'speed': LaunchConfiguration('speed'),
'use_sim': LaunchConfiguration('use_sim'),
}]
)
return LaunchDescription([
robot_model, speed, use_sim,
robot_node
])
参数替换
from launch.substitutions import TextSubstitution, PythonExpression
speed_factor = LaunchConfiguration('speed_factor')
computed_rate = PythonExpression(
['10.0 / ', LaunchConfiguration('speed_factor')]
)
config_path = TextSubstitution(
text=os.path.join(pkg_dir, 'config', LaunchConfiguration('config_file'))
)
条件启动
if 条件
from launch.actions import DeclareLaunchArgument
from launch.conditions import IfCondition
def generate_launch_description():
use_camera = DeclareLaunchArgument(
'use_camera',
default_value='true',
description='Enable camera'
)
camera_node = Node(
package='camera_driver',
executable='camera_node',
condition=IfCondition(LaunchConfiguration('use_camera'))
)
return LaunchDescription([use_camera, camera_node])
unless 条件
from launch.conditions import UnlessCondition
real_hw_node = Node(
package='hardware_driver',
executable='hw_node',
condition=UnlessCondition(LaunchConfiguration('use_sim'))
)
多条件分支
from launch.actions import OpaqueFunction
def launch_mode(context, *args,
mode = LaunchConfiguration('mode').perform(context)
if mode == 'navigation':
return [navigation_nodes()]
elif mode == 'mapping':
return [mapping_nodes()]
else:
return [default_nodes()]
return LaunchDescription([
DeclareLaunchArgument('mode', default_value='navigation'),
OpaqueFunction(function=launch_mode),
])
事件处理
事件动作
from launch.events import OnProcessStart, OnProcessExit, OnShutdown
from launch.actions import RegisterEventHandler, EmitEvent
on_start = RegisterEventHandler(
OnProcessStart(
target_action=robot_node,
on_start=[EmitEvent(event=some_event)]
)
)
on_exit = RegisterEventHandler(
OnProcessExit(
target_action=robot_node,
on_exit=[log_exit]
)
)
on_shutdown = RegisterEventHandler(
OnShutdown(
on_shutdown=[cleanup_action]
)
)
状态转换事件
from launch_ros.events.lifecycle import ChangeState, StateTransition
lifecycle_change = RegisterEventHandler(
ChangeState(
lifecycle_node_matcher=lambda node: node.name == 'managed_node',
transition=TransitionTransition(
start_state='inactive',
goal_state='active'
)
)
)
嵌套 Launch
包含子 Launch
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
robot_bringup = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(pkg_dir, 'launch', 'bringup.launch.py')
),
launch_arguments={
'robot_name': 'robot1',
'use_sim': 'true',
}.items()
)
参数化嵌套
def generate_launch_description():
robot_name = DeclareLaunchArgument('robot_name', default_value='robot1')
robot_launch = IncludeLaunchDescription(
PythonLaunchDescriptionSource(pkg_dir + '/launch/robot.launch.py'),
launch_arguments=[('robot_name', LaunchConfiguration('robot_name'))]
)
return LaunchDescription([robot_name, robot_launch])
条件嵌套
from launch.actions import GroupAction
group_launch = GroupAction(
condition=IfCondition(LaunchConfiguration('enable_robot')),
actions=[
Node(package='robot', executable='robot_node'),
IncludeLaunchDescription(
PythonLaunchDescriptionSource(pkg_dir + '/launch/robot_params.launch')
),
]
)
复杂 Launch 示例
机器人启动 Launch
import os
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription
from launch.substitutions import LaunchConfiguration
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node
def generate_launch_description():
robot_name = DeclareLaunchArgument('robot_name', default_value='robot1')
use_sim = DeclareLaunchArgument('use_sim', default_value='true')
namespace = DeclareLaunchArgument('namespace', default_value='')
ns = LaunchConfiguration('namespace')
hardware = Node(
package='hardware_driver',
executable='hw_node',
condition=IfCondition(
PythonExpression(['not ', LaunchConfiguration('use_sim')])
),
namespace=ns,
)
sim_driver = Node(
package='gazebo_ros',
executable='gz_sim',
condition=IfCondition(LaunchConfiguration('use_sim')),
namespace=ns,
)
controller = Node(
package='robot_controller',
executable='controller_node',
parameters=[{
'robot_name': LaunchConfiguration('robot_name'),
}],
namespace=ns,
)
nav_nodes = IncludeLaunchDescription(
PythonLaunchDescriptionSource(pkg_dir + ),
condition=IfCondition(LaunchConfiguration()),
launch_arguments=[(, ns)],
)
LaunchDescription([
robot_name, use_sim, namespace,
hardware, sim_driver, controller, nav_nodes,
])
命令行工具
ros2 launch pkg_name launch_file.launch.py
ros2 launch pkg_name launch_file.launch.py robot_name:=robot1
ros2 launch pkg_name -s
ros2 launch pkg_name launch_file.launch.py --show-args
最佳实践
- 模块化: 将不同功能模块分到不同 launch 文件
- 参数化: 使用参数使 launch 文件可配置
- 条件启动: 根据环境启用/禁用功能
- 命名空间: 合理使用 namespace 避免冲突
- 错误处理: 添加事件处理应对异常退出