【ROS2】中级-编写可组合节点 (C++)

目录

  •  起点

  •  代码更新

    • 添加包依赖

    •  类定义

    • 没有主方法

    •  CMake 变更

  •  运行您的节点

 起点

我们假设你有一个常规的 rclcpp::Node 可执行文件,你希望在与其他节点相同的进程中运行它,以实现更高效的通信。

我们将从一个直接继承自 Node 的类开始,并且定义了一个主方法。

namespace palomino
{class VincentDriver : public rclcpp::Node{// ...};
}int main(int argc, char * argv[])
{rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<palomino::VincentDriver>());rclcpp::shutdown();return 0;
}

这通常会在您的 Cmake 中编译为可执行文件。

# ...
add_executable(vincent_driver src/vincent_driver.cpp)
# ...
install(TARGETS vincent_driverDESTINATION lib/${PROJECT_NAME}
)

 代码更新 

添加包依赖项

您的 package.xml 应该依赖于 rclcpp_components ,类似于

<depend>rclcpp_components</depend>

或者,您可以独立添加一个 build_depend/exec_depend 。

<?xml version="1.0"?>
<!-- XML 版本声明 --><?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<!-- XML 模型声明,定义了 ROS 包的格式 --><package format="3">
<!-- 开始定义一个 ROS 包,格式为 3 --><name>composition</name><!-- 包的名称为 composition --><version>0.33.4</version><!-- 包的版本号为 0.33.4 --><description>Examples for composing multiple nodes in a single process.</description><!-- 包的描述 --><maintainer email="aditya.pande@openrobotics.org">Aditya Pande</maintainer><maintainer email="audrow@openrobotics.org">Audrow Nash</maintainer><!-- 维护者的信息 --><license>Apache License 2.0</license><!-- 许可证信息 --><author email="dthomas@osrfoundation.org">Dirk Thomas</author><author email="mabel@openrobotics.org">Mabel Zhang</author><!-- 作者的信息 --><buildtool_depend>ament_cmake</buildtool_depend><!-- 构建工具依赖项 --><build_depend>example_interfaces</build_depend><build_depend>rclcpp</build_depend><build_depend>rclcpp_components</build_depend><build_depend>rcutils</build_depend><build_depend>std_msgs</build_depend><!-- 构建依赖项 --><exec_depend>example_interfaces</exec_depend><exec_depend>launch_ros</exec_depend><exec_depend>rclcpp</exec_depend><exec_depend>rclcpp_components</exec_depend><exec_depend>rcutils</exec_depend><exec_depend>std_msgs</exec_depend><!-- 执行依赖项 --><test_depend>ament_cmake_pytest</test_depend><test_depend>ament_lint_auto</test_depend><test_depend>ament_lint_common</test_depend><test_depend>launch</test_depend><test_depend>launch_testing</test_depend><test_depend>launch_testing_ros</test_depend><test_depend>launch_testing_ament_cmake</test_depend><test_depend>rmw_implementation_cmake</test_depend><!-- 测试依赖项 --><export><build_type>ament_cmake</build_type></export><!-- 导出构建类型 --></package>
<!-- 结束定义 ROS 包 -->

 类定义

您的类定义唯一可能需要更改的是确保类的构造函数https://github.com/ros2/demos/blob/jazzy/composition/src/talker_component.cpp 接受一个 NodeOptions 参数。

VincentDriver(const rclcpp::NodeOptions & options) : Node("vincent_driver", options)
{// ...
}
// 版权声明
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// 根据 Apache License 2.0(“许可证”)许可;
// 除非遵守许可证,否则不得使用此文件。
// 您可以在以下位置获取许可证副本:
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// 除非适用法律要求或书面同意,否则在许可证下分发的软件
// 将按“原样”基础分发,无任何形式的明示或暗示保证。
// 请参阅许可证以了解管理权限和
// 许可证下的限制。// 导入 Talker 组件头文件
#include "composition/talker_component.hpp"// 导入所需的标准库
#include <chrono>
#include <iostream>
#include <memory>
#include <utility>// 导入 ROS 客户端库和标准消息
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"// 使用 std::chrono_literals 命名空间
using namespace std::chrono_literals;// 定义 composition 命名空间
namespace composition
{// 创建一个 Talker “组件”,该组件继承自通用的 rclcpp::Node 基类。
// 组件被构建成共享库,因此不编写自己的主函数。
// 使用组件的共享库的进程将实例化该类作为 ROS 节点。
Talker::Talker(const rclcpp::NodeOptions & options)
: Node("talker", options), count_(0)
{// 在 "chatter" 主题上创建一个 "std_mgs/String" 消息的发布者。pub_ = create_publisher<std_msgs::msg::String>("chatter", 10);// 使用定时器来定期发布消息。timer_ = create_wall_timer(1s, this {return this->on_timer();});
}// 定时器回调函数
void Talker::on_timer()
{// 创建一个独特的消息auto msg = std::make_unique<std_msgs::msg::String>();// 设置消息数据msg->data = "Hello World: " + std::to_string(++count_);// 记录发布信息RCLCPP_INFO(this->get_logger(), "发布: '%s'", msg->data.c_str());// 刷新标准输出std::flush(std::cout);// 将消息放入队列中,由中间件处理。// 此调用是非阻塞的。pub_->publish(std::move(msg));
}}  // namespace composition 结束// 导入节点注册宏
#include "rclcpp_components/register_node_macro.hpp"// 使用 class_loader 注册组件。
// 这相当于一个入口点,允许在其库被加载到正在运行的进程时发现组件。
RCLCPP_COMPONENTS_REGISTER_NODE(composition::Talker)

没有主方法了

将您的主方法替换为 pluginlib 风格的宏调用。

#include <rclcpp_components/register_node_macro.hpp>
RCLCPP_COMPONENTS_REGISTER_NODE(palomino::VincentDriver)

 小心

如果您要替换的主方法包含 MultiThreadedExecutor ,请务必记下并确保您的容器节点是多线程的。请参阅下面的部分。

 CMake 变更 

首先,在 CMakeLists.txt 中添加 rclcpp_components 作为依赖项:

find_package(rclcpp_components REQUIRED)

其次,我们将用一个新的目标名称替换我们的 add_executable 为 add_library 。

add_library(vincent_driver_component src/vincent_driver.cpp)

第三,将使用旧目标的其他构建命令替换为作用于新目标的命令。即 ament_target_dependencies(vincent_driver ...) 变为 ament_target_dependencies(vincent_driver_component ...)

第四,添加一个新命令来声明您的组件。

rclcpp_components_register_node(vincent_driver_componentPLUGIN "palomino::VincentDriver"EXECUTABLE vincent_driver
)

第五,最后,将 CMake 中的任何安装命令从操作旧目标更改为安装库版本。例如,不要将任何目标安装到 lib/${PROJECT_NAME} 中。请用库安装替换。

ament_export_targets(export_vincent_driver_component)
install(TARGETS vincent_driver_componentEXPORT export_vincent_driver_componentARCHIVE DESTINATION libLIBRARY DESTINATION libRUNTIME DESTINATION bin
)

运行您的节点

查看组合教程https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Composition.html ,以深入了解节点的组合。快速而简洁的版本是,如果您在 Python 启动文件中有以下内容,

from launch_ros.actions import Node# ..ld.add_action(Node(package='palomino',executable='vincent_driver',# ..
))

你可以将它替换掉

from launch_ros.actions import ComposableNodeContainer
from launch_ros.descriptions import ComposableNode# ..
ld.add_action(ComposableNodeContainer(name='a_buncha_nodes',namespace='',package='rclcpp_components',executable='component_container',composable_node_descriptions=[ComposableNode(package='palomino',plugin='palomino::VincentDriver',name='vincent_driver',# ..extra_arguments=[{'use_intra_process_comms': True}],),]
))

 小心

如果您需要多线程,请不要将可执行文件设置为 component_container ,而应将其设置为 component_container_mt

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Socket网络通信流程

目录 创建Socket 绑定和监听(服务器端) 建立连接 数据传输 关闭连接 Socket不是一种协议,是对TCP/UDP等协议进行封装后供程序调用的接口,代码中调用相应的接口,即可将数据发送给对方,这种编程方式叫做socket编程。客户端建立一个socket,服务端建立一个socket,二者…

ELB和VPC是云计算领域中的两个术语,通常与Amazon Web Services (AWS)相关联

ELB 和 VPC 是云计算领域中的两个术语&#xff0c;通常与亚马逊云服务&#xff08;AWS&#xff09;相关&#xff1a; 1. **ELB (Elastic Load Balancer)**&#xff1a; - 这是AWS提供的一种服务&#xff0c;用于自动分配进入应用程序的流量&#xff0c;以实现高可用性和容错…

近红外光谱脑功能成像(fNIRS):2.实验设计、指标计算与多重比较

一、实验设计的策略与方法 近红外光谱成像&#xff08;INIRS&#xff09;作为一种非侵入性脑功能成像技术&#xff0c;为研究大脑活动提供了一种高效、生态效度高的方法。然而&#xff0c;为了充分利用INIRS技术并确保实验结果的准确性和可靠性&#xff0c;研究者必须精心设计实…

基于stm32开发的红外循迹小车

本项目算是接触32来开发的第一个小项目了&#xff0c;虽然前期用51写过一个循迹小车&#xff0c;以为直接转到32会比较简单&#xff0c;结果还是花了大几天才把小车的参数完全调完&#xff0c;以此来记录下自己的学习历程&#xff08;注&#xff1a;循迹算法并未加入PID算法&am…

spring boot集成easypoi导出word换行处理

项目场景&#xff1a; spring boot集成easypoi导出word <dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-spring-boot-starter</artifactId><version>4.4.0</version> </dependency> 问题描述 spring boo…

基于深度学习的RGB图像和IMU的数据融合

基于深度学习的RGB图像和IMU数据融合是一种结合视觉信息和惯性测量单元&#xff08;IMU&#xff09;数据以提升系统性能的方法。这种技术在机器人导航、无人机飞行控制、增强现实&#xff08;AR&#xff09;和虚拟现实&#xff08;VR&#xff09;等应用中具有重要意义。以下是关…

Spring AOP 通知的执行顺序

1. 结论 官方文档&#xff1a;Spring AOP Advice 故各种通知的执行顺序&#xff1a; Spring版本5.2.7以后&#xff1a; Around环绕通知前置操作Before前置通知目标方法After后置通知AfterReturnin返回通知或AfterThrowing异常通知Around环绕通知后置操作 Spring版本5.2.7一千…

最新的 DL/T645 调试工具,工程师必备

分享一个好用的 DL/T645 调试工具&#xff0c;下载地址&#xff1a;https://www.redisant.cn/dl645master 文章目录 最新的 DL/T645 调试工具&#xff0c;工程师必备主要功能软件截图 最新的 DL/T645 调试工具&#xff0c;工程师必备 DL/T645 是中国电力行业的一个通信协议标准…

Day47:LeedCode1143.最长公共子序列 1035.不相交的线 53. 最大子序和 392.判断子序列

1143. 最长公共子序列 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符的相对顺序的情况下删除某些字…

解决uni-app中全局设置页面背景颜色只有部分显示颜色的问题

在页面的style标签设置了背景色但是只显示一部分 <style lang"scss"> .content{background-color: #f7f7f7;height: 100vh; } </style>我们在app.vue里设置就行了 注意一定要是**page{}** <style>/*每个页面公共css */page{background-color: #…

淘宝商品评论电商API接口:提升销量与用户评论的策略

一、API接口简介 淘宝商品评论电商API接口是淘宝开放平台提供的一项服务&#xff0c;联讯数据通过这个接口&#xff0c;商家可以获取关于自己商品的评论数据&#xff0c;包括评论内容、评分、买家等级等信息。这些数据可以帮助商家更好地了解消费者需求&#xff0c;优化商品和服…

724.力扣每日一题7/8 Java

博客主页&#xff1a;音符犹如代码系列专栏&#xff1a;算法练习关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 目录 思路 解题方法 时间复杂度 空间复杂度 Code 思路 主要基于数组的…

linux主机离线安装python3环境

一、下载好python版本 Index of /ftp/python/https://www.python.org/ftp/python/ 二、创建文件夹 mkdir /home/python/ 三、上传到主机 四、解压 # 解压xz得到tar包 xz -d Python-3.9.8.tar.xz # 解压tar包 tar -xvf Python-3.9.8.tar 五、指定安装路径 # 进入解压后的…

Java:StringJoiner 类

文章目录 一、概念二、StringJoiner 类 一、概念 StringJoiner 跟 StringBuilder一样&#xff0c;创建之后里面的内容是可变的&#xff0c;它可以非常高效的进行字符串拼接&#xff0c;代码编写简洁。 二、StringJoiner 类 import java.util.StringJoiner;public class Test …

【Python_GUI】tkinter常用组件——文本类组件

文本时窗口中必不可少的一部分&#xff0c;tkinter模块中&#xff0c;有3种常用的文本类组件&#xff0c;通过这3种组件&#xff0c;可以在窗口中显示以及输入单行文本、多行文本、图片等。 Label标签组件 Label组件的基本使用 Label组件是窗口中比较常用的组件&#xff0c;…

【LeetCode】有效的数独

目录 一、题目二、解法 一、题目 请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 &#xff0c;验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&…

智能充电(新能源电动车,电单车)云管理系统的定制解决方案

一 系统简介 智能充电&#xff08;新能源电动车&#xff0c;电单车&#xff09;云管理系统 是一套能够实现对充电站/桩的实时通讯、状态监控、故障检测、运营分析、数据统计、策略设置的智能化多任务管理系统。 二 平台概览 智能充电云管理系统 https://chongdianzhuang.itg…

嵌入式Linux系统编程 — 7.4 fork、vfork函数创建子进程

目录 1 父进程与子进程概念 2 fork创建子进程 3 系统调用 vfork()函数 4 vfork与 fork函数如何选择 1 父进程与子进程概念 进程与子进程是操作系统中的一个基本概念&#xff0c;用于描述进程之间的层级关系。下面是对这一概念的简要说明&#xff1a; 父进程&#xff1a;在…

从项目中初识Autosar状态机转换

目录 0 前言 1 状态转换 1.1 BSM TO RMS 1.2 RMS TO RSS 1.3 RMS TO NOS 1.4 RSS TO PBSM 1.5 PBSM TO BSM 1.6 RSS TO NOS 1.7 RSS TO RMS 2 结尾 0 前言 之前在这篇《从项目中初识Autosar网络管理》已经和大家讲了Autosar网络管理的几个状态机以及定时器的大致概念&a…

Java:System 类

文章目录 一、概念二、常用方法2.1 exit()2.2 currentTimeMillis()2.3 arraycopy() 一、概念 System 类提供了对系统操作的一些方法&#xff0c;其中的方法都是静态的可以直接通过类名调用方法&#xff0c;构造方法是私有化无法实例化。 二、常用方法 2.1 exit() System.exi…