ROS2组件component自定义实现

ROS2系列文章目录

ROS2中nav_msgs/msg/Path 数据含义及使用

ROS2中std_msgs/msg/Header 数据含义及使用

ROS中TF变换详解

ROS2中launch编写及参数含义(launch.xml、python)


提示:阅读并实践本文档后,将掌握并理解ros1中nodelet用法,掌握并理解ros2中component用法

文章目录

  • ROS2系列文章目录
  • ROS中nodelet与component的作用
  • 一、创建功能包并添加依赖
  • 二、新建组件函数文件及修改CMakeLists.txt
    • 1.新建component实现函数
    • 2.修改CMakeLists.txt添加组件信息
      • 2.1 使用cmake添加依赖生成库文件
      • 2.2 构建组件实现
    • 3. 使用指令查看是否加载成功自定义组件
      • 3.1查询插件是否生成
      • 3.2 加载运行自定义插件
  • 总结


ROS中nodelet与component的作用

Nodelet/component旨在提供一种方法,在一台机器上、在一个进程中运行多个算法,在进程内传递消息时不会产生拷贝成本。ros1与ros2中的节点发布与订阅话题数据,本质是将数据打包后通过TCP或者UDP将数据发送、接收、解包后进行数据处理。当存在大量数据如点云、图像等会导致消息传送滞后,因此在同一台机器中,使用nodelet/component会很好的避免数据传输问题,使用该方法只需要发送一个指向该数据的指针,而不是通过TCP/UDP发送数据本身,消息传输会更快。

ROS2中Component官方资料:http://docs.ros.org/en/humble/Tutorials/Intermediate/Writing-a-Composable-Node.html


提示:以下是本篇文章正文内容,下面案例可供参考

本教程的主要目标为:生成一个自定义的组件信息test_component::Test1,功能包为test_component,该组件的主要功能为发布话题“/talker”,发送的数据类型为std_msg/msg/string。

一、创建功能包并添加依赖

创建test_component功能包,添加依赖rclcpp、std_msgs、rcl_components等,实现如下:

ros2 pkg create test_component --build-type ament_cmake --dependencies  rclcpp std_msgs rclcpp_components

在这里插入图片描述

二、新建组件函数文件及修改CMakeLists.txt

1.新建component实现函数

test_component/src目录下新建C++实现源文件,文件名为:my_component.cpp
在这里插入图片描述

2.修改CMakeLists.txt添加组件信息

2.1 使用cmake添加依赖生成库文件

在cmake中包含实现功能必要的头文件:

include_directories(${rclcpp_INCLUDE_DIRS} ${std_msgs_INCLUDE_DIRS} ${rclcpp_components_INCLUDE_DIRS})

使用add_library添加要生成的库,具体使用方法如下:

 add_library(<name> [STATIC | SHARED | MODULE]
             [EXCLUDE_FROM_ALL]
             [<source>...])

将src/my_component.cpp文件添加生产Test1库

add_library(Test1 src/my_component.cpp )

给Test1库链接ros2相关的lib

ament_target_dependencies(Test1 rclcpp std_msgs rcl_components)

添加声明新构建的组件: test_component::Test1

rclcpp_components_register_node(Test1 "test_component::Test1")

声明添加一个新的的组件test_component::Test1到ros2系统中去

rclcpp_components_register_nodes(Test1 "test_component::Test1")

最后,将生成的库安装在指定的目录

install(TARGETS Test1
        ARCHIVE DESTINATION lib
        LIBRARY DESTINATION lib
        RUNTIME DESTINATION bin
)

上述操作对应的CMakeLists.txt文件如下:

cmake_minimum_required(VERSION 3.8)
project(test_component)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
find_package(rclcpp_components REQUIRED)

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # comment the line when a copyright and license is added to all source files
  set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # comment the line when this package is in a git repo and when
  # a copyright and license is added to all source files
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()
include_directories(${rclcpp_INCLUDE_DIRS} ${std_msgs_INCLUDE_DIRS} ${rclcpp_components_INCLUDE_DIRS})
add_library(Test1 SHARED src/my_component.cpp )
ament_target_dependencies(Test1 rclcpp std_msgs rclcpp_components)
rclcpp_components_register_nodes(Test1 "test_component::Test1")
install(TARGETS Test1
        ARCHIVE DESTINATION lib
        LIBRARY DESTINATION lib
        RUNTIME DESTINATION bin
)
ament_package()

2.2 构建组件实现

初始化节点, 从Node继承的类开始,并定义了Test1构造函数,确保类的构造函数采用NodeOptions参数。

  explicit Test1(const rclcpp::NodeOptions & options):Node("test_node",options){
        // 创建话题发布者
        pub_ptr = this->create_publisher<std_msgs::msg::String>("/talker",10);
        // 创建定时器,定时1s后进入回调函数
        time_ptr = this->create_wall_timer(std::chrono::seconds(1),std::bind(&Test1::time_callback,this));
    }

使用RSO2中的pluginlib类似的宏调用声明

#include <rclcpp_components/register_node_macro.hpp>
// 给ROS系统调用提供宏定义接口
RCLCPP_COMPONENTS_REGISTER_NODE(test_component::Test1);

生成一个自定义的组件信息test_component::Test1的实现文件test_component.cpp如下:

#include <rclcpp/rclcpp.hpp>
#include <std_msgs/msg/string.hpp>
#include <chrono>
#include <string>
#include <rclcpp_components/register_node_macro.hpp>

namespace test_component{
    //继承rclcpp中的node节点,注意构建组件的构造函数有区别
    class Test1:public rclcpp::Node
    {

    public:
    // 构造函数中加入rclcpp::NodeOptions,并初始化
    explicit Test1(const rclcpp::NodeOptions & options):Node("test_node",options){
        // 创建话题发布者
        pub_ptr = this->create_publisher<std_msgs::msg::String>("/talker",10);
        // 创建定时器,定时1s后进入回调函数
        time_ptr = this->create_wall_timer(std::chrono::seconds(1),std::bind(&Test1::time_callback,this));
    }
    private:
    // 定时器指针
    rclcpp::TimerBase::ConstSharedPtr time_ptr;
    // 发布者话题指针
    rclcpp::Publisher<std_msgs::msg::String>::SharedPtr pub_ptr;
    // 话题发布数据
    std_msgs::msg::String data;
    // 定时器回调函数
    void time_callback(){
        static unsigned int i = 0;
        i++;
        data.data = std::to_string(i);
        pub_ptr->publish(data);
        RCLCPP_INFO(this->get_logger(),"进入定时器回调:%d",i);
    }
    };
};
// 给ROS系统调用提供宏定义接口
RCLCPP_COMPONENTS_REGISTER_NODE(test_component::Test1);

3. 使用指令查看是否加载成功自定义组件

3.1查询插件是否生成

使用ROS2推荐的colcon编译工具编译上述功能包后,执行一下指令:

source install/setup.bash
ros2 component types 

执行后输出结果中可以查看到是否已经加载自定义的组件信息
在这里插入图片描述

3.2 加载运行自定义插件

执行组件容器运行指令

ros2 run rclcpp_components component_container

执行完成后,可以通过查询ROS2中的节点指令确认是否启动成功

在这里插入图片描述

使用指令加载命令对生产的自定义插件加载

#ros2 component load /组件管理器名称  功能包  注册的组件名称
ros2 component load /ComponentManager test_component test_component::Test1 

执行上述指令后,在组件管理终端即可看到打印输出的日志信息

在这里插入图片描述使用节点管理工具以及话题打印工具查看是否正常显示节点以及话题内容

请添加图片描述


总结

本教程主要实现一个自定义的组件信息test_component::Test1,功能包为test_component,组件管理器启动加载该组件后,能够正常发布话题“/talker”,据类型为std_msg/msg/string。

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

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

相关文章

单元测试很难么?也没有吧

前言 你可能会用单元测试框架&#xff0c;python的unittest、pytest&#xff0c;Java的Junit、testNG等。 那么你会做单元测试么&#xff01;当然了&#xff0c;这有什么难的&#xff1f; test_demo.py def inc(x): return x 1 def test_answer(): assert inc(3) 4 i…

多模态实验记录--MMIM

1、遇到的问题 1.1 环境安装&#xff1a; 当使用比较新的显卡&#xff08;比如NVIDIA GeForce RTX 4090&#xff09;时&#xff0c;由于显卡的架构比较新&#xff0c;可能旧版本的pytorch库没有支持到。这时候就会出现capability sm_86 is not compatible的问题&#xff0c;同…

OpenCV(八)——基本线条操作

基本线条操作 OpenCV中提供了基本的线条的操作&#xff0c;包括画直线、画矩形、画圆形等。 &#xff08;1&#xff09;画直线&#xff0c;在OpenCV中利用line()画直线&#xff0c;形式为image_with_line cv2.line(image, start_point, end_point, color, thickness)。line(…

三星计划将其NAND闪存芯片价格上调最高20%

韩国媒体一份报告显示&#xff0c;三星电子的内存业务成功挺过了去年的市场低迷时期。最近&#xff0c;其减产策略终于见效&#xff0c;芯片价格随之上升。 据报导&#xff0c;今年第一季度&#xff0c;三星计划将其NAND闪存芯片价格上调最高20%&#xff0c;目标是恢复其内存芯…

面向对象【final关键字】

文章目录 final 关键字final 修饰类final 修饰方法final 修饰变量参考链接 final 关键字 在Java编程语言中&#xff0c;final关键字扮演着重要的角色&#xff0c;用于表示“最终的”或“不可更改的”特性。通过final关键字&#xff0c;可以对类、方法和变量进行限制和保护&…

【JavaScript】JavaScript 运算符 ② ( 表达式 与 返回值 | 自增 与 自减运算符 细节 | 前置自增运算符 | 后置自增运算符 )

文章目录 一、JavaScript 运算符1、表达式 与 返回值2、自增 与 自减运算符 细节3、前置自增运算符4、后置自增运算符5、自增 / 自减 运算符 代码示例 一、JavaScript 运算符 1、表达式 与 返回值 " 表达式 " 是 由 数字 , 运算符 , 变量 组成的 " 式子 " …

功能问题:如何用Docker部署一个后端项目?

大家好&#xff0c;我是大澈&#xff01; 本文约1800字&#xff0c;整篇阅读大约需要3分钟。 关注微信公众号&#xff1a;“程序员大澈”&#xff0c;免费加入问答群&#xff0c;一起交流技术难题与未来&#xff01; 现在关注公众号&#xff0c;免费送你 ”前后端入行大礼包…

VBA_MF系列技术资料1-400

MF系列VBA技术资料1-400 为了让广大学员在VBA编程中有切实可行的思路及有效的提高自己的编程技巧&#xff0c;我参考大量的资料&#xff0c;并结合自己的经验总结了这份MF系列VBA技术综合资料&#xff0c;而且开放源码&#xff08;MF04除外&#xff09;&#xff0c;其中MF01-0…

*Javaweb -- MyBatis*

一:介绍: 1.MyBatis是一个优秀的 ①持久层 ②框架,用于简化JDBC的开发! ①:JAVAEE有三层的结构:表现层, 业务层, 持久层. 表现层代表的是页面的展示,业务层则指的是对于相关逻辑的处理, 而持久层, 指的则是对于数据进行持久化,保存在数据库当中. 持久层具体的来说就是负责…

maven本地仓库依赖上传到远程仓库

本地仓库上传到远程仓库 批量上传&#xff1a; 批量本地仓库依赖&#xff08;jar包&#xff09;上传脚本&#xff1a; #!/bin/bash # copy and run this script to the root of the repository directory containing files # this script attempts to exclude uploading itse…

基础算法-分治算法-学习

现象&#xff1a; 基础算法-分治算法-学习 分而治之&#xff0c;将复杂问题分成小问题&#xff0c;小问题直接求解&#xff0c;最后合并得到最终结果&#xff0c; 和递归思想有点相近&#xff0c;也是区分小问题自己解决&#xff0c;所以在分治算法很多以递归的方式实现 每个…

客户案例|100M 768 维向量数据,Zilliz Cloud 稳定支持 Shulex VOC 业务场景

日前&#xff0c;国际化 VOC SaaS 公司数里行间&#xff08;Shulex&#xff09;将上亿数据量的核心业务从开源向量数据库 Milvus 迁移至全托管的向量数据库云服务 Zilliz Cloud。 相比于 Milvus&#xff0c;Zilliz Cloud 实现了 Shulex VOC 评论分析洞察报告生成速度 30% 的提升…

遥感深度学习:CNN-LSTM模型用于NDVI的预测(Pytorch代码深度剖析)

代码上传至Github库&#xff1a;https://github.com/ChaoQiezi/CNN-LSTM-model-is-used-to-predict-NDVI 01 前言 这是一次完整的关于时空遥感影像预测相关的深度学习项目&#xff0c;后续有时间更新后续部分。 通过这次项目&#xff0c;你可以了解&#xff1a; pytroch的模…

力扣● 1143.最长公共子序列 ● 1035.不相交的线 ● 53. 最大子序和 动态规划

● 1143.最长公共子序列 1.dp数组含义。 dp[i][j]&#xff1a;数组1[0,i-1]范围的子数组和数组2[0,j-1]的子数组的公共子序列最长长度。注意这里不需要一定以A[i-1]/B[j-1]结尾&#xff0c;原因在下面有说明。 动态规划求子序列的问题&#xff0c;一般都是dp的下标相对于数组…

YOLOv7-Openvino和ONNXRuntime推理【CPU】

纯检测系列&#xff1a; YOLOv5-Openvino和ONNXRuntime推理【CPU】 YOLOv6-Openvino和ONNXRuntime推理【CPU】 YOLOv8-Openvino和ONNXRuntime推理【CPU】 YOLOv7-Openvino和ONNXRuntime推理【CPU】 YOLOv9-Openvino和ONNXRuntime推理【CPU】 跟踪系列&#xff1a; YOLOv5/6/7-O…

EtherCAT开源主站 IGH 介绍及主站伺服控制过程

目录 前言 IGH EtherCAT主站介绍 主要特点和功能 使用场景 SOEM 主站介绍 SOEM 的特点和功能 SOEM 的使用场景 IGH 主站 和 SOEM对比 1. 功能和复杂性 2. 资源消耗和移植性 3. 使用场景 EtherCAT 通信原理 EtherCAT主站控制伺服过程 位置规划模式 原点复归模式…

渗透测试实战思路分析

免责声明&#xff1a;文章来源真实渗透测试&#xff0c;已获得授权&#xff0c;且关键信息已经打码处理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人…

Android图片加载-Glide4,Android多进程从头讲到尾

open fun load(context: WeakReference, url: String?, image: ImageView?, transformation: BitmapTransformation) { if (image null) return // 具体图片加载逻辑 } open fun load(holder: Int, context: WeakReference, url: String, image: ImageView?, width: Int, …

Slim-Neck by GSConv

paper&#xff1a;Slim-neck by GSConv: A better design paradigm of detector architectures for autonomous vehicles official implementation&#xff1a;https://github.com/alanli1997/slim-neck-by-gsconv 背景 目标检测是计算机视觉中一个重要的下游任务。对于车载…

UE4_AI_行为树_行为树快速入门指南

声明&#xff1a;学习笔记。 在 行为树快速入门指南 中&#xff0c;你将学会如何创建一个敌方AI&#xff0c;该AI看到玩家后会做出反应并展开追逐。当玩家离开视线后&#xff0c;AI将在几秒钟后&#xff08;这可根据你的需求进行调整&#xff09;放弃追逐&#xff0c;并在场景中…