4. ROS2工具链与调试:rqt工具集使用、ros2命令行工具、bag包录制与回放、tf2坐标变换、日志系统与调试技巧
说实话,ROS2 的开发体验比 ROS1 好了不少,但工具链也更庞大了。很多新手一上来就被各种命令行和图形工具搞晕了。我刚开始接触的时候也踩过不少坑,今天就把这些工具串起来讲清楚。
这一章的核心就一句话:工具是拿来用的,不是拿来背的。你不需要记住所有命令,但要知道什么时候该用什么。
本章知识体系速览
调试工具链 = 可视化(rqt) + 命令行(ros2) + 数据回放(bag) + 坐标变换(tf2) + 日志系统
4.1 rqt 工具集:可视化调试利器
rqt 是 ROS2 的瑞士军刀。我个人习惯先开 rqt,再跑节点。为什么?因为你能一眼看到整个系统的拓扑结构。
4.1.1 rqt_graph:看节点通信
启动方式很简单:
rqt_graph
你会看到节点(椭圆)和话题(矩形)之间的连线。我在项目中遇到过一个问题:两个节点明明在同一个网络里,但就是收不到消息。打开 rqt_graph 一看,原来话题名字拼错了——一个叫 /camera/image,另一个叫 /camera/Image。大小写问题,折腾了我一下午。
小技巧:勾选 "Hide Debug" 可以过滤掉 /rosout 这类系统话题,让图更清爽。
4.1.2 rqt_plot:实时数据曲线
调试 PID 控制器或者看传感器数据时,rqt_plot 特别好用:
rqt_plot /topic/field1 /topic/field2
说白了,这就是一个简易示波器。你想想看,要调试一个自动驾驶的横向控制,没有实时曲线,全靠打印日志,那得多痛苦。
4.1.3 其他常用插件
- rqt_console:日志过滤,按级别(DEBUG/INFO/WARN/ERROR)查看
- rqt_reconfigure:动态参数调整,不用重启节点
- rqt_bag:可视化 bag 文件内容
4.2 ros2 命令行工具:日常必备
命令行是 ROS2 调试的基础。我建议你把这些命令练到肌肉记忆的程度。
4.2.1 节点管理
# 列出所有节点
ros2 node list
# 查看节点信息
ros2 node info /node_name
# 查看节点参数
ros2 param list /node_name
嗯,这里要注意:ros2 node info 会显示该节点的所有发布者、订阅者、服务端和客户端。我曾经用它排查过一个节点为什么没收到消息——原来它订阅的话题根本没人发布。
4.2.2 话题操作
# 列出所有话题
ros2 topic list
# 查看话题信息(类型、发布者数量等)
ros2 topic info /topic_name
# 实时查看话题数据
ros2 topic echo /topic_name
# 查看话题发布频率
ros2 topic hz /topic_name
# 手动发布消息(调试神器)
ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.5}}"
实战场景:调试底盘驱动时,我经常用 ros2 topic pub 手动发速度指令,看电机是否响应。如果电机不动,要么是话题名不对,要么是驱动节点没跑起来。
4.2.3 服务与动作
# 列出服务
ros2 service list
# 调用服务
ros2 service call /service_name package/msg/Type "{arg: value}"
# 列出动作
ros2 action list
4.3 bag 包录制与回放:数据是金矿
做自动驾驶,数据就是一切。没有数据,你没法复现问题,没法做回归测试。
4.3.1 录制 bag
# 录制所有话题
ros2 bag record -a
# 录制指定话题
ros2 bag record /camera/image /lidar/points /imu/data
# 指定输出目录
ros2 bag record -o my_bag /topic1 /topic2
我个人习惯只录需要的话题。为什么?因为全录的话,一个 64 线激光雷达的数据,几分钟就能撑爆你的硬盘。我曾经在路测时忘了限制话题,结果 10 分钟录了 15GB,回放时电脑直接卡死。
4.3.2 回放 bag
# 回放 bag
ros2 bag play my_bag
# 循环回放
ros2 bag play my_bag --loop
# 控制回放速度(0.5倍速)
ros2 bag play my_bag --rate 0.5
注意:回放时,bag 中的时间戳会被保留。如果你用 --clock 选项,系统时间会被 bag 时间覆盖。这在调试时间敏感算法时要特别小心。
4.3.3 bag 信息查看
ros2 bag info my_bag
这条命令会告诉你 bag 里有哪些话题、消息数量、时长等信息。我每次拿到路测数据,第一件事就是跑这个命令,看看数据是否完整。
4.4 tf2 坐标变换:自动驾驶的骨架
tf2 是 ROS2 的坐标变换系统。说白了,就是回答一个问题:A 坐标系下的点,在 B 坐标系下是什么位置?
4.4.1 核心概念
- 坐标帧(Frame):比如 base_link、odom、map、camera_link
- 变换(Transform):两个帧之间的平移和旋转关系
- tf tree:所有帧的父子关系树
4.4.2 常用调试命令
# 查看两个帧之间的变换
ros2 run tf2_ros tf2_echo base_link camera_link
# 查看整个 tf tree
ros2 run tf2_tools view_frames.py
# 静态变换发布(比如相机到车体的固定变换)
ros2 run tf2_ros static_transform_publisher x y z yaw pitch roll frame_id child_frame_id
我记得有一次,激光雷达的点云和相机图像怎么都对不齐。用 tf2_echo 一看,原来激光雷达的安装位置参数写错了——y 方向偏了 10 厘米。这种问题,没有 tf2 工具,你根本查不出来。
调试技巧:用 view_frames.py 生成 PDF 文件,可以直观看到所有帧的连接关系。如果某个帧断开了,那肯定有问题。
4.4.3 代码中使用 tf2
# Python 示例:获取变换
from tf2_ros import Buffer, TransformListener
import rclpy
buffer = Buffer()
listener = TransformListener(buffer, node)
# 等待变换可用
transform = buffer.lookup_transform(
'base_link', # 目标帧
'camera_link', # 源帧
rclpy.time.Time() # 当前时间
)
4.5 日志系统与调试技巧
日志是调试的最后一道防线。ROS2 的日志系统比 ROS1 强太多了。
4.5.1 日志级别
| 级别 | 宏/函数 | 使用场景 |
|---|---|---|
| DEBUG | RCLCPP_DEBUG | 开发调试,生产环境关闭 |
| INFO | RCLCPP_INFO | 正常运行时信息 |
| WARN | RCLCPP_WARN | 潜在问题,但不影响运行 |
| ERROR | RCLCPP_ERROR | 功能异常,需要处理 |
| FATAL | RCLCPP_FATAL | 致命错误,程序即将退出 |
4.5.2 日志配置
# 设置日志级别(命令行启动时)
ros2 run my_package my_node --ros-args --log-level debug
# 代码中设置
rclcpp::Logger logger = node->get_logger();
logger.set_level(rclcpp::Logger::Level::Debug);
# 条件日志(只在满足条件时打印)
RCLCPP_INFO_THROTTLE(logger, *node->get_clock(), 1000, "每秒打印一次");
4.5.3 我的调试三板斧
- 先看 rqt_graph:确认节点连接是否正确
- 再用 topic echo:看数据内容是否符合预期
- 最后加日志:如果前两步查不出问题,就在关键路径加 DEBUG 日志
避坑指南:我曾经在生产代码里忘了关 DEBUG 日志,结果每秒打印几千条,导致 CPU 占用飙升。记住:生产环境只开 INFO 及以上级别。
4.5.4 日志文件
ROS2 默认把日志写到 ~/.ros/log/ 目录下。你可以用 rqt_console 实时查看,也可以用 ros2 run 的 --ros-args --log-file 指定输出文件。
# 指定日志文件
ros2 run my_package my_node --ros-args --log-file /tmp/my_log.log
好了,这一章的内容就这些。工具链这东西,光看没用,你得动手。找个实际项目,把每个工具都用一遍,自然就记住了。
一句话总结:rqt 看拓扑,命令行查细节,bag 存数据,tf2 管坐标,日志保底线。五件套齐了,调试不慌。