LK 博客
ROS 2 订阅者与发布者总结
项目
约 1 分钟阅读 0 赞 0 条评论 鸿蒙黑体

ROS 2 订阅者与发布者总结

Jokerbai
Jokerbai @Jokerbai
累计点赞 0 登录后每个账号只能点一次
内容长度 0 正文词元数
正文
目录会跟随阅读位置移动。
阅读进度

ROS 2 订阅者与发布者总结

一、发布者和订阅者

在 ROS 2 里,节点之间最常见的通信方式就是 话题(Topic)通信

它包含两个角色:

  • 发布者(Publisher):负责发送消息
  • 订阅者(Subscriber):负责接收消息

可以把它理解成广播模式:

  • 发布者像广播站,不断往某个话题发送数据
  • 订阅者像收音机,只要订阅了这个话题,就能收到数据

二、它们适合做什么

发布/订阅适合处理 连续的数据流,例如:

  • 相机图像
  • 激光雷达点云
  • IMU 数据
  • 机器人速度指令
  • 里程计信息

这些数据的共同特点是:

  • 持续产生
  • 高频更新
  • 不需要一问一答

所以这类场景通常不用 service,而是用 topic。

三、基本通信流程

以一个字符串话题为例,流程如下:

  1. 发布者创建一个 topic
  2. 订阅者订阅这个 topic
  3. 发布者构造消息
  4. 发布者调用 publish() 发送消息
  5. 订阅者收到消息后触发回调函数
  6. 在回调函数中处理收到的数据

简化理解:

发布者 -> Topic -> 订阅者

四、发布者的核心代码结构

发布者最核心的步骤有四个:

  1. 创建节点
  2. 创建发布者对象
  3. 构造消息
  4. 发布消息

典型代码:

publisher_ = this->create_publisher<std_msgs::msg::String>("chatter", 10);

这句话的含义是:

  • 创建一个消息类型为 std_msgs::msg::String 的发布者
  • 话题名称为 chatter
  • 队列长度为 10

发布消息时一般写:

publisher_->publish(msg);

这表示把 msg 发送到对应的话题上。

五、订阅者的核心代码结构

订阅者最核心的步骤有三个:

  1. 创建节点
  2. 创建订阅者对象
  3. 编写回调函数处理消息

典型代码:

subscription_ = this->create_subscription<std_msgs::msg::String>(
    "chatter",
    10,
    std::bind(&MySubscriber::topic_callback, this, std::placeholders::_1)
);

这句话的含义是:

  • 订阅 chatter 这个话题
  • 消息类型为 std_msgs::msg::String
  • 队列长度为 10
  • 当有新消息到来时,调用 topic_callback

典型回调函数:

void topic_callback(const std_msgs::msg::String::SharedPtr msg)
{
    RCLCPP_INFO(this->get_logger(), "收到消息: %s", msg->data.c_str());
}

其中:

  • msg 就是收到的消息
  • msg->data 是字符串内容

六、发布者和订阅者各自做什么

发布者做的事

发布者主要负责:

  • 组织要发送的数据
  • 按一定频率发送消息
  • 把数据发布到指定 topic

常见写法是配合定时器:

timer_ = this->create_wall_timer(
    500ms,
    std::bind(&MyPublisher::timer_callback, this)
);

意思是每隔 500ms 调用一次发布函数。

订阅者做的事

订阅者主要负责:

  • 监听某个 topic
  • 接收消息
  • 在回调函数中进行处理

比如:

  • 打印日志
  • 保存数据
  • 参与算法计算
  • 转发成别的消息

七、队列长度是什么意思

无论是发布者还是订阅者,创建时常会看到一个数字,比如:

10

它一般表示消息队列深度,可以理解成缓存区大小。

含义是:

  • 如果消息来得太快,处理不过来,可以先暂存一些
  • 队列太小,旧消息可能被丢掉
  • 队列太大,会占更多内存,还可能导致延迟变大

初学时写 10 就够用了。

八、发布/订阅和服务通信的区别

发布/订阅(Topic)

特点:

  • 单向通信
  • 连续发送
  • 不需要回复
  • 一个发布者可以对应多个订阅者

适合:

  • 传感器数据
  • 控制指令
  • 状态信息

服务通信(Service)

特点:

  • 请求/响应
  • 一问一答
  • 需要返回结果

适合:

  • 查询状态
  • 请求执行某个动作
  • 计算某个结果

所以:

  • 点云、图像、IMU 用发布/订阅
  • 加法服务、清空地图、保存路径这类用服务通信

九、最常见的 API

发布者常见 API

create_publisher
publish

订阅者常见 API

create_subscription
callback

只要你在源码里看到这些函数,基本就能快速判断这个节点在做什么。

十、阅读源码时怎么快速判断

当你看一个 ROS 2 节点源码时,可以先找这些关键字:

如果看到了

create_publisher
publish

说明这个节点是 发布者 或至少包含发布功能。

如果看到了

create_subscription
std::bind(...callback...)

说明这个节点是 订阅者 或至少包含订阅功能。

通常一个节点不一定只有一种身份,它可能同时:

  • 订阅某个话题
  • 处理数据
  • 再发布到另一个话题

这在机器人系统里非常常见。

十一、一个完整理解例子

例如雷达驱动节点和建图节点:

  • 雷达驱动节点:发布点云
  • 建图节点:订阅点云
  • 建图节点处理后:再发布位姿或地图
  • 其他节点继续订阅位姿或地图

所以整个 ROS 系统常常是:

节点A发布 -> 节点B订阅并处理 -> 节点B再发布 -> 节点C订阅

这其实就是很多机器人系统的数据流本质。

created by jokerbai

作者名片

Jokerbai
Jokerbai
@Jokerbai

这个作者暂时还没有填写个人简介。

评论区
文章作者和管理员都可以管理这里的评论。
0 条评论
登录后即可参与评论。 去登录
还没有评论,欢迎留下第一条交流内容。