当前位置: 首页 > news >正文

ros2 launch文件编写详解

一个完整的简单的launch文件配置过程

1.编写launch文件

2.配置package.xml

3.配置setup.py(python包)

4.配置CMakeList(C++包)

5.编译+运行

# 在 ROS 2 的 Python 启动文件中,这些导入语句用于引入各类启动模块,以构建和配置节点启动流程
from launch import LaunchDescription
from launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([Node(package='turtlesim',namespace='turtlesim1',executable='turtlesim_node',name='sim'),Node(package='turtlesim',namespace='turtlesim2',executable='turtlesim_node',name='sim'),Node(package='turtlesim',executable='mimic',name='mimic',remappings=[('/input/pose', '/turtlesim1/turtle1/pose'),('/output/cmd_vel', '/turtlesim2/turtle1/cmd_vel'),])])

package.xml加入以下内容: 

<exec_depend>ros2launch</exec_depend>

CMakeList:  to the end of the file (but before ament_package()).

# Install launch files.
install(DIRECTORYlaunchDESTINATION share/${PROJECT_NAME}/
)

package.list:

import os
from glob import glob
# Other imports ...package_name = 'py_launch_example'setup(# Other parameters ...data_files=[# ... Other data files# Include all launch files.(os.path.join('share', package_name, 'launch'), glob('launch/*'))]
)

 

替换表达式

from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.substitutions import PathJoinSubstitution
from launch_ros.substitutions import FindPackageSharedef generate_launch_description():colors = {'background_r': '200'}return LaunchDescription([# 使用PathJoinSubstitution和FindPackageShare动态构建启动文件路径IncludeLaunchDescription(PathJoinSubstitution([FindPackageShare('launch_tutorial'),'launch','example_substitutions.launch.py']),# 传递给被包含启动文件的参数launch_arguments={'turtlesim_ns': 'turtlesim2','use_provided_red': 'True','new_background_r': colors['background_r'],}.items())])

在 Python 中,.items() 是字典(dict)对象的一个方法,用于将字典转换为可迭代的键值对元组列表。

又如:

from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, ExecuteProcess, TimerAction
from launch.conditions import IfCondition
from launch.substitutions import LaunchConfiguration, PythonExpression
from launch_ros.actions import Nodedef generate_launch_description():# turtlesim_ns = LaunchConfiguration('turtlesim_ns')use_provided_red = LaunchConfiguration('use_provided_red')new_background_r = LaunchConfiguration('new_background_r')return LaunchDescription([DeclareLaunchArgument('turtlesim_ns',default_value='turtlesim1'),DeclareLaunchArgument('use_provided_red',default_value='False'),DeclareLaunchArgument('new_background_r',default_value='200'),Node(package='turtlesim',namespace=turtlesim_ns,executable='turtlesim_node',name='sim'),ExecuteProcess(cmd=[['ros2 service call ',turtlesim_ns,'/spawn ','turtlesim/srv/Spawn ','"{x: 2, y: 2, theta: 0.2}"']],shell=True),ExecuteProcess(cmd=[['ros2 param set ',turtlesim_ns,'/sim background_r ','120']],shell=True),TimerAction(period=2.0,actions=[ExecuteProcess(condition=IfCondition(PythonExpression([new_background_r,' == 200',' and ',use_provided_red])),cmd=[['ros2 param set ',turtlesim_ns,'/sim background_r ',new_background_r]],shell=True),],)])

为什么需要 LaunchConfiguration?

简单说,LaunchConfiguration就像一个 “参数占位符”。当你在 Launch 文件中声明了一个启动参数(比如DeclareLaunchArgument('turtlesim_ns')),LaunchConfiguration可以引用这个参数的值,让你在后续的节点、动作配置中动态使用它,而不用写死具体数值。

比如你声明了一个参数background_r,默认值为 200,但用户启动时可能会通过命令行修改为 255。LaunchConfiguration('background_r')就能自动获取用户输入的最新值,无需修改 Launch 文件代码。

命令行进程调用:

ExecuteProcess(cmd=[['ros2 param set ',turtlesim_ns,'/sim background_r ','120']],shell=True),

条件执行:

TimerAction(period=2.0,actions=[ExecuteProcess(condition=IfCondition(PythonExpression([new_background_r,' == 200',' and ',use_provided_red])),cmd=[['ros2 param set ',turtlesim_ns,'/sim background_r ',new_background_r]],shell=True),],)

格式: 

TimerAction(period = ....  # 多少时间后actions =[ExecuteProcess(condition = IfCondition(......  # 具体条件),cmd = [ [........... # 命令行指令]],shell = True),],)

这段代码的作用是:在启动后 2 秒,检查特定条件是否满足,如果满足则执行一条 ROS 2 命令修改 turtlesim 模拟器的背景红色值

ROS 2 中的事件处理器(Event Handlers)使用示例 


from launch import LaunchDescription
from launch.actions import (DeclareLaunchArgument,EmitEvent,ExecuteProcess,LogInfo,RegisterEventHandler,TimerAction
)
from launch.conditions import IfCondition
from launch.event_handlers import (OnExecutionComplete,OnProcessExit,OnProcessIO,OnProcessStart,OnShutdown
)
from launch.events import Shutdown
from launch.substitutions import (EnvironmentVariable,FindExecutable,LaunchConfiguration,LocalSubstitution,PythonExpression
)
from launch_ros.actions import Nodedef generate_launch_description():turtlesim_ns = LaunchConfiguration('turtlesim_ns')use_provided_red = LaunchConfiguration('use_provided_red')new_background_r = LaunchConfiguration('new_background_r')turtlesim_ns_launch_arg = DeclareLaunchArgument('turtlesim_ns',default_value='turtlesim1')use_provided_red_launch_arg = DeclareLaunchArgument('use_provided_red',default_value='False')new_background_r_launch_arg = DeclareLaunchArgument('new_background_r',default_value='200')turtlesim_node = Node(package='turtlesim',namespace=turtlesim_ns,executable='turtlesim_node',name='sim')spawn_turtle = ExecuteProcess(cmd=[[FindExecutable(name='ros2'),' service call ',turtlesim_ns,'/spawn ','turtlesim/srv/Spawn ','"{x: 2, y: 2, theta: 0.2}"']],shell=True)change_background_r = ExecuteProcess(cmd=[[FindExecutable(name='ros2'),' param set ',turtlesim_ns,'/sim background_r ','120']],shell=True)change_background_r_conditioned = ExecuteProcess(condition=IfCondition(PythonExpression([new_background_r,' == 200',' and ',use_provided_red])),cmd=[[FindExecutable(name='ros2'),' param set ',turtlesim_ns,'/sim background_r ',new_background_r]],shell=True)return LaunchDescription([turtlesim_ns_launch_arg,use_provided_red_launch_arg,new_background_r_launch_arg,turtlesim_node,RegisterEventHandler(OnProcessStart(target_action=turtlesim_node,on_start=[LogInfo(msg='Turtlesim started, spawning turtle'),spawn_turtle])),RegisterEventHandler(OnProcessIO(target_action=spawn_turtle,on_stdout=lambda event: LogInfo(msg='Spawn request says "{}"'.format(event.text.decode().strip())))),RegisterEventHandler(OnExecutionComplete(target_action=spawn_turtle,on_completion=[LogInfo(msg='Spawn finished'),change_background_r,TimerAction(period=2.0,actions=[change_background_r_conditioned],)])),RegisterEventHandler(OnProcessExit(target_action=turtlesim_node,on_exit=[LogInfo(msg=(EnvironmentVariable(name='USER'),' closed the turtlesim window')),EmitEvent(event=Shutdown(reason='Window closed'))])),RegisterEventHandler(OnShutdown(on_shutdown=[LogInfo(msg=['Launch was asked to shutdown: ', LocalSubstitution('event.reason')])])),])

 详解:

这个启动文件创建了一个 turtlesim 模拟器,并实现了以下功能:

  1. 启动 turtlesim 节点后,自动生成一只新乌龟
  2. 捕获生成乌龟的服务响应并打印日志
  3. 乌龟生成完成后,修改模拟器背景颜色
  4. 2 秒后,根据参数条件再次修改背景颜色
  5. 当 turtlesim 窗口关闭时,自动终止整个启动过程
  6. 捕获系统关闭事件并打印关闭原因
1.节点与命令定义
turtlesim_node = Node(package='turtlesim',namespace=turtlesim_ns,executable='turtlesim_node',name='sim'
)
spawn_turtle = ExecuteProcess(...)  # 生成乌龟的服务调用
change_background_r = ExecuteProcess(...)  # 修改背景颜色的命令
change_background_r_conditioned = ExecuteProcess(...)  # 条件性修改背景颜色

这些组件定义了要执行的基本操作,但它们的执行时机由事件处理器控制。

2.事件处理器注册
RegisterEventHandler(OnProcessStart(target_action=turtlesim_node,on_start=[LogInfo(...), spawn_turtle])
)
  • OnProcessStart:当turtlesim_node启动时,触发生成乌龟的命令。

RegisterEventHandler(OnProcessIO(target_action=spawn_turtle,on_stdout=lambda event: LogInfo(...))
)
  • OnProcessIO:捕获spawn_turtle命令的标准输出,提取服务响应信息。

当执行spawn_turtle命令(即调用turtlesim/srv/Spawn服务)时,服务响应会通过标准输出返回。例如:

ros2 service call /turtlesim1/spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2}"

服务成功响应后,控制台会打印:

[INFO] [launch]: Spawn request says "Created turtle [turtle2]"

这表明新乌龟已成功生成,并且名称为turtle2

RegisterEventHandler(OnExecutionComplete(target_action=spawn_turtle,on_completion=[LogInfo(...), change_background_r, TimerAction(...)])
)
  • OnExecutionComplete:当spawn_turtle命令完成后,修改背景颜色,并设置一个 2 秒后的延迟动作。

RegisterEventHandler(OnProcessExit(target_action=turtlesim_node,on_exit=[LogInfo(...), EmitEvent(event=Shutdown(...))])
)
  • OnProcessExit:当turtlesim_node退出时,触发系统关闭事件。

RegisterEventHandler(OnShutdown(on_shutdown=[LogInfo(...)])
)
  • OnShutdown:捕获系统关闭事件,打印关闭原因。
3.编译执行: 
ros2 launch launch_tutorial example_event_handlers.launch.py turtlesim_ns:='turtlesim3' use_provided_red:='True' new_background_r:=200

管理大型工程

顶层管理:

from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.substitutions import PathJoinSubstitution
from launch_ros.substitutions import FindPackageSharedef generate_launch_description():launch_dir = PathJoinSubstitution([FindPackageShare('launch_tutorial'), 'launch'])return LaunchDescription([IncludeLaunchDescription(PathJoinSubstitution([launch_dir, 'turtlesim_world_1.launch.py'])),IncludeLaunchDescription(PathJoinSubstitution([launch_dir, 'turtlesim_world_2.launch.py'])),IncludeLaunchDescription(PathJoinSubstitution([launch_dir, 'broadcaster_listener.launch.py']),launch_arguments={'target_frame': 'carrot1'}.items()),IncludeLaunchDescription(PathJoinSubstitution([launch_dir, 'mimic.launch.py'])),IncludeLaunchDescription(PathJoinSubstitution([launch_dir, 'fixed_broadcaster.launch.py'])),IncludeLaunchDescription(PathJoinSubstitution([launch_dir, 'turtlesim_rviz.launch.py'])),])

在launch文件设置参数:

from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([DeclareLaunchArgument('background_r', default_value='0'),DeclareLaunchArgument('background_g', default_value='84'),DeclareLaunchArgument('background_b', default_value='122'),Node(package='turtlesim',executable='turtlesim_node',name='sim',parameters=[{'background_r': LaunchConfiguration('background_r'),'background_g': LaunchConfiguration('background_g'),'background_b': LaunchConfiguration('background_b'),}]),])

通过YAML文件设置参数:

from launch import LaunchDescription
from launch.substitutions import PathJoinSubstitution
from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageSharedef generate_launch_description():return LaunchDescription([Node(package='turtlesim',executable='turtlesim_node',namespace='turtlesim2',name='sim',parameters=[PathJoinSubstitution([FindPackageShare('launch_tutorial'), 'config', 'turtlesim.yaml'])],),])

/turtlesim2/sim:ros__parameters:background_b: 255background_g: 86background_r: 150

整个/turtlesim2/sim代表的是 “位于turtlesim2命名空间下、名为simturtlesim节点”,其后的ros__parameters则是该节点的具体参数配置(如背景色的 RGB 值)

命名空间 :

当启动文件需要包含大量节点时,手动为每个节点单独设置命名空间会变得繁琐且易出错。PushRosNamespace 提供了一种更优雅的解决方案,让你可以为一组节点批量设置命名空间。

首先remove the namespace='turtlesim2' line from the turtlesim_world_2.launch.py 。然后按照以下修改:

from launch.actions import GroupAction
from launch_ros.actions import PushRosNamespace...GroupAction(actions=[PushROSNamespace('turtlesim2'),IncludeLaunchDescription(PathJoinSubstitution([launch_dir, 'turtlesim_world_2.launch.py'])),]),

那么在turtlesim_world_2.launch.py中的每一个节点都有一个turtlesim2前缀的命令空间。

节点复用

from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfigurationfrom launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([DeclareLaunchArgument('target_frame', default_value='turtle1',description='Target frame name.',),Node(package='turtle_tf2_py',executable='turtle_tf2_broadcaster',name='broadcaster1',parameters=[{'turtlename': 'turtle1'}],),Node(package='turtle_tf2_py',executable='turtle_tf2_broadcaster',name='broadcaster2',parameters=[{'turtlename': 'turtle2'}],),Node(package='turtle_tf2_py',executable='turtle_tf2_listener',name='listener',parameters=[{'target_frame': LaunchConfiguration('target_frame')}],),])

 话题重映射

from launch import LaunchDescription
from launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([Node(package='turtlesim',executable='mimic',name='mimic',remappings=[('/input/pose', '/turtle2/pose'),('/output/cmd_vel', '/turtlesim2/turtle1/cmd_vel'),])])

 启动rviz,并按照文件配置:

from launch import LaunchDescription
from launch.substitutions import PathJoinSubstitution
from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageSharedef generate_launch_description():return LaunchDescription([Node(package='rviz2',executable='rviz2',name='rviz2',arguments=['-d', PathJoinSubstitution([FindPackageShare('turtle_tf2_py'), 'rviz', 'turtle_rviz.rviz'])],),])

动态配置节点名:

from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import EnvironmentVariable, LaunchConfiguration
from launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([DeclareLaunchArgument('node_prefix',default_value=[EnvironmentVariable('USER'), '_'],description='prefix for node name'),Node(package='turtle_tf2_py',executable='fixed_frame_tf2_broadcaster',name=[LaunchConfiguration('node_prefix'), 'fixed_broadcaster'],),])
  1. 声明一个启动参数node_prefix,默认值为当前系统用户的用户名加上下划线(例如:doubao_)
  2. 启动一个节点,节点名称由node_prefix和固定后缀fixed_broadcaster组成(例如:doubao_fixed_broadcaster)

更新setup.py:

import os
from glob import glob
from setuptools import setup
...data_files=[...(os.path.join('share', package_name, 'launch'),glob('launch/*')),(os.path.join('share', package_name, 'config'),glob('config/*.yaml')),(os.path.join('share', package_name, 'rviz'),glob('config/*.rviz')),],

http://www.lryc.cn/news/605324.html

相关文章:

  • Python 程序设计讲义(46):组合数据类型——集合类型:集合间运算
  • 【百卷编程】Go语言大厂高级面试题集
  • 如何修改VM虚拟机中的ip
  • 2024 年 NOI 最后一题题解
  • 《汇编语言:基于X86处理器》第10章 复习题和练习
  • 歌尔微报考港交所上市:业绩稳增显韧性,创新引领生态发展
  • S3、SFTP、FTP、FTPS 协议的概念、对比与应用场景
  • openwrt中br-lan,eth0,eth0.1,eth0.2
  • 第2章 cmd命令基础:常用基础命令(3)
  • cmake_parse_arguments()构建清晰灵活的 CMake 函数接口
  • G9打卡——ACGAN
  • 获取TensorRT引擎文件(.engine)版本号的几种方法
  • 2022 年 NOI 最后一题题解
  • 数据集相关类代码回顾理解 | DataLoader\datasets.xxx
  • 【高等数学】第七章 微分方程——第四节 一阶线性微分方程
  • 【支持Ubuntu22】Ambari3.0.0+Bigtop3.2.0——Step4—时间同步(Chrony)
  • Spark的宽窄依赖
  • 《设计模式之禅》笔记摘录 - 11.策略模式
  • uniapp-vue3来实现一个金额千分位展示效果
  • uniapp实现微信小程序导航功能
  • 思途JSP学习 0730
  • LeetCode 刷题【22. 括号生成】
  • Winform 渐变色 调色板
  • 代码随想录算法训练营第五十六天|动态规划part6
  • C语言基础11——结构体1
  • AutoSAR(MCAL) --- ADC
  • VoIP技术全面深度学习指南:从原理到实践的认知进化
  • 【GEO从入门到精通】生成式引擎与其他 AI 技术的关系
  • Linux ARM 平台 C 语言操作 Excel 文件的常用库与工具汇总(支持 xls 和 xlsx)
  • Linux基本指令,对路径的认识