news 2026/4/16 9:04:04

Ros2主题的:发布、订阅 demo

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ros2主题的:发布、订阅 demo

1、创建文件夹、创建功能包

# 创建文件夹mkdirros2_dir# 进入文件夹, 创建src, 进入srccdros2_dirmkdirsrccdsrc# 创建功能包ros2 pkg create pub_sub_pkg --build-type ament_cmake --dependencies rclcpp std_msgs

2、创建节点:发布主题

  • publisher_member_function.cpp
/** * @file publisher_member_function.cpp * @brief ROS 2 发布者示例:周期性向"topic"话题发布字符串消息 * @details 基于rclcpp实现,使用类封装Node,通过定时器周期性触发消息发布 */ // 1. 引入核心依赖头文件 #include <rclcpp/rclcpp.hpp> // ROS 2 C++核心库:提供Node、发布者、定时器、日志等核心功能 #include <std_msgs/msg/string.hpp> // ROS 2标准字符串消息类型:定义话题通信的消息格式 #include <chrono> // C++标准时间库:用于设置定时器周期 #include <string> // C++标准字符串库:用于消息内容拼接 // 引入chrono字面量(如500ms),避免写std::chrono::milliseconds(500),简化代码 using namespace std::chrono_literals; /** * @class MinimalPublisher * @brief 自定义发布者类,继承自rclcpp::Node(ROS 2所有功能的核心载体) * @details 封装发布者对象、定时器对象和消息计数器,通过定时器回调实现周期性发布 */ class MinimalPublisher : public rclcpp::Node { public: /** * @brief 构造函数:初始化节点、创建发布者、创建定时器 * @details * 1. 调用父类Node的构造函数,设置节点名称为"minimal_publisher"(全局唯一) * 2. 初始化消息计数器count_为0 * 3. 创建发布者对象,绑定话题名和队列大小 * 4. 创建定时器对象,绑定回调函数和触发周期 */ MinimalPublisher() : Node("minimal_publisher"), // 初始化父类Node,节点命名为"minimal_publisher" count_(0) // 初始化消息计数器,记录发布的消息数量 { // 创建发布者对象 // 模板参数:发布的消息类型(必须与订阅者一致) // 参数1:话题名称"topic"(订阅者需订阅该话题才能接收消息) // 参数2:队列大小10(消息积压时最多缓存10条,超出则丢弃旧消息,避免内存溢出) publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10); // 创建定时器对象(壁钟定时器,基于系统时间) // 参数1:定时器周期500ms(每500毫秒触发一次回调函数) // 参数2:回调函数绑定(将类的成员函数timer_callback绑定到当前对象) timer_ = this->create_wall_timer( 500ms, std::bind(&MinimalPublisher::timer_callback, this) // bind保证回调函数能访问类的成员变量 ); // 打印初始化日志(可选,用于确认发布者创建成功) RCLCPP_INFO(this->get_logger(), "MinimalPublisher node initialized, start publishing..."); } private: /** * @brief 定时器回调函数:每次定时器触发时执行,负责构建并发布消息 * @details * 1. 创建字符串消息对象 * 2. 拼接消息内容(包含计数器,每次发布后自增) * 3. 打印发布日志(便于调试) * 4. 发布消息到"topic"话题 */ void timer_callback() { // 创建std_msgs::msg::String类型的消息对象(自动生命周期管理) auto message = std_msgs::msg::String(); // 拼接消息内容:计数器count_自增,生成带计数的字符串 message.data = "Hello, ROS 2! Count: " + std::to_string(count_++); // 打印INFO级日志:输出当前发布的消息内容 // this->get_logger()获取节点的日志器,RCLCPP_INFO是ROS 2日志宏(支持DEBUG/WARN/ERROR/FATAL) RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str()); // 发布消息:将消息发送到"topic"话题,所有订阅该话题的节点都会收到 publisher_->publish(message); } // 类成员变量(私有化,避免外部直接修改) rclcpp::TimerBase::SharedPtr timer_; // 定时器智能指针:ROS 2推荐用智能指针管理资源,自动释放 rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_; // 发布者智能指针 size_t count_; // 消息计数器:记录已发布的消息数量(size_t是无符号整型,适合计数) }; /** * @brief 主函数:ROS 2程序入口,负责初始化、运行节点、释放资源 * @param argc 命令行参数个数 * @param argv 命令行参数数组 * @return int 程序退出码(0表示正常退出) * @details * 1. 初始化ROS 2上下文(全局资源,必须先调用) * 2. 创建发布者节点的智能指针(ROS 2推荐用智能指针管理节点) * 3. 自旋节点(进入事件循环,处理定时器回调等异步事件) * 4. 关闭ROS 2上下文,释放资源 */ int main(int argc, char * argv[]) { // 初始化ROS 2上下文:解析命令行参数,初始化全局资源(如DDS通信层) rclcpp::init(argc, argv); // 自旋节点:阻塞当前线程,持续运行事件循环 // std::make_shared创建MinimalPublisher对象的智能指针,自动管理内存 // spin会处理所有异步事件(定时器回调、消息发布等),直到节点被关闭(如Ctrl+C) rclcpp::spin(std::make_shared<MinimalPublisher>()); // 关闭ROS 2上下文:释放全局资源,必须与init配对使用 rclcpp::shutdown(); // 程序正常退出 return 0; }

3、创建节点:订阅主题

  • subscriber_member_function.cpp
/** * @file subscriber_member_function.cpp * @brief ROS 2 订阅者示例:订阅"topic"话题并接收/打印字符串消息 * @details 基于rclcpp实现,使用类封装Node,通过回调函数处理接收到的话题消息 */ // 1. 引入核心依赖头文件 #include <rclcpp/rclcpp.hpp> // ROS 2 C++核心库:提供Node、订阅者、日志等核心功能 #include <std_msgs/msg/string.hpp> // ROS 2标准字符串消息类型:与发布者保持一致的消息格式 /** * @class MinimalSubscriber * @brief 自定义订阅者类,继承自rclcpp::Node(ROS 2所有功能的核心载体) * @details 封装订阅者对象,通过回调函数响应话题消息,实现异步接收消息 */ class MinimalSubscriber : public rclcpp::Node { public: /** * @brief 构造函数:初始化节点、创建订阅者 * @details * 1. 调用父类Node的构造函数,设置节点名称为"minimal_subscriber"(全局唯一) * 2. 创建订阅者对象,绑定话题名、队列大小和消息回调函数 */ MinimalSubscriber() : Node("minimal_subscriber") // 初始化父类Node,节点命名为"minimal_subscriber" { // 创建订阅者对象 // 模板参数:订阅的消息类型(必须与发布者完全一致,否则无法解析消息) // 参数1:话题名称"topic"(必须与发布者的话题名一致,才能接收对应消息) // 参数2:队列大小10(缓存未处理的消息,超出则丢弃旧消息,避免内存溢出) // 参数3:消息回调函数绑定(收到消息时触发topic_callback,_1为消息参数占位符) subscription_ = this->create_subscription<std_msgs::msg::String>( "topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, std::placeholders::_1) ); // 打印初始化日志(可选,用于确认订阅者创建成功) RCLCPP_INFO(this->get_logger(), "MinimalSubscriber node initialized, start listening..."); } private: /** * @brief 话题消息回调函数:收到消息时自动执行,处理接收到的字符串消息 * @param msg 接收到的消息智能指针(ROS 2推荐用SharedPtr,避免拷贝+自动内存管理) * @details 打印接收到的消息内容,支持后续扩展(如消息解析、业务逻辑处理等) */ void topic_callback(const std_msgs::msg::String::SharedPtr msg) { // 打印INFO级日志:输出接收到的消息内容 // this->get_logger()获取节点日志器,msg->data.c_str()将C++ string转为C风格字符串 RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg->data.c_str()); } // 类成员变量(私有化,避免外部直接修改) rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_; // 订阅者智能指针 // ROS 2通过智能指针管理资源,自动释放 }; /** * @brief 主函数:ROS 2程序入口,负责初始化、运行节点、释放资源 * @param argc 命令行参数个数 * @param argv 命令行参数数组 * @return int 程序退出码(0表示正常退出) * @details * 1. 初始化ROS 2上下文(全局资源,必须先调用) * 2. 创建订阅者节点的智能指针(ROS 2推荐用智能指针管理节点生命周期) * 3. 自旋节点(进入事件循环,持续监听话题消息,触发回调函数) * 4. 关闭ROS 2上下文,释放全局资源 */ int main(int argc, char * argv[]) { // 初始化ROS 2上下文:解析命令行参数,初始化DDS通信层、节点管理器等全局资源 rclcpp::init(argc, argv); // 自旋节点:阻塞当前线程,持续运行事件循环 // std::make_shared创建MinimalSubscriber对象的智能指针,自动管理内存 // spin会监听"topic"话题的消息,收到消息时触发topic_callback,直到节点被关闭(如Ctrl+C) rclcpp::spin(std::make_shared<MinimalSubscriber>()); // 关闭ROS 2上下文:释放全局资源,必须与init配对使用 rclcpp::shutdown(); // 程序正常退出 return 0; }

4、CMakeLists.txt 追加内容

  • find_package 函数后面加入如下内容
# ==============================================================================# 编译可执行文件 & 配置依赖 & 安装# 核心逻辑:编译源码生成可执行文件 → 链接 ROS 2 依赖库 → 安装到标准路径(支持 ros2 run 调用)# ==============================================================================# 1. 编译发布者可执行文件# add_executable:CMake 核心指令,将指定源码编译为可执行文件# 参数1:可执行文件名称(自定义,对应 ros2 run 命令的第二个参数,如 ros2 run 包名 talker)# 参数2:待编译的源码文件路径(src/ 是ROS 2包的标准源码目录)add_executable(talker src/publisher_member_function.cpp)# 2. 为发布者可执行文件绑定ROS 2依赖# ament_target_dependencies:ROS 2封装的CMake指令,替代原生CMake的include_directories+target_link_libraries# 作用:# - 自动查找 rclcpp/std_msgs 包的头文件路径(如 /opt/ros/humble/include)# - 自动链接依赖库(如 librclcpp.so、libstd_msgs.so)# - 自动设置编译选项(如C++标准、ROS 2宏定义)# 参数1:目标可执行文件名称(与add_executable的第一个参数一致)# 参数2+:依赖的ROS 2包名(必须与find_package中声明的包一致)ament_target_dependencies(talker rclcpp std_msgs)# 3. 编译订阅者可执行文件# 逻辑同发布者:将订阅者源码编译为名为 listener 的可执行文件add_executable(listener src/subscriber_member_function.cpp)# 4. 为订阅者可执行文件绑定ROS 2依赖# 依赖包与发布者一致(rclcpp是核心通信库,std_msgs是消息类型库)ament_target_dependencies(listener rclcpp std_msgs)# 5. 安装可执行文件到系统路径# install:CMake核心指令,将编译产物安装到指定目录# TARGETS:指定要安装的目标(可执行文件talker、listener)# DESTINATION:安装路径(ROS 2标准路径:lib/${PROJECT_NAME})# 关键作用:# - 安装后可通过 ros2 run 包名 可执行文件名 调用(ROS 2会在lib/包名目录下查找可执行文件)# - ${PROJECT_NAME}是CMake变量,自动替换为当前包名(避免硬编码,提高可移植性)install(TARGETS talker# 要安装的发布者可执行文件listener# 要安装的订阅者可执行文件DESTINATION lib/${PROJECT_NAME})# ROS 2标准安装路径

5、colcon build 编译

# 回到:工作空间目录【ros2_dir】 下执行colcon build --packages-select pub_sub_pkg

6、运行:发布者、订阅者

  • 终端1:发布者
# 刷入:临时环境变量, 方便ros2 找到sourceinstall/setup.bash# 执行:发布者ros2 run pub_sub_pkg talker
  • 终端2:订阅者
# 刷入:临时环境变量, 方便ros2 找到sourceinstall/setup.bash# 执行:发布者ros2 run pub_sub_pkg listener
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/14 19:15:14

GNSS位移监测站:配备扼流圈天线和磁性吸波材料

GNSS位移监测站配备扼流圈天线和磁性吸波材料&#xff0c;可显著提升监测精度与抗干扰能力&#xff0c;适用于复杂环境下的高精度位移监测需求。以下是具体分析&#xff1a;一、核心功能与优势高精度定位毫米级精度&#xff1a;通过差分RTK技术&#xff0c;结合扼流圈天线与磁性…

作者头像 李华
网站建设 2026/4/12 1:04:20

LobeChat可视化图表说明文字生成

LobeChat&#xff1a;构建可扩展、多模型兼容的开源AI聊天平台 在大语言模型&#xff08;LLM&#xff09;席卷全球的今天&#xff0c;人们早已不再满足于“能不能对话”&#xff0c;而是追问&#xff1a;“能否更安全&#xff1f;更可控&#xff1f;更灵活&#xff1f;”虽然像…

作者头像 李华
网站建设 2026/4/16 2:09:48

基于单片机的智能衣柜

基于单片机的智能衣柜设计 第一章 绪论 传统衣柜仅作为衣物收纳载体&#xff0c;存在诸多痛点&#xff1a;梅雨季或潮湿环境下衣物易发霉&#xff08;据统计&#xff0c;南方地区因潮湿导致的衣物霉变率达35%&#xff09;、长期封闭产生异味、衣物堆积后查找困难&#xff08;单…

作者头像 李华
网站建设 2026/4/15 12:22:16

谁占据专利代理机构高授权量C位?星河智源发布《2025年1-11月代理机构发明专利授权量想法TOP100》榜单,头部格局清晰呈现!

据统计&#xff0c;2025年1-11月代理机构CN发明专利授权量&#xff0c;其中前三均已破万&#xff0c;分别为&#xff1a; 北京集佳 13476件 广州三环 12644件 北京品源 10803件 图源专利茶馆 通过解读这份榜单内容&#xff0c;可以得出以下结论&#xff1a; 一、头部机…

作者头像 李华
网站建设 2026/4/13 12:42:08

【必学收藏】AI与大语言模型到底是什么关系?一文带你彻底理解大模型核心概念

本文详细解析了AI、机器学习、深度学习和语言模型的层级关系&#xff0c;重点介绍了大语言模型的概念、工作原理和训练过程。文章解释了大语言模型如何通过预训练、指令微调和RLHF三个步骤培养而成&#xff0c;以及Transformer框架如何通过注意力机制提升语言处理能力。最后&am…

作者头像 李华
网站建设 2026/4/11 3:30:18

如何在2025年将联系人从iPhone传输到iPhone

存储在iPhone上的联系人无疑是用户最重要的元素之一。因此&#xff0c;在从旧iPhone型号过渡到新iPhone 17/16/15/14/13/12/11时&#xff0c;必须将之前设备上的所有联系人无缝转移到新设备上。手动复制联系人可能是一项艰巨的任务&#xff0c;特别是对于那些已经积累了数百甚至…

作者头像 李华