【ROS2】概念:中级-组件

news2024/9/9 1:01:43

 目录

  • ROS 1 - 节点 vs. 节点组

  • ROS 2 - 统一 API

  •  编写组件

  •  使用组件

  •  实际应用

ROS 1 - 节点 vs. 节点组 

在 ROS 1 中,您可以将代码编写为 ROS node 或 ROS nodelet 。ROS 1 节点被编译成可执行文件。另一方面,ROS 1 nodelet 被编译成共享库,然后由容器进程在运行时加载。

ROS 2 - 统一 API 

在 ROS 2 中,推荐的编写代码方式类似于 nodelet - 我们称之为 Component 。这使得将常见概念添加到现有代码中变得容易,比如生命周期 https://design.ros2.org/articles/node_lifecycle.html 。在 ROS 1 中最大的缺点是有不同的 API,而在 ROS 2 中避免了这一点,因为两种方法使用相同的 API。

 注意

仍然可以使用“编写自己的主程序”的节点样式,但对于常见情况,不推荐这样做。

通过将流程布局设为部署时的决策,用户可以选择:

  • 在单独的进程中运行多个节点,具有进程/故障隔离的好处以及更容易调试单个节点

  • 在单个进程中运行多个节点,具有较低的开销,并且可选择更高效的通信(参见进程内通信 https://docs.ros.org/en/jazzy/Tutorials/Demos/Intra-Process-Communication.html )

此外, ros2 launch 可以通过专门的启动操作来自动化这些操作。

编写组件 

由于组件仅内置于共享库中,因此它没有 main 函数(请参阅 Talker 源代码 https://github.com/ros2/demos/blob/jazzy/composition/src/talker_component.cpp )。组件通常是 rclcpp::Node 的子类。由于它不控制线程,因此不应在其构造函数中执行任何长时间运行或阻塞的任务。相反,它可以使用计时器来获取定期通知。此外,它可以创建发布者、订阅者、服务器和客户端

#include "composition/talker_component.hpp" // 包含"composition/talker_component.hpp"头文件


#include <chrono>    // 包含时间库
#include <iostream>  // 包含输入输出流库
#include <memory>    // 包含智能指针库
#include <utility>   // 包含工具库


#include "rclcpp/rclcpp.hpp"         // 包含rclcpp库
#include "std_msgs/msg/string.hpp"   // 包含标准消息库


using namespace std::chrono_literals;  // 使用chrono字面量命名空间


namespace composition  // 定义composition命名空间
{


// 创建一个Talker "组件",它继承了通用的rclcpp::Node基类。
// 组件被构建成共享库,因此不编写自己的main函数。
// 使用组件的共享库的进程将实例化该类作为ROS节点。
Talker::Talker(const rclcpp::NodeOptions & options)
: Node("talker", options), count_(0)  // 构造函数初始化列表,设置节点名称为"talker",并初始化count_为0
{
  // 创建一个在"chatter"主题上发布"std_msgs/String"消息的发布者。
  pub_ = create_publisher<std_msgs::msg::String>("chatter", 10);  // 创建发布者,队列大小为10


  // 使用定时器安排周期性消息发布。
  timer_ = create_wall_timer(1s, [this]() {return this->on_timer();});  // 创建定时器,每1秒调用一次on_timer函数
}


void Talker::on_timer()  // 定时器回调函数
{
  auto msg = std::make_unique<std_msgs::msg::String>();  // 创建一个唯一指针,指向std_msgs::msg::String类型的消息
  msg->data = "Hello World: " + std::to_string(++count_);  // 设置消息数据为"Hello World: "加上当前计数
  RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", msg->data.c_str());  // 打印日志信息
  std::flush(std::cout);  // 刷新标准输出流


  // 将消息放入队列中由中间件处理。
  // 这个调用是非阻塞的。
  pub_->publish(std::move(msg));  // 发布消息
}


}  // namespace composition


#include "rclcpp_components/register_node_macro.hpp"  // 包含rclcpp组件注册宏头文件


// 使用class_loader注册组件。
// 这作为一种入口点,使组件在其库加载到运行进程中时可被发现。
RCLCPP_COMPONENTS_REGISTER_NODE(composition::Talker)  // 注册composition::Talker组件

将这样的类制作成组件的一个重要方面是,该类使用包 rclcpp_components 中的宏注册自身(请参见源代码的最后一行)。这使得在将其库加载到正在运行的进程中时可以发现该组件 - 它充当了一种入口点。

此外,一旦组件创建完成,必须将其注册到索引中,以便工具能够发现它。

add_library(talker_component SHARED src/talker_component.cpp)
rclcpp_components_register_nodes(talker_component "composition::Talker")
# To register multiple components in the same shared library, use multiple calls
# rclcpp_components_register_nodes(talker_component "composition::Talker2")

例如,请查看本教程 

https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Writing-a-Composable-Node.html

 注意

为了使 component_container 能够找到所需的组件,必须从已获取相应工作区的 shell 中执行或启动它。

 使用组件 

组合包https://github.com/ros2/demos/tree/jazzy/composition 包含几种不同的方法来使用组件。最常见的三种方法是:

  1. 启动一个(通用容器进程 https://github.com/ros2/rclcpp/blob/jazzy/rclcpp_components/src/component_container.cpp )并调用容器提供的 ROS 服务 load_node。然后,ROS 服务将加载由传递的包名和库名指定的组件,并在正在运行的进程中开始执行它。除了以编程方式调用 ROS 服务外,您还可以使用命令行工具通过传递的命令行参数来调用 ROS 服务

  2. 创建一个包含多个在编译时已知节点的自定义可执行 https://github.com/ros2/demos/blob/jazzy/composition/src/manual_composition.cpp 文件。这种方法要求每个组件都有一个头文件(对于第一种情况,这不是严格需要的)。

  3. 创建一个启动文件,并使用 ros2 launch 创建一个加载了多个组件的容器进程。

 实际应用 

试用 Composition 演示。https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Composition.html

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

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

相关文章

C#网络连接:TCP/IP模式下的网络连接与同步

1&#xff0c;目的 为了测试局域网的消息同步&#xff0c;简单写了下TCP/IP模式的同步&#xff0c;参考这个帖子。 2&#xff0c;核心库部分 using System; using System.Net; using System.Net.Sockets; using System.Text;namespace Coldairarrow.Util.Sockets {/// <s…

【React】useEffect 钩子详解

文章目录 一、useEffect 概念二、useEffect 的基本用法1. 无依赖项2. 空依赖项数组3. 带依赖项的 useEffect 三、useEffect 的常见应用场景1. 数据获取2. 订阅与清除3. 动画与定时器 四、useEffect 的进阶用法1. 多个 useEffect2. 条件执行副作用 五、注意事项 useEffect 是 Re…

playbooks 分布式部署 LNMP

1、环境配置 ansible 服务器 192.168.10.10nginx 服务器 192.168.10.20mysql 服务器 192.168.10.21php 服务器 192.168.10.22 2、安装 ansble #192.168.10.10节点 yum install -y epel-release #先安装 epel 源 yum install -y ansible配置主机清单 …

Vue 动态改变css文件

theme: smartblue 一、背景需求 现有 Vue3 项目&#xff0c;要求点击按钮后&#xff0c;会动态加载css文件内容 二、实现过程 2.1 相关代码 假设有 blue.css 和 red.css,要求点击加载对应文件 若想切换为原版样式&#xff0c;点击 back 回退到初始样式 this is a simple text …

76.SAP ME - 归档

目录 1.归档 2.系统设置维护 3.后台处理执行 1.归档 可使用此功能将某一特定已完成产品的相关记录从活动的“在制品”(WIP) 数据库移动到归档数据库&#xff0c;这样可改进生产记录的检索。在一段时间内&#xff0c;WIP 数据库中的记录数量将增加。当系统在大量记录中进行搜…

c++ 内存管理(newdeletedelete[])

因为在c里面新增了类&#xff0c;所以我们在有时候会用malloc来创建类&#xff0c;但是这种创建只是单纯的开辟空间&#xff0c;没有什么默认构造的。同时free也是free的表面&#xff0c;如果类里面带有指针指向堆区的成员变量就会free不干净。 所以我们c增加了new delete和de…

pdf太大怎么压缩大小?这几种压缩方法操作起来很简单!

pdf太大怎么压缩大小&#xff1f;在数字化洪流席卷的当下&#xff0c;PDF文件的“臃肿”难题如同巨石般横亘于高效办公之路&#xff0c;它们不仅贪婪地吞噬着宝贵的存储空间&#xff0c;更如沉重的枷锁&#xff0c;拖曳着我们的工作进度&#xff0c;步入迟缓之境&#xff0c;试…

06 内置的整数、实数与复数

在 Python 中&#xff0c;内置的数字类型有整数、实数和复数&#xff0c;借助于标准库 fractions 中的 Fraction 对象可以实现分数及其运算&#xff0c;而 fractions 中的 Decimal 类则实现了更高精度的运算。 Python 支持任意大的数字&#xff0c;具体可以大到什么程度仅受内…

电阻液冷 可提升 3.3kV 中压负载-EAK水冷电阻器

电阻液冷 可提升 3.3kV 中压负载-EAK水冷电阻器 在工业和海洋应用中&#xff0c;水冷在削减电阻器封装方面至关重要的地方 在起重机、升降机、升降机和输送机等电机驱动应用中&#xff0c;风冷电阻器很常见&#xff0c;但在中压、高功率应用中&#xff0c;液体冷却胜出。 使…

IDEA项目的依赖(pom.xml文件)导入问题及解决

前言&#xff1a;该文章为转载&#xff0c;没有仔细的看 IDEA新建项目和pom.xml文件被修改时&#xff0c;右下角都会出现 Maven projects need to be imported&#xff08;项目需要导入依赖&#xff09; 如下&#xff0c;点击 Import Changes导入后&#xff0c;有时会一直处于…

【基础篇】Docker 概览 ONE

嗨&#xff0c;大家好&#xff01;我是小竹笋&#xff0c;一名热爱创作的工程师。今天我将带领大家一起踏上探索 Docker 的奇妙之旅。我们先从 Docker 的历史和发展说起&#xff0c;然后再看看 Docker 和虚拟机之间的区别&#xff0c;最后了解一下 Docker 在各行各业的应用情况…

数据结构算法经典题目刨析(c语言)返回单链表的倒数第 k 个节点

&#x1f493; 博客主页&#xff1a;C-SDN花园GGbond ⏩ 文章专栏&#xff1a;数据结构经典题目刨析(c语言) 一.题目描述 二.解题思路 方法一:计数器方式 先遍历链表&#xff0c;求出链表长度count倒数第k个节点&#xff0c;就是正数第count-k1个节点&#xff08;下标为count…

《系统架构设计师教程(第2版)》第13章-层次式架构设计理论与实践-02-表现层框架设计

文章目录 1. 表现层设计模式1.1 MVC模式1.1.1 三个核心模块1&#xff09;控制器 (Controller)2&#xff09;模型 (Model)3&#xff09;视图 (View): 1.1.2 过程1.1.3 优点1.1.4 应用 1.2 MVP模式1.3 MVVM模式 2. 使用XML设计表现层统一Web Form与 Windows Form的外观3. 表现层中…

⚠️ Buffer Overflow: 安全编码必备知识 ️

⚠️ Buffer Overflow: 安全编码必备知识 &#x1f6e1;️ ⚠️ Buffer Overflow: 安全编码必备知识 &#x1f6e1;️摘要引言正文内容一、缓冲区溢出基本概念 &#x1f9e9;二、常见场景及实际案例 &#x1f6e0;️2.1 利用不安全的函数2.2 堆溢出攻击 三、调试技巧 &#x1f…

算法入门:Java实现排序、查找算法

链接&#xff1a;算法入门&#xff1a;Java实现排序、查找算法 (qq.com) 冒泡/选择/插入/希尔排序代码 (qq.com) 快排/归并/堆排/基数排序代码 (qq.com)

Python酷库之旅-第三方库Pandas(053)

目录 一、用法精讲 196、pandas.Series.first方法 196-1、语法 196-2、参数 196-3、功能 196-4、返回值 196-5、说明 196-6、用法 196-6-1、数据准备 196-6-2、代码示例 196-6-3、结果输出 197、pandas.Series.head方法 197-1、语法 197-2、参数 197-3、功能 1…

【C++题解】1069. 字符图形5-星号梯形

问题&#xff1a;1069. 字符图形5-星号梯形 类型&#xff1a;嵌套循环、图形输出 题目描述&#xff1a; 打印字符图形。 输入&#xff1a; 一个整数&#xff08; 0<n<10 &#xff09;。 输出&#xff1a; 一个字符图形。 样例&#xff1a; 输入&#xff1a; 3输…

卷积神经网络(三)---案例分析

上面部分介绍了 PyTorch 中的卷积模块&#xff0c;接下来将会介绍几个卷积神经网络的案例&#xff0c;通过案例入手来介绍卷积神经网络的结构设计。 1. LeNet LeNet 是整个卷积神经网络的开山之作&#xff0c;1998年由 LeCun 提出&#xff0c;它的结构特别简单&#xff0c;我们…

看懂循环队列

循环队列的设计过程 1.循环队列2.设计循环队列的逻辑过程2.1 定义循环队列的数据结构2.2 初始化队列2.3 入队操作2.4. 出队操作2.5 判断队列状态2.5 获取队头和队尾的元素力扣相关题目完整代码 1.循环队列 循环队列是使用有限数组来模拟队列&#xff0c;与普通的队列不同的是&…