【ROS2】☆ launch之Python

 

☆重点 

        ROS1和ROS2其中一个很大区别之一就是launch的编写方式。在ROS1中采用xml格式编写launch,而ROS2保留了XML 格式launch,还另外引入了Python和YAML 编写方式。选择哪种编写取决于每位开发人员的爱好,但是ROS2官方推荐使用Python方式编写,理由如下:Python 是一种脚本语言,使用灵活,Python库强大,可以直接引入:ROS2launch框架本身是用Python编写,由于亲和力高Python可以直接调用一些高级特性 ,而XML 和 YAML 可能无法调用。

        当然用 Python 编写的启动文件可能比 XML 或 YAML 编写的启动文件更复杂、更冗长。

        不过建议能使用Python编写尽量使用Python,不要问为什么,问就是官方推荐!

在使用Python版的launch文件时,涉及的API众多,为了提高编码效率,可以在VScode中设置launch文件的代码模板,将VScode的配置文件python.json修改为为如下内容:

    "ros2 launch py": {
        "prefix": "ros2_launch_py",
        "body": [
            "from launch import LaunchDescription",
            "from launch_ros.actions import Node",
            "# 封装终端指令相关类--------------",
            "# from launch.actions import ExecuteProcess",
            "# from launch.substitutions import FindExecutable",
            "# 参数声明与获取-----------------",
            "# from launch.actions import DeclareLaunchArgument",
            "# from launch.substitutions import LaunchConfiguration",
            "# 文件包含相关-------------------",
            "# from launch.actions import IncludeLaunchDescription",
            "# from launch.launch_description_sources import PythonLaunchDescriptionSource",
            "# 分组相关----------------------",
            "# from launch_ros.actions import PushRosNamespace",
            "# from launch.actions import GroupAction",
            "# 事件相关----------------------",
            "# from launch.event_handlers import OnProcessStart, OnProcessExit",
            "# from launch.actions import ExecuteProcess, RegisterEventHandler,LogInfo",
            "# 获取功能包下share目录路径-------",
            "# from ament_index_python.packages import get_package_share_directory",
            "",
            "def generate_launch_description():",
            "    ",    
            "    return LaunchDescription([])"
        ],
        "description": "ros2 launch"
    }

一、节点设置

launch 中需要执行的节点被封装为了 launch_ros.actions.Node 对象。

示例:新建 py01_node.launch.py 文件,输入如下内容:

from launch import LaunchDescription
from launch_ros.actions import Node
import os
from ament_index_python.packages import get_package_share_directory

def generate_launch_description():

    turtle1 = Node(package="turtlesim", 
                executable="turtlesim_node", 
                namespace="ns_1",
                name="t1", 
                exec_name="turtle_label", # 表示流程的标签
                respawn=True)
    turtle2 = Node(package="turtlesim", 
                executable="turtlesim_node", 
                name="t2",
                # 参数设置方式1
                # parameters=[{"background_r": 0,"background_g": 0,"background_b": 0}],
                # 参数设置方式2: 从 yaml 文件加载参数,yaml 文件所属目录需要在配置文件中安装。
                parameters=[os.path.join(get_package_share_directory("cpp01_launch"),"config","t2.yaml")],
                )
    turtle3 = Node(package="turtlesim", 
                executable="turtlesim_node", 
                name="t3", 
                remappings=[("/turtle1/cmd_vel","/cmd_vel")] #话题重映射
                )
    rviz = Node(package="rviz2",
                executable="rviz2",
                # 节点启动时传参
                arguments=["-d", os.path.join(get_package_share_directory("cpp01_launch"),"config","my.rviz")]
    )

    turtle4 = Node(package="turtlesim", 
                executable="turtlesim_node",
                # 节点启动时传参,相当于 arguments 传参时添加前缀 --ros-args 
                ros_arguments=["--remap", "__ns:=/t4_ns", "--remap", "__node:=t4"]
    )
    return LaunchDescription([turtle1, turtle2, turtle3, rviz, turtle4])

代码解释

1.1 Node使用语法1
turtle1 = Node(package="turtlesim", 
                executable="turtlesim_node", 
                namespace="group_1", 
                name="t1", 
                exec_name="turtle_label", # 表示流程的标签
                respawn=True)

上述代码会创建一个 turtlesim_node 节点,设置了若干节点属性,并且节点关闭后会自动重启。

  • package:功能包;
  • executable:可执行文件;
  • namespace:命名空间;
  • name:节点名称;
  • exe_name:流程标签;
  • respawn:设置为True时,关闭节点后,可以自动重启。
1.2 Node使用语法2
turtle2 = Node(package="turtlesim", 
                executable="turtlesim_node", 
                name="t2",
                # 参数设置方式1
                # parameters=[{"background_r": 0,"background_g": 0,"background_b": 0}],
                # 参数设置方式2: 从 yaml 文件加载参数,yaml 文件所属目录需要在配置文件中安装。
                parameters=[os.path.join(get_package_share_directory("cpp01_launch"),"config","t2.yaml")],
                )

上述代码会创建一个 turtlesim_node 节点,并导入背景色相关参数。

  • parameters:导入参数。

parameter 用于设置被导入的参数,如果是从 yaml 文件加载参数,那么需要先准备 yaml 文件,在功能包下新建 config 目录,config目录下新建 t2.yaml 文件,并输入如下内容:

/t2:
  ros__parameters:
    background_b: 0
    background_g: 0
    background_r: 50
    qos_overrides:
      /parameter_events:
        publisher:
          depth: 1000
          durability: volatile
          history: keep_last
          reliability: reliable
    use_sim_time: false

注意,还需要在 CMakeLists.txt 中安装 config:

install(DIRECTORY 
  launch
  config
  DESTINATION share/${PROJECT_NAME})
1.3 Node使用语法3
turtle3 = Node(package="turtlesim", 
                executable="turtlesim_node", 
                name="t3", 
                remappings=[("/turtle1/cmd_vel","/cmd_vel")] #话题重映射
                )

上述代码会创建一个 turtlesim_node 节点,并将话题名称从 /turtle1/cmd_vel 重映射到 /cmd_vel。

  • remappings:话题重映射。
1.4 Node使用语法4
rviz = Node(package="rviz2",
                executable="rviz2",
                # 节点启动时传参
                arguments=["-d", os.path.join(get_package_share_directory("cpp01_launch"),"config","my.rviz")]
    )

上述代码会创建一个 rviz2 节点,并加载了 rviz2 相关的配置文件。

该配置文件可以先启动 rviz2 ,配置完毕后,保存到 config 目录并命名为 my.rviz。

  • arguments:调用指令时的参数列表。
1.5 Node使用语法5
turtle4 = Node(package="turtlesim", 
                executable="turtlesim_node",
                # 节点启动时传参,相当于 arguments 传参时添加前缀 --ros-args 
                ros_arguments=["--remap", "__ns:=/t4_ns", "--remap", "__node:=t4"]
    )

上述代码会创建一个 turtlesim_node 节点,并在指令调用时传入参数列表。

  • ros_arguments:相当于 arguments 前缀 --ros-args。

二、执行指令

launch 中需要执行的命令被封装为了 launch.actions.ExecuteProcess 对象。

示例:新建 py02_cmd.launch.py 文件,输入如下内容:

from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions import ExecuteProcess
from launch.substitutions import FindExecutable

def generate_launch_description():
    turtle = Node(package="turtlesim", executable="turtlesim_node")
    spawn = ExecuteProcess(
        # cmd=["ros2 service call /spawn turtlesim/srv/Spawn \"{x: 8.0, y: 9.0,theta: 0.0, name: 'turtle2'}\""],
        # 或
        cmd = [
            FindExecutable(name = "ros2"), # 不可以有空格
            " service call",
            " /spawn turtlesim/srv/Spawn",
            " \"{x: 8.0, y: 9.0,theta: 1.0, name: 'turtle2'}\""
        ],
        output="both",
        shell=True)
    return LaunchDescription([turtle,spawn])

代码解释

spawn = ExecuteProcess(
        # cmd=["ros2 service call /spawn turtlesim/srv/Spawn \"{x: 8.0, y: 9.0,theta: 0.0, name: 'turtle2'}\""],
        # 或
        cmd = [
            FindExecutable(name = "ros2"), # 不可以有空格
            " service call",
            " /spawn turtlesim/srv/Spawn",
            " \"{x: 8.0, y: 9.0,theta: 1.0, name: 'turtle2'}\""
        ],
        output="both",
        shell=True)

上述代码用于执行 cmd 参数中的命令,该命令会在 turtlesim_node 中生成一只新的小乌龟。

  • cmd:被执行的命令;
  • output:设置为 both 时,日志会被输出到日志文件和终端,默认为 log,日志只输出到日志文件。
  • shell:如果为 True,则以 shell 的方式执行命令。

三、参数设置

参数设置主要涉及到参数的声明与调用两部分,其中声明被封装为 launch.actions.DeclareLaunchArgument,调用则被封装为 launch.substitutions import LaunchConfiguration。

需求:启动turtlesim_node节点时,可以动态设置背景色。

示例:新建 py03_args.launch.py 文件,输入如下内容:

from pkg_resources import declare_namespace
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration

def generate_launch_description():

    decl_bg_r = DeclareLaunchArgument(name="background_r",default_value="255")
    decl_bg_g = DeclareLaunchArgument(name="background_g",default_value="255")
    decl_bg_b = DeclareLaunchArgument(name="background_b",default_value="255")

    turtle = Node(package="turtlesim", 
            executable="turtlesim_node",
            parameters=[{"background_r": LaunchConfiguration("background_r"), "background_g": LaunchConfiguration("background_g"), "background_b": LaunchConfiguration("background_b")}]
            )
    return LaunchDescription([decl_bg_r,decl_bg_g,decl_bg_b,turtle])

代码解释

decl_bg_r = DeclareLaunchArgument(name="background_r",default_value="255")
decl_bg_g = DeclareLaunchArgument(name="background_g",default_value="255")
decl_bg_b = DeclareLaunchArgument(name="background_b",default_value="255")

上述代码会使用DeclareLaunchArgument对象声明三个参数,且每个参数都有参数名称以及默认值。

  • name:参数名称;
  • default_value:默认值。
parameters=[{"background_r": LaunchConfiguration(variable_name="background_r"), "background_g": LaunchConfiguration("background_g"), "background_b": LaunchConfiguration("background_b")}]

上述代码会使用LaunchConfiguration对象获取参数值。

  • variable_name:被解析的参数名称。

launch文件执行时,可以动态传入参数,示例如下:

ros2 launch cpp01_launch py03_args.launch.py background_r:=200 background_g:=80 background_b:=30

如果执行launch文件时不手动传入参数,那么解析到的参数值是声明时设置的默认值。

四、文件包含

在 launch 文件中可以包含其他launch文件,需要使用的API为:launch.actions.IncludeLaunchDescription 和 launch.launch_description_sources.PythonLaunchDescriptionSource。

需求:新建 launch 文件,包含 4.2.3 中的 launch 文件并为之传入设置背景色相关的参数。

示例:新建 py04_include.launch.py 文件,输入如下内容:

from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource

import os
from ament_index_python import get_package_share_directory

def generate_launch_description():

    include_launch = IncludeLaunchDescription(
        launch_description_source= PythonLaunchDescriptionSource(
            launch_file_path=os.path.join(
                get_package_share_directory("cpp01_launch"),
                "launch/py",
                "py03_args.launch.py"
            )
        ),
        launch_arguments={
            "background_r": "200",
            "background_g": "100",
            "background_b": "70",
        }.items()
    )

    return LaunchDescription([include_launch])

代码解释

include_launch = IncludeLaunchDescription(
        launch_description_source= PythonLaunchDescriptionSource(
            launch_file_path=os.path.join(
                get_package_share_directory("cpp01_launch"),
                "launch/py",
                "py03_args.launch.py"
            )
        ),
        launch_arguments={
            "background_r": "200",
            "background_g": "100",
            "background_b": "70",
        }.items()
    )

上述代码将包含一个launch文件并为launch文件传参。

在 IncludeLaunchDescription 对象中:

  • launch_description_source:用于设置被包含的 launch 文件;
  • launch_arguments:元组列表,每个元组中都包含参数的键和值。

在 PythonLaunchDescriptionSource 对象中:

  • launch_file_path:被包含的 launch 文件路径。

五、分组设置

在 launch 文件中,为了方便管理可以对节点分组,分组相关API为:launch.actions.GroupAction和launch_ros.actions.PushRosNamespace。

需求:对 launch 文件中的多个 Node 进行分组。

示例:新建 py05_group.launch.py 文件,输入如下内容:

from launch import LaunchDescription
from launch_ros.actions import Node
from launch_ros.actions import PushRosNamespace
from launch.actions import GroupAction

def generate_launch_description():
    turtle1 = Node(package="turtlesim",executable="turtlesim_node",name="t1")
    turtle2 = Node(package="turtlesim",executable="turtlesim_node",name="t2")
    turtle3 = Node(package="turtlesim",executable="turtlesim_node",name="t3")
    g1 = GroupAction(actions=[PushRosNamespace(namespace="g1"),turtle1, turtle2])
    g2 = GroupAction(actions=[PushRosNamespace(namespace="g2"),turtle3])
    return LaunchDescription([g1,g2])

代码解释

g1 = GroupAction(actions=[PushRosNamespace(namespace="g1"),turtle1, turtle2])
g2 = GroupAction(actions=[PushRosNamespace(namespace="g2"),turtle3])

上述代码将创建两个组,两个组使用了不同的命名空间,每个组下包含了不同的节点。

在 GroupAction 对象中,使用的参数为:

  • actions:action列表,比如被包含到组内的命名空间、节点等。

在 PushRosNamespace 对象中,使用的参数为:

  • namespace:当前组使用的命名空间。

六、添加事件

节点在运行过程中会触发不同的事件,当事件触发时可以为之注册一定的处理逻辑。事件使用相关的 API 为:launch.actions.RegisterEventHandler、launch.event_handlers.OnProcessStart、launch.event_handlers.OnProcessExit。

需求:为 turtlesim_node 节点添加事件,事件1:节点启动时调用spawn服务生成新乌龟;事件2:节点关闭时,输出日志信息。

示例:新建 py06_event.launch.py 文件,输入如下内容:

from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions import ExecuteProcess, RegisterEventHandler,LogInfo
from launch.substitutions import FindExecutable
from launch.event_handlers import OnProcessStart, OnProcessExit
def generate_launch_description():
    turtle = Node(package="turtlesim", executable="turtlesim_node")
    spawn = ExecuteProcess(
        cmd = [
            FindExecutable(name = "ros2"), # 不可以有空格
            " service call",
            " /spawn turtlesim/srv/Spawn",
            " \"{x: 8.0, y: 1.0,theta: 1.0, name: 'turtle2'}\""
        ],
        output="both",
        shell=True)

    start_event = RegisterEventHandler(
        event_handler=OnProcessStart(
            target_action = turtle,
            on_start = spawn
        )
    )
    exit_event = RegisterEventHandler(
        event_handler=OnProcessExit(
            target_action = turtle,
            on_exit = [LogInfo(msg = "turtlesim_node退出!")]
        )
    )

    return LaunchDescription([turtle,start_event,exit_event])

代码解释

start_event = RegisterEventHandler(
        event_handler=OnProcessStart(
            target_action = turtle,
            on_start = spawn
        )
    )
exit_event = RegisterEventHandler(
        event_handler=OnProcessExit(
            target_action = turtle,
            on_exit = [LogInfo(msg = "turtlesim_node退出!")]
        )
    )

上述代码为 turtle 节点注册启动事件和退出事件,当 turtle 节点启动后会执行 spwn 节点,当 turtle 节点退出时,会输出日志文本:“turtlesim_node退出!”。

对象 RegisterEventHandler 负责注册事件,其参数为:

  • event_handler:注册的事件对象。

OnProcessStart 是启动事件对象,其参数为:

  • target_action:被注册事件的目标对象;
  • on_start:事件触发时的执行逻辑。

OnProcessExit 是退出事件对象,其参数为:

  • target_action:被注册事件的目标对象;
  • on_exit:事件触发时的执行逻辑。

LogInfo 是日志输出对象,其参数为:

  • msg:被输出的日志信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/951164.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Shell编程详解

文章目录 一、Linux系统结构二、Shell介绍1、Shell简介2、Shell种类3、Shell查询和切换 三、Shell基础语法1、注释2、本地变量3、环境变量3.1、查看环境变量3.2、临时设置环境变量3.3、永久设置环境变量 4、特殊变量5、控制语句5.1、shell中的中括号5.2、if语句5.3、for循环5.4…

Zemax 序列模式下的扩束器

扩束器结构原理 扩束器用于增加准直光束(例如激光束)的直径,同时保持其准直。它通常用于激光光学和其他需要修改光束大小或发散度的应用。 在典型的扩束器中,输入光束是准直激光器,或光束进入第一个光学元件。当光束开…

react-quill 富文本组件编写和应用

index.tsx文件 import React, { useRef, useState } from react; import { Modal, Button } from antd; import RichEditor from ./RichEditor;const AnchorTouchHistory: React.FC () > {const editorRef useRef<any>(null);const [isModalVisible, setIsModalVis…

【深度学习】多目标融合算法(二):底部共享多任务模型(Shared-Bottom Multi-task Model)

目录 一、引言 1.1 往期回顾 1.2 本期概要 二、Shared-Bottom Multi-task Model&#xff08;SBMM&#xff09; 2.1 技术原理 2.2 技术优缺点 2.3 业务代码实践 三、总结 一、引言 在朴素的深度学习ctr预估模型中&#xff08;如DNN&#xff09;&#xff0c;通常以一个行…

探秘MetaGPT:革新软件开发的多智能体框架(22/30)

一、MetaGPT 引发的 AI 变革浪潮 近年来&#xff0c;人工智能大模型领域取得了令人瞩目的进展&#xff0c;GPT-3、GPT-4、PaLM 等模型展现出了惊人的自然语言处理能力&#xff0c;仿佛为 AI 世界打开了一扇通往无限可能的大门。它们能够生成流畅的文本、回答复杂的问题、进行创…

LabVIEW软件Bug的定义与修改

在LabVIEW软件开发过程中&#xff0c;bug&#xff08;程序错误或缺陷&#xff09;指的是程序中导致不符合预期行为的任何问题。Bug可能是由于编码错误、逻辑漏洞、硬件兼容性问题、系统资源限制等因素引起的。它可能会导致程序崩溃、功能无法正常执行或输出结果不符合预期。理解…

高性能网络模式:Reactor 和 Proactor

Reactor Reactor 采用I/O多路复用监听事件&#xff0c;收到事件后&#xff0c;根据事件类型分配给某个进程/线程。 实际应用中用到的模型&#xff1a; 单 Reactor 单进程 单 Reactor 多线程 优点&#xff1a;能充分利用多核CPU性能。 缺点&#xff1a;存在多线程竞争共享资源…

扩散模型论文概述(三):Stability AI系列工作【学习笔记】

视频链接&#xff1a;扩散模型论文概述&#xff08;三&#xff09;&#xff1a;Stability AI系列工作_哔哩哔哩_bilibili 本期视频讲的是Stability AI在图像生成的工作。 同样&#xff0c;第一张图片是神作&#xff0c;总结的太好了&#xff01; 介绍Stable Diffusion之前&…

大数据技术-Hadoop(四)Yarn的介绍与使用

目录 一、Yarn 基本结构 1、Yarn基本结构 2、Yarn的工作机制 二、Yarn常用的命令 三、调度器 1、Capacity Scheduler&#xff08;容量调度器&#xff09; 1.1、特点 1.2、配置 1.2.1、yarn-site.xml 1.2.2、capacity-scheduler.xml 1.3、重启yarn、刷新队列 测试 向hi…

玩转大语言模型——ollama导入huggingface下载的模型

ollama导入huggingface模型 前言gguf模型查找相关模型下载模型 导入Ollama配置参数文件导入模型查看导入情况 safetensfors模型下载模型下载llama.cpp配置环境并转换 前言 ollama在大语言模型的应用中十分的方便&#xff0c;但是也存在一定的问题&#xff0c;比如不能使用自己…

apollo内置eureka dashboard授权登录

要确保访问Eureka Server时要求输入账户和密码&#xff0c;需要确保以下几点&#xff1a; 确保 eurekaSecurityEnabled 配置为 true&#xff1a;这个配置项控制是否启用Eureka的安全认证。如果它被设置为 false&#xff0c;即使配置了用户名和密码&#xff0c;也不会启用安全认…

【Dify】Dify自定义模型设置 | 对接DMXAPI使用打折 Openai GPT 或 Claude3.5系列模型方法详解

一、Dify & DMXAPI 1、Dify DIFY&#xff08;Do It For You&#xff09;是一种自动化工具或服务&#xff0c;旨在帮助用户简化操作&#xff0c;减少繁琐的手动操作&#xff0c;提升工作效率。通过DIFY&#xff0c;用户能够快速完成任务、获取所需数据&#xff0c;并且可以…

【深度学习】布匹寻边:抓边误差小于3px【附完整链接】

布匹寻边 项目简介 布匹寻边是指布料裁剪过程中&#xff0c;通过AI寻边技术自动识别布匹的边缘&#xff0c;将检测到的边缘信息输出&#xff0c;确保裁剪的准确性&#xff0c;减少浪费&#xff0c;并提高生产效率。 项目需求 将打满针眼的布匹边缘裁剪掉&#xff0c;且误差小…

http range 下载大文件分片

摘自&#xff1a;https://www.jianshu.com/p/32c16103715a 上传分片下载也能分 HTTP 协议范围请求允许服务器只发送 HTTP 消息的一部分到客户端。范围请求在传送大的媒体文件&#xff0c;或者与文件下载的断点续传功能搭配使用时非常有用。 检测服务器端是否支持范围请求 假…

解决WordPress出现Fatal error: Uncaught TypeError: ftp_nlist()致命问题

错误背景 WordPress版本&#xff1a;wordpress-6.6.2-zh_CN WooCommerce版本&#xff1a;woocommerce.9.5.1 WordPress在安装了WooCommerce插件后&#xff0c;安装的过程中没有问题&#xff0c;在安装完成后提示&#xff1a; 此站点遇到了致命错误&#xff0c;请查看您站点管理…

用户使用LLM模型都在干什么?

Anthropic 对用户与 Claude 3.5 Sonnet 的大量匿名对话展开分析&#xff0c;主要发现及相关情况如下&#xff1a; 使用用途分布 软件开发主导&#xff1a;在各类使用场景中&#xff0c;软件开发占比最高&#xff0c;其中编码占 Claude 对话的 15% - 25%&#xff0c;网页和移动应…

【巨实用】Git客户端基本操作

本文主要分享Git的一些基本常规操作&#xff0c;手把手教你如何配置~ ● 一个文件夹中初始化Git git init ● 为了方便以后提交代码需要对git进行配置&#xff08;第一次使用或者需求变更的时候&#xff09;&#xff0c;告诉git未来是谁在提交代码 git config --global user.na…

腾讯云AI代码助手编程挑战赛:自动生成漂亮的网页

在当今数字化时代&#xff0c;网页设计和开发已经成为一项至关重要的技能。在当今时代&#xff0c;借助AI的力量&#xff0c;这部分工作变得简单。本文借助腾讯云AI代码助手——“自动生成需要的网页”。本文将详细介绍如何利用AI代码助手生成网页素材&#xff0c;帮助你轻松打…

多台PC共用同一套鼠标键盘

当环境中有多个桌面 pc 需要操作的时候&#xff0c;在 多台 pc 之间切换会造成很多的不方便 可以通过远程进行连接&#xff0c;但是有一个更好的方案是让多台机器之间共用同一套键盘鼠标 常用的解决方案 synergy 和 sharemouse&#xff0c;通过移动光标在不同的 pc 间切换 s…

UOS系统mysql服务安装

UOS系统mysql服务安装 背景 1、安装环境&#xff1a;kvm虚拟机2、运行环境&#xff1a;uos server-1060e3、架构&#xff1a;x864、安装mysql版本&#xff1a;mysql-5.71、安装准备 # Mysql官网 https://downloads.mysql.com/archives/community/ # 下载安装包 wget -i -c …