ROS 话题通信实战详解|发布者 Publisher 与订阅者 Subscriber 完整代码实现(含运行截图 + 原理分析)
·
文章目录
- 实验概述
- ROS 话题通信底层原理
- 实验环境说明
- 项目完整代码实现4.1 创建 ROS 功能包4.2 发布者 talker.py 代码4.3 订阅者 listener.py 代码
- 项目编译与运行步骤
- 运行效果展示
- 常见报错问题解决
- 实验总结与心得
一、实验概述
本次实验以 ROS 话题通信为核心,实现发布者(Publisher) 持续向指定话题发送字符串消息,订阅者(Subscriber) 监听话题并接收打印消息。实验目标:
- 理解 ROS Master、节点、话题、消息、发布 / 订阅五者的协作关系;
- 掌握 Python 实现 ROS 话题通信完整流程;
- 熟练使用 rosrun、roscore、catkin_make 等 ROS 基础命令;
- 区分话题通信的异步单向通信特性,理解其适用场景。
话题通信是机器人开发最常用的数据传输方式,相机图像、激光雷达数据、底盘速度指令全部基于话题传输,是机器人技术入门核心知识点。
二、ROS 话题通信底层原理
2.1 核心四大角色
- Master(ROS 核心管理器):节点注册中心,记录所有节点与话题信息,匹配发布者和订阅者;
- Publisher 发布节点:主动创建话题,周期性向外发送自定义消息;
- Topic 话题:数据传输通道,同一话题只能使用统一消息类型;
- Subscriber 订阅节点:向 Master 申请绑定指定话题,收到消息自动触发回调函数。
2.2 完整通信流程
- 启动
roscore,开启 Master 管理中心; - 发布节点启动,向 Master 注册自己要发布的话题
chatter; - 订阅节点启动,向 Master 声明订阅
chatter话题; - Master 匹配两者信息,建立发布者与订阅者点对点 TCP 连接;
- 发布者循环发送消息,订阅者实时接收并执行回调逻辑。
2.3 通信特点
- 单向异步通信:发布者只管发送,无需等待订阅者回复;
- 多对多支持:一个话题可多个发布者、多个订阅者;
- 适合高频连续数据流传输(传感器、运动控制)。
三、实验环境说明
- 操作系统:Ubuntu 20.04 LTS
- ROS 版本:ROS Noetic Ninjemys
- 编程语言:Python3
- 依赖库:rospy、std_msgs(标准消息库)
四、项目完整代码实现
4.1 创建工作空间与功能包
打开终端依次执行以下命令,搭建项目工程:
# 1. 创建ROS工作空间
mkdir -p ~/topic_ws/src
cd ~/topic_ws/src
# 2. 创建话题通信功能包,声明依赖
catkin_create_pkg topic_demo rospy roscpp std_msgs
# 进入功能包,新建脚本文件夹存放python代码
cd topic_demo
mkdir scripts
4.2 发布者代码 talker.py
路径:topic_ws/src/topic_demo/scripts/talker.py
#!/usr/bin/env python3
# 导入ros核心库与标准字符串消息
import rospy
from std_msgs.msg import String
def talker():
# 1. 创建发布对象:话题名chatter,消息类型String,消息队列长度10
pub = rospy.Publisher("chatter", String, queue_size=10)
# 2. 初始化节点,节点名称talker_node,anonymous自动加后缀避免重名
rospy.init_node("talker_node", anonymous=True)
# 设置发布频率1Hz,每秒发送1条消息
rate = rospy.Rate(1)
count = 0 # 消息计数变量
# 未关闭ros节点时循环发送
while not rospy.is_shutdown():
# 拼接发送内容
send_msg = f"ROS话题通信测试消息,当前计数:{count}"
# ROS日志打印输出,相当于print
rospy.loginfo(f"【发布端】发送消息:{send_msg}")
# 将消息发布到chatter话题
pub.publish(send_msg)
count += 1
# 控制发送频率,休眠1秒
rate.sleep()
if __name__ == "__main__":
try:
talker()
# 捕获Ctrl+C终止程序异常
except rospy.ROSInterruptException:
pass
4.3 订阅者代码 listener.py
路径:topic_ws/src/topic_demo/scripts/listener.py
#!/usr/bin/env python3
import rospy
from std_msgs.msg import String
# 消息回调函数:收到话题消息自动执行
def msg_callback(data):
# 打印接收到的消息内容
rospy.loginfo(f"【订阅端】成功接收消息:{data.data}")
def listener():
# 初始化订阅节点
rospy.init_node("listener_node", anonymous=True)
# 创建订阅对象:订阅chatter话题,绑定回调函数msg_callback
rospy.Subscriber("chatter", String, msg_callback)
rospy.loginfo("订阅节点启动,等待接收chatter话题消息...")
# 循环阻塞,持续监听话题消息
rospy.spin()
if __name__ == "__main__":
listener()
4.4 添加脚本执行权限
代码写完后必须赋予可执行权限,否则 rosrun 无法启动节点:
cd ~/topic_ws/src/topic_demo/scripts
chmod +x talker.py listener.py
五、项目编译与运行步骤
5.1 编译工作空间
# 返回工作空间根目录编译
cd ~/topic_ws
catkin_make
# 刷新环境变量,让系统识别新建功能包
source devel/setup.bash
5.2 多终端分步启动(需要 3 个独立终端窗口)
终端 1:启动 ROS 核心 Master
roscore
输出started core service [/rosout]代表启动成功。
终端 2:运行发布者节点
rosrun topic_demo talker.py
终端持续打印发送日志,循环输出计数消息。
终端 3:运行订阅者节点
rosrun topic_demo listener.py
启动瞬间接收发布者实时推送的所有消息。
六、运行效果展示
这里插入你的运行截图,文字描述如下:
- 终端 1:roscore 启动成功,显示核心服务运行;
- 终端 2:发布者持续输出【发布端】日志,计数持续自增;
- 终端 3:订阅者实时同步打印和发布端完全一致的消息,无延迟丢包。
现象说明:发布者与订阅者节点建立通信,话题chatter数据传输正常,实验功能全部实现。
七、常见报错问题解决
- rosrun 找不到包解决:执行
source devel/setup.bash刷新环境变量; - PermissionError 权限不足解决:给 py 文件添加
chmod +x执行权限; - 消息接收空白 / 无输出解决:确认发布者、订阅者话题名称完全一致,大小写敏感;
- roscore 启动失败端口占用解决:执行
killall roscore关闭残留进程后重启。
八、实验总结与心得
通过本次 ROS 话题通信实验,我完整掌握了机器人底层最基础的通信模型,理清了 Master、发布节点、订阅节点、话题消息之间的协作逻辑。
- 话题通信适合传感器连续数据流传输,是自动驾驶、移动机器人底盘控制的基础;
- 发布者依靠
rospy.Publisher创建通道,订阅者通过回调函数异步处理消息,rospy.spin()是订阅节点持续监听的核心; - 开发流程固定:创建工作空间→新建功能包→编写节点代码→授权→编译→多终端分步调试;
- 实际开发中需要严格统一话题名、消息类型,否则会出现节点无法通信的问题。
本次实验为后续 ROS 服务通信、动作通信、自定义消息打下坚实基础,理解异步通信模型对后续人工智能机器人项目开发至关重要。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)