尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

演示一下如何编写 Publisher (发布者) 和 Subscriber (订阅者) 的代码吗?-02 - jack

演示一下如何编写 Publisher (发布者) 和 Subscriber (订阅者) 的代码吗?-02 - jack
📅 发布时间:2026/6/19 21:44:25

这是一个非常经典的 ROS 入门场景。我们将创建一个“说话者”(Publisher)和一个“倾听者”(Subscriber)。

为了让你看得清晰,我将沿用上一轮假设的包名 my_robot_control。

核心概念图解

在写代码之前,先理解数据流向:

  1. Publisher (Talker): 告诉 ROS Master 我要往某个话题(Topic)发数据。
  2. Topic: 就像一个广播频道(例如名为 /chatter)。
  3. Subscriber (Listener): 告诉 ROS Master 我要监听这个频道,一旦有数据,就调用我的回调函数处理。

第一步:编写 Publisher 代码 (talker.cpp)

在 ~/catkin_ws/src/my_robot_control/src/ 目录下新建 talker.cpp。

这个节点会每秒发送一条 "Hello ROS" 消息。

/*** 文件名: talker.cpp* 功能: 持续发布 std_msgs/String 类型的消息到 "chatter" 话题*/#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>int main(int argc, char **argv)
{// 1. 初始化节点,命名为 "talker"// 注意:节点名称必须在 ROS 网络中唯一ros::init(argc, argv, "talker");// 2. 创建节点句柄,它是管理节点资源的入口ros::NodeHandle nh;// 3. 创建 Publisher// 语法: nh.advertise<消息类型>("话题名称", 队列长度)// 队列长度 1000 意味着:如果网络堵塞,保留最近 1000 条消息,旧的丢弃ros::Publisher chatter_pub = nh.advertise<std_msgs::String>("chatter", 1000);// 4. 设置循环频率 (10Hz,即每秒 10 次)ros::Rate loop_rate(10);int count = 0;while (ros::ok()) // 当 ROS 正常运行时(比如没有按 Ctrl+C){// 5. 封装消息数据std_msgs::String msg;std::stringstream ss;ss << "Hello ROS " << count;msg.data = ss.str();// 打印到终端 (类似 printf)ROS_INFO("%s", msg.data.c_str());// 6. 正式发布消息chatter_pub.publish(msg);// 7. 处理回调 (虽然这里没有订阅,但保留是个好习惯)ros::spinOnce();// 8. 休眠直到达到 10Hz 的时间间隔loop_rate.sleep();++count;}return 0;
}

第二步:编写 Subscriber 代码 (listener.cpp)

在同一目录下新建 listener.cpp。

这个节点会一直等待,一旦 /chatter 话题有消息,就触发回调函数打印出来。

/*** 文件名: listener.cpp* 功能: 订阅 "chatter" 话题并打印收到的内容*/#include "ros/ros.h"
#include "std_msgs/String.h"// 1. 回调函数 (Callback)
// 当有新消息到达时,ROS 会自动调用这个函数
// msg 是消息的常量指针,效率高
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{ROS_INFO("I heard: [%s]", msg->data.c_str());
}int main(int argc, char **argv)
{// 初始化节点,命名为 "listener"ros::init(argc, argv, "listener");ros::NodeHandle nh;// 2. 创建 Subscriber// 语法: nh.subscribe("话题名称", 队列长度, 回调函数)ros::Subscriber sub = nh.subscribe("chatter", 1000, chatterCallback);// 3. 进入自旋 (Blocking)// ros::spin() 会阻塞在这里,不断检查是否有消息到达。// 一旦有消息,它就去执行 chatterCallback,执行完回来继续等。ros::spin();return 0;
}

第三步:修改 CMakeLists.txt (最重要!)

代码写好了,必须告诉编译器如何编译这两个文件。打开 ~/catkin_ws/src/my_robot_control/CMakeLists.txt。

你需要确保 find_package 中包含了 std_msgs(因为我们用了 String 消息)。

然后在 Build 区域添加以下内容:

## ... 前面的 find_package ...## 1. 编译 talker
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
# add_dependencies(talker ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})## 2. 编译 listener
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
# add_dependencies(listener ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

第四步:编译与运行

  1. 编译
cd ~/catkin_ws
catkin_make

(确保没有报错,如果有 "undefined reference",检查 CMakeLists.txt 是否保存)
2. 运行 (需要打开 3 个终端窗口)

  • 终端 1 (Master):
roscore
  • 终端 2 (Listener/Subscriber):
source ~/catkin_ws/devel/setup.bash
rosrun my_robot_control listener

(此时它会卡住等待,这是正常的)

  • 终端 3 (Talker/Publisher):
source ~/catkin_ws/devel/setup.bash
rosrun my_robot_control talker

结果:
你会看到终端 3 不断打印 "Hello ROS 0", "Hello ROS 1"...
同时,终端 2 会同步打印 "I heard: [Hello ROS 0]"...


关键点总结

概念 Publisher (Talker) Subscriber (Listener)
主动性 主动发送数据 被动等待数据
核心对象 ros::Publisher ros::Subscriber
循环方式 while(ros::ok()) + loop_rate.sleep() ros::spin() (死循环等待)
关键函数 .publish(msg) callback(msg)

接下来,你想了解如何定义自己的“自定义消息”(比如发送一个包含 姓名(string) 和 年龄(int) 的消息),还是想了解如何使用 roslaunch 一次性启动这两个节点?

相关新闻

  • 如何利用WebRTC实现实时远程操控Linly-Talker?
  • 数字人创业新方向:基于Linly-Talker的SaaS服务构想
  • 一张人脸照片+文本生动数字人?Linly-Talker做到了

最新新闻

  • 2026年6月正规诸城热压罐硫化罐杀菌锅设备优质厂家名单表 - 海棠依旧大
  • SPI通信协议深度解析:CPHA/CPOL配置、错误处理与MC68HC908MR24实战
  • 2026年天津强力巨彩销售商、分销商选择指南 - mypinpai
  • 2026年辽宁正规光伏厂家名单表:工商业光伏、分布式光伏、太阳能板定制服务商甄选 - 海棠依旧大
  • fpSpread(FarPoint Spread / Spread.NET)报表设计器
  • 终极指南:在Linux系统上解锁Realtek RTL8125 2.5GbE网卡完整性能

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号