ROS2 入门应用 发布和订阅(C++)
ROS2 入门应用 发布和订阅(C++)
- 1. 创建功能包
- 2. 创建源文件
- 2.1. 话题发布
- 2.2. 话题订阅
- 3. 添加依赖关系
- 4. 添加编译信息
- 4.1. 添加搜索库
- 4.2. 增加可执行文件
- 4.3. 增加可执行文件位置
- 5. 编译和运行
1. 创建功能包
在《ROS2 入门应用 工作空间》中已创建和加载了ros2_ws
工作空间
在《ROS2 入门应用 元功能包(C++)》中已创建和加载了my_package
功能包
那么就创建一个独立的cpp_pubsub
功能包来做话题发布和订阅的功能
cd ~/ros2_ws/src
ros2 pkg create --build-type ament_cmake cpp_pubsub
2. 创建源文件
进入cpp_pubsub
功能包的src
文件夹
cd ~/ros2_ws/src/cpp_pubsub/src
2.1. 话题发布
新建publisher_member_function.cpp
话题发布源文件
nano publisher_member_function.cpp
复制 ROS2 官方例程 的内容到文件中:
#include <chrono>
#include <functional>
#include <memory>
#include <string>#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"/* 方便表示时间 */
using namespace std::chrono_literals;/* This example creates a subclass of Node and uses std::bind() to register a
* member function as a callback from the timer. *//* 继承rclcpp:: node创建节点类MinimalPublisher */
class MinimalPublisher : public rclcpp::Node
{public:/* 公共构造函数将节点命名为minimal_publisher,并将count_初始化为0 */MinimalPublisher(): Node("minimal_publisher"), count_(0){/* 初始化发布者publisher_ ,使用String消息类型、主题名称topic和在发生备份时限制消息所需的队列大小10 */publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);/* 初始化timer_,设置timer_callback函数每500ms执行一次 */timer_ = this->create_wall_timer(500ms, std::bind(&MinimalPublisher::timer_callback, this));}private:/* 定义定时器回调函数 */void timer_callback(){/* 打印并发布字符串信息 */auto message = std_msgs::msg::String();message.data = "Hello, world: " + std::to_string(count_++);RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());publisher_->publish(message);}/* 计时器、发布者和计数器字段的声明 */rclcpp::TimerBase::SharedPtr timer_;rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;size_t count_;
};int main(int argc, char * argv[])
{/* 初始化ROS2 */rclcpp::init(argc, argv);/* 运行节点MinimalPublisher */rclcpp::spin(std::make_shared<MinimalPublisher>());/* 退出ROS2 */rclcpp::shutdown();return 0;
}
2.2. 话题订阅
新建subscriber_member_function.cpp
话题订阅源文件
nano subscriber_member_function.cpp
复制 ROS2 官方例程 的内容到文件中:
#include <memory>#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"/* 占位符,代替回调函数中的第一个参数 */
using std::placeholders::_1;/* 继承rclcpp:: node创建节点类MinimalSubscriber */
class MinimalSubscriber : public rclcpp::Node
{public:/* 公共构造函数将节点命名为minimal_subscriber */MinimalSubscriber(): Node("minimal_subscriber"){/* 初始化订阅者subscription_ ,使用String消息类型、主题名称topic和在发生备份时限制消息所需的队列大小10,订阅话题回调函数topic_callback */subscription_ = this->create_subscription<std_msgs::msg::String>("topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));}private:/* 定义订阅话题回调函数 */void topic_callback(const std_msgs::msg::String & msg) const{/* 打印话题消息的字符串信息 */RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg.data.c_str());}/* 订阅者字段的声明 */rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};int main(int argc, char * argv[])
{/* 初始化ROS2 */rclcpp::init(argc, argv);/* 运行节点MinimalSubscriber*/rclcpp::spin(std::make_shared<MinimalSubscriber>());/* 退出ROS2 */rclcpp::shutdown();return 0;
}
3. 添加依赖关系
在package.xml
清单文件中
找到<buildtool_depend>ament_cmake</buildtool_depend>
依赖项,在其下面添加源文件所需的依赖(depend):
<depend>rclcpp</depend>
<depend>std_msgs</depend>
这声明了功能包在执行代码时需要rclcpp
和std_msgs
4. 添加编译信息
在CMakeLists.txt
编译文件中
4.1. 添加搜索库
首先,找到find_package(ament_cmake REQUIRED)
依赖项,在其下面添加搜索源文件所需(REQUIRED)的库:
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
4.2. 增加可执行文件
然后,再增加可执行文件,
src/publisher_member_function.cpp
命名为talker
可执行文件,
src/subscriber_member_function.cpp
命名为listener
可执行文件,
并添加目标依赖关系:
add_executable(talker src/publisher_member_function.cpp)
ament_target_dependencies(talker rclcpp std_msgs)add_executable(listener src/subscriber_member_function.cpp)
ament_target_dependencies(listener rclcpp std_msgs)
4.3. 增加可执行文件位置
最后,增加可执行文件位置,这样ROS2就可以找到现在的可执行文件:
install(TARGETStalkerlistener DESTINATION lib/${PROJECT_NAME})
5. 编译和运行
进入工作空间根目录
cd ~/ros2_ws
在编译之前检查缺失的依赖项(可跳过):
rosdep install -i --from-path src --rosdistro humble -y
编译:
colcon build --packages-select cpp_pubsub
打开一个新终端,运行话题发布节点:
ros2 run cpp_pubsub talker# [INFO] [minimal_publisher]: Publishing: 'Hello World: 0'
# [INFO] [minimal_publisher]: Publishing: "Hello World: 1"
# [INFO] [minimal_publisher]: Publishing: 'Hello World: 2'
打开一个新终端,运行话题订阅节点:
ros2 run cpp_pubsub listener# [INFO] [minimal_subscriber]: I heard: 'Hello World: 11'
# [INFO] [minimal_subscriber]: I heard: 'Hello World: 12'
# [INFO] [minimal_subscriber]: I heard: 'Hello World: 13'
谢谢
相关文章:
ROS2 入门应用 发布和订阅(C++)
ROS2 入门应用 发布和订阅(C)1. 创建功能包2. 创建源文件2.1. 话题发布2.2. 话题订阅3. 添加依赖关系4. 添加编译信息4.1. 添加搜索库4.2. 增加可执行文件4.3. 增加可执行文件位置5. 编译和运行1. 创建功能包 在《ROS2 入门应用 工作空间》中已创建和加…...

XSS漏洞,通过XSS实现网页挂马
**今天讲下通过XSS实现网页挂马~*,目的是了解安全方面知识,提升生活网络中辨别度 原理: 实验分为两部分: 1、通过Kali linux,利用MS14_064漏洞,制作一个木马服务器。存在该漏洞的用户一旦通过浏览器访问木…...

家政服务小程序实战教程09-图文卡片
小程序还有一类需求就是展示服务的列表,我们这里用图文卡片组件来实现,我们先要添加一个标题,使用网格布局来实现 第一列添加一个文本组件,第二列添加一个图标组件 修改文本组件的文本内容,设置外边距 设置第二列的样式…...

国内唯一一部在CentOS下正确编译安装和使用RediSearch的教程
开篇 Redis6开始增加了诸多激动人心的模块,特别是:RedisJSON和RediSearch。这两个模块已经完全成熟了。它们可以直接使用我们的生产上的Redis服务器来做全文搜索(二级搜索)以取得更廉价的硬件成本、同时在效率上竟然超过了Elastic…...

前端对于深拷贝和浅拷贝的应用和思考
浅拷贝 浅拷贝 : 浅拷贝是指对基本类型的值拷贝,以及对对象类型的地址拷贝。它是将数据中所有的数据引用下来,依旧指向同一个存放地址,拷贝之后的数据修改之后,也会影响到原数据的中的对象数据。最简单直接的浅拷贝就…...

Java基础常见面试题(三)
String 字符型常量和字符串常量的区别? 形式上: 字符常量是单引号引起的一个字符,字符串常量是双引号引起的若干个字符; 含义上: 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算;字符串常量代表一个地址值…...

C++设计模式(13)——装饰模式
亦称: 装饰者模式、装饰器模式、Wrapper、Decorator 意图 装饰模式是一种结构型设计模式, 允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。 问题 假设你正在开发一个提供通知功能的库, 其他程序可使用它向用户发…...

ESP-01S通过AT指令上报数据到阿里云物模型
ESP-01S使用AT指令上报数据到阿里云物模型 上篇文章介绍了如何用AT指令连接阿里云并进行通信:https://blog.csdn.net/weixin_46251230/article/details/128995530 但最终需要将传感器数据上报到云平台显示,所以需要建立阿里云物模型 阿里云平台建立物…...

【强化学习】马尔可夫决策过程MDP
1.马尔可夫决策过程MDP 1.1 MDP五元组 MDP<S,A,P,R,γ>MDP<\mathcal{S},\mathcal{A},\mathcal{P},\mathcal{R},\mathcal{\gamma}>MDP<S,A,P,R,γ>,其中: S\mathcal{S}S:状态空间A\mathcal{A}A:动作空间P\mathc…...

刘润:五维思考,让你站得更高、看得更远
原标题:刘润:五维思考,让你站得更高、看得更远 前言:遇到问题时,有的人很快就能想明白,有的人需要很久才能想明白,还有的人始终都想不明白。 而且,那些很快就能想明白的人࿰…...

从运维角度看微服务 k8s部署微服务【偏理论】【AL】
从运维角度看微服务 & 部署微服务【偏理论】 1、微服务的特点 服务组件化: 每个服务独立开发、部署,有效避免一个服务的修改引起整个系统重新部署。 技术栈灵活: 约定通信方式,使得服务本身功能实现对技术要求不再那么敏感。…...

专题 | 防抖和节流
一 防抖:单位时间内,频繁触发事件,只执行最后一次 场景:搜索框搜索输入(利用定时器,每次触发先清掉以前的定时器,从新开始) 节流:单位时间内,频繁触发事件&…...
C++入门:重载运算符和重载函数
C 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。当您调用一个重载函…...
conda 新建虚拟环境 等等
1:conda create -n env_name package_name #创建名为env_name的新环境,并在该环境下安装名为package_name 的包,例如:conda create -n Arg python3.8 # 创建名字为Arg python为3.8版本的虚拟环境2: conda activate env…...

【C++:STL之栈和队列 | 模拟实现 | 优先级队列 】
目录 1. stack的介绍和使用 1.1 stack的介绍 1.2 stack的使用 2 栈的模拟实现 3 queue的介绍和使用 3.1 queue的介绍 3.2 queue的使用 4 queue的模拟实现 5 deque的介绍 5.1deque的原理介绍 5.2 deque的缺陷 5.3 为什么选择deque作为stack和queue的底层默认容器 6 p…...

基于SpringBoot+Vue的疫苗预约管理系统(Java项目)
【辰兮要努力】:hello你好我是辰兮,很高兴你能来阅读,昵称是希望自己能不断精进,向着优秀程序员前行! 博客来源于项目以及编程中遇到的问题总结,偶尔会有读书分享,我会陆续更新Java前端、后台、…...
华为OD机试 - 计算网络信号(Python),真题含思路
计算网络信号 题目 网络信号经过传递会逐层衰减,且遇到阻隔物无法直接穿透,在此情况下需要计算某个位置的网络信号值。 注意:网络信号可以绕过阻隔物 array[m][n] 的二维数组代表网格地图,array[i][j] = 0 代表 i 行 j 列是空旷位置;array[i][j] = x ( x 为正整数)代表 i …...

【Spring】注解实现IOC操作,你理解了吗?
作者:狮子也疯狂 专栏:《spring开发》 坚持做好每一步,幸运之神自然会驾凌在你的身上 专栏推荐:写文章刚刚起步,各个专栏的知识点后续会补充完善,不断更新好文,希望大 家支持一下。 专栏名字El…...
微搭低代码从入门到精通01-总体介绍
在过去我们开发小程序,要学习各类知识。比如前端知识、后端知识、服务器知识及各种中间件及数据库的知识。 要想学会这些知识,既需要投入大量的学习时间,而且要经过相当的实践才可以掌握。 如果立志从事开发行业,投入精力去学习…...

类的继承
类的继承:一个类继承另一个类,自动拥有这个类的属性和方法,类似于包含与被包含的关系。被继承的类称为父类--子类则是继承父类的类。一个父类可以有多个子类;一个子类可以有多个父类(多继承)问题创建子类时…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...

如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...