返回专辑
·Johan·4 分钟阅读

ROS 2 CLI 分诊:一条可复现的证据链

从节点图、QoS、频率到时间戳逐步收敛;echo 是显微镜,不是结论。

ROS 2 CLI 分诊:一条可复现的证据链

1. echo 刷屏解决不了「为什么没数据」

新人故障单只贴一段 ros2 topic echo,等于没贴:缺 info -v、缺对端 node info、缺时钟源说明。「我 echo 了有数据」当成结案,常会漏掉频率塌陷、frame 错误、QoS 半匹配——驱动日志在刷帧,RViz 却空白,就是因为没人查 Offered/Requested。

固定证据链:进程在否 → 图连通否 → QoS 兼容否 → stamp/frame 合理否 → 回调在跑否。每步只回答一个问题,结论才能复现给别人。

2. 第一步:节点还在不在

bash
ros2 node list
ros2 node info /your_node

node list 空或缺预期节点:查 launch、lifecycle 状态、是否 crash loop。node info 看 Publishers/Subscriptions 是否挂上预期话题——节点活着但图没连上,和节点根本没起来是两类问题。

lifecycle 节点 inactive 时,业务话题可能不存在或不再发布:

bash
ros2 lifecycle get /your_lifecycle_node
ros2 lifecycle list /your_lifecycle_node

3. 第二步:QoS 与连接

无数据时优先 ros2 topic info -v,不要先 echo:

bash
ros2 topic info -v /camera/image_raw

看 Offered vs Requested 的 reliability、durability、depth。不兼容时连接数可能大于零,数据面仍空——RViz 有时只显示「有 publisher」,不显示匹配失败。Publisher count 与 Subscription count 都非零,仍可能零兼容——这是 ROS 2 新手最容易误判的点。

有连接后再看频率与带宽:

bash
ros2 topic hz /camera/image_raw
ros2 topic bw /camera/image_raw

hz 接近零但进程没挂:查 CPU 抢占、回调阻塞、或上游实际停发。executor 里一个慢回调拖死同节点其他订阅,表现为「只有某个话题零 hz」——用 ros2 node info 看同节点还有哪些订阅,再查日志是否有单线程堵死。

bw 异常低:查压缩、分辨率或字段是否为空。

4. 第三步:时间戳与 frame

抽样 header.stampframe_id

bash
ros2 topic echo /scan --field header --once

仿真场景强制先确认 /clockuse_sim_time——时钟错了,上面整条链的「频率正常」可能毫无意义。stamp 不单调或跳变:查驱动、NTP 或 bag 回放设置。

TF 问题用专用工具,别盲目 echo /tf

bash
ros2 run tf2_tools view_frames
ros2 run tf2_ros tf2_echo map base_link

5. 服务、Action 与参数

服务:先 list,再带超时调用,区分超时、拒绝与逻辑错误。

bash
ros2 service list
ros2 service call /your_service std_srvs/srv/Trigger "{}"

Action:看 goal 状态与 feedback,别用 topic echo 猜进度。

bash
ros2 action list
ros2 action info /follow_path

参数漂移用 ros2 param get/describe 对照 launch yaml——「改了没效果」常是键名或节点命名空间错了:

bash
ros2 param list /your_node
ros2 param get /your_node inflation_radius
ros2 param describe /your_node inflation_radius

Composable 容器里节点名带前缀,param get 的绝对名与 yaml 里相对名对不上,是 second most common「配置无效」原因。

6. 环境层:doctor 与日志

bash
ros2 doctor --report
ros2 doctor --fail-warnings

doctor 抓 RMW、domain、网络接口异常。日志级别:

bash
ros2 run rclcpp_components component_container --ros-args --log-level debug

联调脚本用频率阈值、字段非空、lifecycle active 等检查替代人工 echo。输出应包含失败步骤编号,方便对照证据链。

7. 录包与回放

bash
ros2 bag record -o debug_bag /tf /tf_static /clock /scan /odom
ros2 bag info debug_bag
ros2 bag play debug_bag --clock

回放时订阅者 QoS 必须与在线一致,否则会在 Reliable 回放里调试 Best Effort 系统的幻觉。bag 里没有 /clock 但节点 use_sim_time:=true,时间域全乱。

8. 多机与容器:先缩小战场

跨机问题先在单机复现:同一 bag、同一 launch,排除网络变量。容器里 ros2 node list 只有本容器进程时,查 network mode 与 ROS_LOCALHOST_ONLY,不要急着改算法。

bash
# 对比两机环境
ros2 doctor --report | diff - machine_a_report.txt -

domain、RMW、网卡绑定不一致时,diff 一眼可见。K8s 侧车模式下,确保业务容器与 ROS 守护进程共享 network namespace,否则 discovery 永远单边。

9. 案例:频率正常但规划不动

一次 Nav2 故障:ros2 topic hz /odom 显示 50 Hz,但局部规划不更新。证据链往下走:node info 发现 costmap 节点订阅的 /scan QoS 不兼容(Reliable 订 Best Effort);info -v 一行结案。若停在「odom 有数据」,会浪费半天调 global planner。

10. 团队习惯与验收

故障模板强制字段:node infotopic info -v、相关 lifecycle 状态、是否 sim_time、RMW 与 domain。新人培训用同一条链复盘两次真实单子,比再发 CLI 速查表有用。

CI 冒烟至少验证:关键话题 hz 下限、lifecycle 到达 active、无 QoS 不匹配的幽灵话题。脚本失败应打印步骤编号,而不是只报 exit 1。

一条链走完再开下一层;echo 是显微镜,不是结论生成器。证据链完整,故障单才可交接、才可自动化。

← 全部文章

johan's blog