From Bits to the Physical World

A Full-Stack Robotics Guide for AI and Software Developers

01The Big Picture

What Is a Robot, Really?The Full-Stack Map of RoboticsWho's Who in the Industry?

02Hardware

SensorsActuatorsCompute Platforms

03Operating System

ROS 2DDS Deep Dive

04Algorithms

SLAMNav2MoveIt 2PerceptionBehavior Trees

05Simulation & Training

Why Simulation?NVIDIA Isaac Sim

06AI Meets Robotics

Reinforcement LearningImitation LearningFoundation Models

07Toolchain

Visualization & DebuggingDev Environment & DevOps

08The Harsh Reality of Deployment

Real-Robot DeploymentReliability EngineeringFleet Management

09Industry Reality

Business ModelsChina vs. GlobalCareer Advice

Part 7: Toolchain · A developer's daily kit

Chapter 19

可视化与调试 - 看见才能修

你写了一个 web 后端,请求返回 500。你怎么调?打开浏览器 DevTools,看 Network 面板,检查请求和响应,查 console 里的报错。整个过程不超过两分钟。

现在换成机器人。你的导航模块在仓库里突然让机器人撞了货架。你怎么调?机器人没有浏览器,没有 DevTools,它当时的“视野”是一堆激光点云和深度图像,它当时的“决策”是一条在 costmap 上算出来的路径,它当时的“理由”是一棵正在执行到第 17 个节点的行为树。这些东西你用 print() 是看不出来的。

这就是为什么机器人领域有一句老话:看不见的 bug 就不存在 - 不是说它真的不存在,而是说如果你没有办法把机器人的内部状态“画”出来,你几乎不可能找到问题。一个 SLAM 算法输出的地图有没有漂移,你盯着一列 [x, y, theta] 的数字是看不出来的,但把它渲染成一张 2D 地图,漂移一目了然。一条局部路径规划是不是太贴墙了,你看日志里的路径点坐标毫无感觉,但在 costmap 上画出来就能立刻看到问题。

机器人调试的核心不是“打日志”,而是“可视化”。这一章讲三个工具:RViz2 帮你看、Foxglove 帮你看得更好、rosbag/MCAP 帮你把“案发现场”录下来事后看。


RViz2 - ROS 2 开发者的第一个朋友

如果你装了 ROS 2,你已经有了 RViz2。它是 ROS 2 自带的可视化工具,几乎每一个 ROS 2 教程都会让你打开它。

RViz2 的工作方式很简单:它订阅 ROS 2 的 topic,把消息内容渲染成图形。你在左边的面板里添加“显示项”(Display),指定数据源(topic 名称),RViz2 就把数据画出来。能画的东西非常多:

TF 树(变换树) - 这可能是你用 RViz2 最频繁的功能。TF 树描述了机器人所有坐标系之间的相对位置关系:base_link(机器人本体)到 odom(里程计原点)的变换、camera_link(相机)到 base_link 的变换,等等。在 RViz2 里你能看到一堆彩色坐标轴在空间中的相对位置,如果某个传感器的外参标定错了 - 比如相机坐标系和机器人本体偏了 90 度 - 你一眼就能看出来。纯看数字?quaternion [0, 0, 0.707, 0.707] 你能一眼看出是旋转了多少度吗?

点云(PointCloud2) - LiDAR 或深度相机输出的 3D 点集。在 RViz2 里渲染成密密麻麻的彩色小点,你能直观地看到机器人“眼中的世界”长什么样。点云里突然有一片空洞?可能是传感器被遮挡了。点云明显歪了?坐标变换有问题。

机器人模型(RobotModel) - 加载 URDF,渲染机器人的 3D 模型。关节角度实时更新,你能看到机器人此刻的姿态。配合 TF 一起看,特别适合调手臂的 IK - 你下发一个目标姿态,RViz2 里能看到手臂到底动到哪了,有没有打到自己。

路径和 costmap - Nav2 的全局路径、局部路径、global costmap、local costmap 都可以叠加显示。这是调导航参数的核心手段 - inflation 半径太大导致通道被“堵死”,在 costmap 可视化里一目了然。

图像(Image) - 相机的 RGB 画面、深度图、分割结果,都能在 RViz2 里实时显示。

RViz2 够用吗?对于单机本地开发,够了。启动你的算法节点,旁边开一个 RViz2 窗口,看着数据流动,发现问题就停下来改。大量 ROS 2 开发者的日常就是这样。

但 RViz2 有几个明确的局限。

第一,它是桌面应用,必须在有 GUI 的环境里跑。你的机器人在仓库里,你在办公室。你要看机器人的点云,只能 ssh 到机器人上然后 X11 转发 - 带宽不够的话,点云渲染卡成幻灯片。或者你在本地跑 RViz2,让它订阅远程机器人的 topic - 但跨网络的 DDS 通信配置是另一个坑(第 8 章讲过 DDS 的各种问题)。

第二,它不能回放历史数据。RViz2 只能看实时数据。机器人凌晨三点撞了货架,你早上来了想看当时发生了什么 - 如果没有提前录数据,RViz2 帮不了你。

第三,多人协作困难。你想让同事看你正在调试的那个画面,只能截屏或者让他也 ssh 过来自己开 RViz2。没有“共享一个调试页面”的概念。

这些局限在实验室阶段不明显,但一旦机器人开始在真实环境部署,每一条都会变成痛点。


Foxglove - 机器人的 Datadog

第 3 章提到过 Foxglove,说它是“机器人的 Datadog”。现在展开讲。

Datadog 对 web 后端开发者来说是什么?是你在浏览器里打开一个 dashboard,能看到所有服务的日志、指标、追踪数据,能搜索、能筛选、能回放,团队里任何人都能看到同一个画面。Foxglove 想在机器人领域做同样的事。

Foxglove 的核心能力分三块:

实时可视化 - 但在浏览器里。 Foxglove 可以直接连接 ROS 2 的 topic(通过 rosbridge 或 Foxglove Bridge),在浏览器里渲染 3D 场景、点云、图像、TF 树、路径 - 基本上 RViz2 能画的它都能画。关键区别是:它跑在浏览器里。你的机器人在深圳仓库,你在家里的 MacBook 上打开 Chrome 就能看到它此刻的 3D 点云。不需要装 ROS 2,不需要 X11 转发,不需要配 DDS 的跨网络通信。

布局系统。 Foxglove 的界面由可自由拖拽的 Panel 组成。你可以在一个屏幕上同时看 3D 视图、相机画面、状态曲线图(Plot)、日志输出、话题列表。这些 Panel 的组合叫 Layout,可以保存和分享。调导航的时候用“导航调试 Layout”(costmap + 路径 + 速度曲线),调抓取的时候切到“抓取调试 Layout”(相机画面 + 关节角度 + 力反馈曲线)。类比一下:就像 Grafana 的 dashboard,但数据源是机器人的 ROS 2 topic 而不是 Prometheus metrics。

录制数据的回放。 这可能是 Foxglove 最杀手级的功能。你把机器人运行时的数据录成文件(后面讲 rosbag/MCAP),然后在 Foxglove 里打开这个文件,就能像看视频一样拖动进度条,在任意时间点查看机器人当时的所有状态 - 它看到了什么、想往哪走、costmap 长什么样、关节角度是多少。调查“机器人凌晨三点为什么撞了货架”这种问题,你需要的就是这个能力。

Foxglove 还有一些加分项:支持自定义 Panel(用 React 写扩展)、支持 MCAP 格式(下一节讲)、有团队协作功能(共享 Layout 和数据)。它的开源版本叫 Foxglove Studio,核心功能免费,云端协作和数据托管是商业化的部分。

一个真实的使用场景:你们团队部署了 5 台机器人在不同仓库,每台机器人都在不停地录 MCAP 数据上传到云端。某台机器人的导航成功率突然下降了,你打开 Foxglove 的 web 界面,拉出最近几天的数据回放,发现是仓库里新放了一排黑色货架 - LiDAR 穿过了黑色表面,costmap 上这一排货架是“隐形”的。如果没有可视化回放,你只能看到“导航失败”的日志,根本不知道是什么物理原因导致的。


rosbag 与 MCAP - 录下“案发现场”

机器人调试和 web 调试最大的区别是什么?不可复现性。

web 服务的 bug 通常可以复现 - 你拿同样的请求参数再打一次,大概率能触发同样的问题。机器人的 bug 很难复现。机器人撞货架那一刻的条件组合 - 当时的光照、地面反光、旁边有个人刚好走过导致 costmap 里出现了一个瞬态障碍物、LiDAR 某一帧恰好漏扫了那个角落 - 这些条件你几乎不可能手动重现。

所以机器人开发者有一个铁律:永远在录数据。 不是“出了问题再去录”,而是机器人只要在跑,数据就在录。等出了问题,你回放录制的数据来分析原因。这就是 rosbag 和 MCAP 的存在意义。

rosbag2 是 ROS 2 自带的数据录制工具。命令很简单:

# 录制所有 topic
ros2 bag record -a
 
# 只录特定 topic
ros2 bag record /scan /tf /camera/image_raw /cmd_vel
 
# 回放
ros2 bag play my_recording

录制时,rosbag2 把你指定的 topic 上的所有消息按时间戳存下来。回放时,它按照原始时间戳重新发布这些消息到对应的 topic 上。对于下游的算法节点来说,回放数据和实时数据没有区别 - 它们都是从 topic 上订阅来的。

这意味着你可以这么调试:录一段机器人在真实环境里的数据,回到办公室,用 ros2 bag play 回放,同时让你修改过的算法节点去处理这些数据,用 RViz2 或 Foxglove 看结果。不需要真机,不需要回到那个环境,就能验证你的修复是否有效。 这比仿真更真实 - 因为数据本身就是真实世界的。

rosbag2 默认用 SQLite3 作为存储后端。这在小规模数据时没问题,但机器人的数据量是很恐怖的:一个 3D LiDAR 每秒产生几十 MB 的点云,加上相机图像、IMU 数据、TF 变换 - 一小时的完整录制轻松超过 100 GB。SQLite3 在这种规模下的读写性能和文件管理都不太理想。

这就是 MCAP 出现的原因。MCAP 是 Foxglove 团队设计的一种专门用于机器人数据的文件格式。它解决了 rosbag 格式的几个痛点:

高效索引。 MCAP 文件内建索引结构,你可以直接跳到文件中任意时间点读取数据,不需要从头扫描。一个 50 GB 的 MCAP 文件,你想看第 37 分钟的数据,几乎是瞬间定位。rosbag 的 SQLite3 后端在大文件上做这种随机访问就慢得多。

跨语言、跨生态。 MCAP 不绑定 ROS 2。它支持多种序列化格式(Protobuf、JSON、ROS 消息、Flatbuffers),可以用在非 ROS 系统里。如果你的项目混合了 ROS 2 节点和自研的非 ROS 模块,MCAP 可以统一录制所有数据。

流式写入。 MCAP 支持边录边写,即使录制过程中程序崩溃了,已经写入的数据也不会丢失。rosbag 在某些情况下,异常退出可能导致整个文件损坏。

ROS 2 的 rosbag2 已经支持 MCAP 作为存储后端。你只需要安装 rosbag2_storage_mcap 插件,然后:

ros2 bag record -s mcap /scan /tf /camera/image_raw

录出来的就是 MCAP 格式,直接拖进 Foxglove 就能回放分析。


踩坑指南:可视化和录制中的真实问题

磁盘写满是最常见的事故之一。 机器人 24 小时运行,rosbag 一直在录,Jetson 上那块 256 GB 的 SSD 三天就满了。满了之后不只是录制停止 - 系统盘也可能满,导致整个机器人挂掉。解决方案:设置录制的分片大小和总量上限(rosbag2 支持 --max-bag-size 和 --max-bag-duration 参数),或者用循环录制 - 只保留最近 N 小时的数据,自动删除旧的。更成熟的做法是录完后自动上传到云端再删除本地文件。

不要录所有 topic。 新手最常犯的错误是 ros2 bag record -a 然后跑一整天。相机原始图像(尤其是深度图像)的数据量巨大,而且大部分时候你调试不需要原始图像 - 你需要的是感知模块的输出(检测结果、位姿估计),而不是输入(原始像素)。想清楚你要调试什么,只录相关的 topic。一个常见的“调试录制配置”:/tf、/tf_static、/scan(LiDAR)、/odom、/cmd_vel、/map、/costmap,加上你自己的关键状态 topic。相机图像只在调感知问题时才录。

时间同步问题。 回放 rosbag 时,如果你的算法节点用的是系统时钟(wall clock),而 rosbag 发出的消息带的是录制时的时间戳,两边对不上。你需要让回放使用仿真时间(--clock 参数)并让算法节点也切到仿真时间模式(设置 use_sim_time 参数为 true)。忘了这一步的话,TF 查询会全部超时,你会看到一堆 Could not transform 的错误,以为是代码有 bug,其实只是时间没对上。这个坑几乎每个 ROS 2 新手都会踩一遍。


可视化工具的选择

如果你刚开始接触 ROS 2,用 RViz2 就够了。它免费、自带、资料多,遇到问题搜索引擎里能找到大量解答。

当你开始在真机上部署、需要远程查看机器人状态、需要事后分析故障数据时,上 Foxglove。它的学习成本不高 - 如果你用过 Grafana 或任何 web dashboard 工具,上手很快。录制格式建议直接用 MCAP,它在各方面都优于 rosbag 的默认 SQLite3 后端。

还有一个工具值得提一句:Rerun。第 3 章也简单提过。如果说 Foxglove 更像运维监控平台(Datadog 的定位),Rerun 更像开发者调试工具(类似 TensorBoard)。它特别适合调感知算法 - 你可以在同一个界面里同步查看原始图像、检测框、点云、位姿估计结果,而且 Python API 非常简洁,几行代码就能把数据丢进去看。如果你的工作重心在感知模块,Rerun 比 Foxglove 用起来更顺手。

机器人调试的本质是:把高维的、抽象的、不直觉的数据,变成人眼能理解的画面。点云、costmap、TF 树、行为树执行状态 - 这些东西在日志里是数字,在可视化工具里是图形。当你盯着数字百思不得其解的时候,画出来看一眼,答案往往就在那里。

← Previous18. Foundation ModelsAI Meets RoboticsNext→20. Dev Environment & DevOps