第2章 ROS话题基础
聊到SLAM调试,绕不开的就是ROS话题。你想想看,激光雷达、IMU、里程计、图像……所有传感器数据都是通过话题在节点之间流动的。说白了,话题就是ROS的血管。这一章我就带你彻底搞懂话题与消息的机制,以及我们每天都要用的命令行工具。
话题与消息:到底在传什么?
话题是ROS里最核心的通信方式。一个节点往话题里发数据,另一个节点从话题里收数据。数据本身叫消息,它有固定的结构。比如激光雷达的消息是 sensor_msgs/LaserScan,里面包含角度、距离、强度等字段。
我个人习惯先看消息定义,再分析数据。你想想看,如果连消息里有什么字段都不清楚,后面怎么定位问题?
发布者与订阅者模式
这个模式其实特别简单:一个节点发布消息,零个或多个节点订阅。我曾经在调试多雷达融合时遇到过一个问题——两个激光雷达发布了相同的话题名,结果数据乱套了。嗯,这里要注意:话题名必须唯一,否则订阅者会收到混合的数据。
- 发布者 (Publisher):负责创建话题并发送消息。频率由节点控制,比如10Hz的激光扫描。
- 订阅者 (Subscriber):注册到话题,每次有新消息就触发回调函数。
- 话题 (Topic):名称是全局的,用字符串标识,比如
/camera/image_raw。
说白了,这就是一个“生产-消费”模型。SLAM里最典型的就是 /scan 话题——激光雷达发布,前端里程计和建图节点同时订阅。
/front_lidar/scan 和 /rear_lidar/scan。记住:命名空间是你的好朋友。
常用命令行工具:rostopic & rosmsg
调试SLAM,90%的时间都在跟这两个命令打交道。我几乎每天都会敲几十遍 rostopic echo 和 rostopic list。下面我把最常用的用法列出来,都是实战里高频的。
| 命令 | 作用 | 我常用的场景 |
|---|---|---|
rostopic list | 列出所有活跃话题 | 先看系统里有哪些话题在跑,确认节点是否正常 |
rostopic echo /topic | 打印话题消息内容 | 实时看激光雷达数据、IMU数据,检查有没有异常值 |
rostopic hz /topic | 显示话题发布频率 | 检查传感器是否掉帧,比如激光雷达应该10Hz,结果只有5Hz |
rostopic bw /topic | 显示话题带宽 | 定位网络或CPU瓶颈,比如图像话题带宽异常高 |
rostopic info /topic | 显示话题类型、发布者和订阅者 | 快速确认谁在发、谁在收 |
rosmsg show <类型> | 显示消息结构 | 查看消息里有哪些字段,比如 rosmsg show sensor_msgs/LaserScan |
rosmsg list | 列出所有已知消息类型 | 查找某个消息包是否安装 |
rostopic echo 时,如果话题频率很高(比如IMU 200Hz),终端会刷屏。我建议加上 --noarr 参数,或者用 rostopic echo /imu | head -20 只看前20行。否则你连Ctrl+C都来不及按。
实战小例子:检查激光雷达话题
假设你刚启动SLAM系统,想知道激光雷达有没有在发数据。我会这么做:
# 1. 先看话题列表
rostopic list | grep scan
# 输出: /scan
# 2. 看话题类型和发布者
rostopic info /scan
# Type: sensor_msgs/LaserScan
# Publishers:
# * /laser_driver (http://...)
# Subscribers:
# * /slam_node (http://...)
# 3. 看消息结构
rosmsg show sensor_msgs/LaserScan
# Header header
# float32 angle_min
# float32 angle_max
# float32 angle_increment
# float32[] ranges
# ...
# 4. 看频率
rostopic hz /scan
# average rate: 10.002 Hz
# 5. 看一帧数据
rostopic echo /scan --noarr -n 1
你看,几步下来,话题的状态就全清楚了。我个人习惯把 rostopic hz 和 rostopic echo 组合起来用——先看频率稳不稳,再看数据有没有异常。
/odom 话题。用 rostopic echo /odom 发现里程计的位置竟然跳变,后来发现是轮子打滑。如果没有这些工具,你只能对着黑盒子猜。
消息机制:序列化与反序列化
你可能好奇,消息在话题里到底怎么传输的?ROS使用自带的序列化格式,把结构体变成字节流,再通过网络或共享内存传递。订阅端收到后反序列化成对象。这个过程对开发者几乎是透明的,但了解它有助于理解带宽和延迟。
举个例子,sensor_msgs/Image 消息包含原始图像数据,如果分辨率是1920x1080,一帧就有好几兆。我曾经在调试时发现话题带宽飙到100Mbps,用 rostopic bw /camera/image_raw 一看,果然图像太大。后来我降低了分辨率,问题就解决了。
rostopic delay /topic 查看消息从发布到订阅的延迟。在SLAM里,延迟超过100ms就可能影响建图质量。