当前位置: 首页 > news >正文

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

这是一个非常经典的 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 一次性启动这两个节点?

http://www.jsqmd.com/news/114170/

相关文章:

  • Open-AutoGLM动态资源分配实战:3步实现GPU利用率提升90%
  • 如何用Linly-Talker构建企业级虚拟主播?完整流程分享
  • 6大房产中介客户管理系统盘点
  • 如何测试一个AI模型——从数据、算法到伦理的完整回答框架
  • 两轮车MATLAB仿真程序的实现方法
  • 6大房产中介客户管理系统盘点
  • Open-AutoGLM效率预测模型解密:9大行业应用落地路径曝光
  • Linly-Talker能否替代真人出镜?应用场景深度探讨
  • Logstash 提示已有另一个实例占用了配置的 `path.data` 目录
  • 网安人才缺口 480 万!3 个相关专业特点大不同:零基础选哪个、有基础选哪个,一文分清!
  • 基于VUE的酒店综合治理系统[VUE]-计算机毕业设计源码+LW文档
  • 一张人脸照片+文本生动数字人?Linly-Talker做到了
  • 数字人创业新方向:基于Linly-Talker的SaaS服务构想
  • 构建可靠的测试自动化:测试脚本代码质量保障体系深度解析
  • 揭秘Open-AutoGLM参数动态调整:3步实现性能跃升
  • Open-AutoGLM场景化部署十大坑点(前3名企业避坑实录首次公开)
  • Open-AutoGLM性能提升300%的背后:你必须掌握的7个底层优化逻辑
  • GitHub 热榜项目 - 日榜(2025-12-20)
  • 揭秘Open-AutoGLM核心能力:为何它能重塑自动驾驶与大模型生态?
  • Axios HTTP请求超时时间参数配置教程
  • Cmake的详细历史,原理,以及常见用法,帮我详细讲解-03 - jack
  • 【解密Open-AutoGLM隐私引擎】:90%开发者忽略的4个安全盲区及应对策略
  • Open-AutoGLM隐私技术落地难题,如何用1套框架解决合规与效率双重挑战?
  • Linly-Talker在心理健康科普中的温和表达实践
  • 信息安全和网络空间安全专业怎么选?想学黑客技术应该选哪个专业?学长告诉你!
  • Open-AutoGLM落地难题全破解:企业级应用中的9大挑战与应对策略
  • Linly-Talker与Stable Diffusion结合的可能性探索
  • 解决机器人“完美难题”:智能拣选与码放技术
  • 还在为大模型落地难发愁?:Open-AutoGLM在智能客服中的4步实施法
  • 传送带异物检测玻璃碴子检测数据集VOC+YOLO格式156张1类别