news 2026/5/30 21:09:21

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/5/30 13:05:00

LobeChatUGC内容激励方案

LobeChat UGC内容激励方案 在AI助手从实验室走向千家万户的今天&#xff0c;一个关键问题摆在开发者面前&#xff1a;如何让开源项目不只是“能用”&#xff0c;而是真正“被广泛使用”&#xff1f;答案或许不在于功能堆砌&#xff0c;而在于构建一种用户愿意参与、乐于贡献的内…

作者头像 李华
网站建设 2026/5/29 21:01:41

LobeChat会员等级晋升通知

LobeChat&#xff1a;从容器化部署到智能对话架构的深度实践 在 AI 技术加速落地的今天&#xff0c;大语言模型&#xff08;LLM&#xff09;早已不再是实验室里的概念。越来越多企业开始尝试将 GPT、Claude、Ollama 等强大模型集成进实际业务中——无论是客服系统、知识助手&am…

作者头像 李华
网站建设 2026/5/29 5:52:30

收藏!2025 AI Agent爆发元年,大模型高薪赛道入门全攻略

一句指令触发手机40余款应用自动完成点餐、订票、购物全流程&#xff0c;工厂里人形机器人精准抓取物料替代熟练工劳作&#xff0c;金融AI智能体自主处理业务并优化客户体验——如今&#xff0c;智能体&#xff08;AI Agent&#xff09;正以“对话即执行、虚拟融实体”的姿态&a…

作者头像 李华
网站建设 2026/5/29 20:13:54

LobeChat网络异常错误提示优化

LobeChat网络异常错误提示优化 在构建AI聊天助手的实践中&#xff0c;一个看似微小却极具影响力的细节往往被忽视——当网络出问题时&#xff0c;系统该如何告诉用户“哪里坏了”。对于像LobeChat这样的开源对话平台而言&#xff0c;它不仅要能流畅地与大模型通信&#xff0c;更…

作者头像 李华
网站建设 2026/5/29 20:53:37

AI Agent在智能床头柜中的睡眠音乐定制

AI Agent在智能床头柜中的睡眠音乐定制 关键词:AI Agent、智能床头柜、睡眠音乐定制、个性化推荐、用户体验 摘要:本文深入探讨了AI Agent在智能床头柜中实现睡眠音乐定制的相关技术。首先介绍了该研究的背景,包括目的、预期读者、文档结构和术语表。接着阐述了核心概念与联…

作者头像 李华