跳转至

第 4 章 可视化与观测工具

机器人系统的调试高度依赖"看见"——看见 TF 树是否正确、看见激光雷达点云是否成形、看见控制信号是否按预期变化。ROS 2 生态的可视化工具按观察对象分为三类:三维场景观察器(RViz2、Foxglove)、时间序列绘图器(PlotJuggler、rqt_plot)、结构图与日志查看器(rqt_graph、rqt_console)。选对工具比熟练操某一个工具更重要——本章末尾给出按问题类型选择工具组合的经验路径。

1. RViz2:三维场景观察器

RViz2 是 ROS 2 的默认三维可视化前端。其定位是观察器而非仿真器——它渲染话题中携带的几何数据(点云、网格、标记),不参与物理计算,也不驱动关节运动。

1.1 Displays 体系

左侧面板的 Displays 列表决定了 3D 视口中渲染的内容。每个 Display 订阅一个或多个话题,将其解释为某种可视化图元:

Display 类型 订阅话题 渲染内容
TF /tf, /tf_static 坐标系树(箭头 + 名称标签)
RobotModel /robot_description + /joint_states URDF 网格 + 关节位置
LaserScan /scan 二维激光点(扇形分布)
PointCloud2 /points2 三维点云
Image /camera/image_raw 摄像头图像(嵌入式窗口)
Path /plan 路径(折线 + 箭头)
Marker /visualization_marker 用户自定义图元(球、箭头、文本等)
Map /map 占用栅格地图(SLAM 结果)
Pose /goal_pose 单个位姿(六面体 + 坐标轴)

常用交互工具(3D 视口上方工具栏):

  • Interact:拖拽机器人模型(发布 /joint_states 改变视觉位置,不驱动真实硬件)。
  • 2D Goal Pose:点击地图设一个目标位姿,发布 /goal_pose(Nav2 用此接收导航目标)。
  • Measure:点击两点测距离,结果直接显示在状态栏。

1.2 配置文件与启动

RViz2 的显示配置保存为 .rviz 文件(YAML 格式),用 -d / --display-config 参数指定:

## 加载已有配置启动
rviz2 -d $(ros2 pkg prefix my_bringup)/share/my_bringup/config/my_view.rviz

## 运行中保存当前配置:File → Save Config As

配置文件记录了 Fixed Frame(TF 参考坐标系)、各 Display 的话题映射与渲染参数。启动后若视口一片黑或"Frame [map] not found",首要检查 Fixed Frame 是否与 TF 树中某个 frame 名一致(详见第 5 章)。

1.3 Marker 消息

程序化地在 RViz 中绘制几何图形,通过 visualization_msgs/msg/Marker 实现:

from visualization_msgs.msg import Marker
from geometry_msgs.msg import Point
from builtin_interfaces.msg import Duration   # 注意:这是消息类型,字段是 .sec / .nanosec

marker = Marker()
marker.header.frame_id = 'base_link'
marker.ns = 'my_objects'
marker.id = 0
marker.type = Marker.SPHERE       # 球体;

其他:CUBE, ARROW, LINE_LIST, TEXT_VIEW_FACING…
marker.action = Marker.ADD
marker.pose.position = Point(x=1.0, y=0.0, z=0.5)
marker.scale.x = marker.scale.y = marker.scale.z = 0.2  # 直径 20cm
marker.color.r, marker.color.g, marker.color.b, marker.color.a = 1.0, 0.0, 0.0, 0.8
marker.lifetime = Duration(sec=0)  # 0 = 永不过期

lifetime=0 时 Marker 持久显示(直到同名 ns + id 的 Marker 被 DELETE 或 RViz 重启)。MarkerArray(/visualization_marker_array)用于一帧批量发布多个 Marker。调试定位目标、标注障碍物、可视化坐标系关系都用 Marker 实现。

坑:RViz 只是观察器

RViz 不推进仿真、不产生数据:画面不动先查数据源与 TF,而不是调 RViz 本身;它的定位是“看”,不是“算”。

2. Foxglove Studio:通用数据可视化

Foxglove 是不绑定 ROS 的数据可视化与监控平台(支持 ROS 1/ROS 2/MCAP/自定义 JSON schema),有桌面版与 Web 版。与 RViz2 的分工:

维度 RViz2 Foxglove
三维场景 强项(原生 URDF/TF 渲染) 支持(通过 3D panel),插件化
面板类型 仅 3D 视口 3D、图像、表格、原始消息、日志、数据流图、仪表盘
数据源 实时 DDS topic bridge 实时 / MCAP 离线 / rosbag 回放
自定义面板 需写 RViz 插件(C++/Python) Web 技术栈(React),或用内置 panel 组合
部署 桌面 GUI 桌面版 / Web 版(浏览器直接打开)

2.1 连接方式

通过 foxglove_bridge 包与 ROS 2 实时数据桥接。Humble 二进制仓库提供 ros-humble-foxglove-bridge(3.6.0,随发行版更新),launch 入口为 foxglove_bridge_launch.xml,port(默认 8765)、address、tls 与各白名单(topic_whitelist 等)均为可覆盖参数:

sudo apt install -y ros-humble-foxglove-bridge
ros2 launch foxglove_bridge foxglove_bridge_launch.xml port:=8765

Foxglove 客户端中 Add Connection → 选 Foxglove Bridge → 输入 ws://localhost:8765。连接后可浏览所有话题、订阅并实时渲染(客户端侧操作以 Foxglove 文档为准)。

MCAP 文件可直接在 Foxglove 中打开做离线回放,无需 ROS 环境——适合作为实验记录的可视化归档格式。

2.2 典型面板组合

  • 3D Panel:加载 TF + URDF + PointCloud2 + Marker(等效 RViz 场景)。
  • Plot Panel:时间序列曲线(等效 PlotJuggler 的基本功能),可叠加多话题多字段。
  • Raw Message Panel:查看单条消息的完整字段值,调试接口字段含义。
  • Image Panel:显示相机话题,支持 compressed 与 raw。
  • Teleop Panel:按钮/滑杆控件发布 /cmd_vel,做遥控测试。

3. PlotJuggler:时间序列分析

PlotJuggler 是专门做时间序列曲线可视化的工具,支持直接连接 ROS 2 topic 流或加载 rosbag/MCAP 日志。与 rqt_plot 的对比:

维度 PlotJuggler rqt_plot
数据源 topic / bag / CSV / 二进制日志 仅 topic
曲线数量 数十通道不卡顿 超过 5 条明显卡顿
游标/缩放 支持框选缩放、多游标对齐 基本缩放
导出 PNG / CSV / SVG PNG
离线分析 直接打开 bag/CSV 不支持

典型用法——同时观察 PID 控制器的设定值、反馈值与误差:

## 启动 PlotJuggler
plotjuggler

## 在 Data Streams 面板选 ROS 2 → Topic 模式
## 订阅 /cmd_vel.linear.x 和 /odom.twist.twist.linear.x
## 两条例入同一曲线面板,观察跟踪偏差

PlotJuggler 的 TF 变换面板可直接订阅 /tf 话题并绘制某两个 frame 之间的位置/姿态随时间变化,省去手写 listener 脚本。

4. rqt 工具集

rqt 是 Qt 插件框架,ROS 2 保留了 ROS 1 时期的核心 rqt 工具:

工具 命令 用途
rqt_graph rqt_graph 可视化计算图(节点 + 话题 + 服务连接关系)
rqt_console rqt_console 实时日志过滤查看(按级别、节点、话题筛选)
rqt_bag rqt_bag bag 文件可视化(时间轴上显示消息流、手动截取片段)
rqt_plot rqt_plot 轻量时间曲线(适合 1~3 条快速查看)
rqt_reconfigure rqt_reconfigure 动态调参 GUI(列出所有节点参数,滑杆/输入框即时生效)
sudo apt install -y ros-humble-rqt-graph ros-humble-rqt-console ros-humble-rqt-reconfigure

rqt_graph 切换 Topic / Node / Topic (nodewide) 三种视图可分别观察数据流拓扑、节点连接和跨命名空间的完整图。节点名旁的颜色标识通信类型:实线为 topic、虚线为 service。

四类工具接的是同一批数据源,差别在呈现形式与是否要求实时:

flowchart LR
    live["实时 topic"] --> rviz["RViz2<br/>空间与图像"]
    live --> fox["Foxglove Studio<br/>面板监控"]
    live --> plot["PlotJuggler<br/>时序曲线"]
    live --> rqt["rqt 系列<br/>图 / 日志 / 调参"]
    bag["rosbag2 / MCAP 文件"] --> fox
    bag --> plot
    bag --> rqt

5. 工具选择组合经验

按调试问题的类型选择工具组合:

问题类型 工具组合 操作要点
"话题存在但没数据" ros2 topic info --verbose + rqt_graph 确认 QoS 与类型匹配(第 2 章排障清单),rqt_graph 看连接是否建立
"机器人模型显示错误" RViz2 RobotModel + TF Display 检查 URDF 是否加载、joint_states 是否在发、TF 树是否完整
"传感器数据是否正确" RViz2 (LaserScan/PointCloud2) + Foxglove Image 实时观察空间分布;图像通道用 Foxglove 或 RViz Image Display
"控制量跟踪不好" PlotJuggler 多通道曲线 订阅 cmd + feedback,观察超调、稳态误差与振荡
"参数需要反复调" rqt_reconfigure 动态改参数即时生效,无需重启节点
"整体系统结构梳理" rqt_graph + ros2 node list 先图观全貌,再逐个 node info 看订阅发布细节
"实验数据归档与离线分析" ros2 bag record + Foxglove (MCAP) 录制用 mcap 格式;离线打开 Foxglove 可回看全话题时序

判据:按问题类型选工具

结构问题开 rqt_graph,空间与图像开 RViz / Foxglove,时序与跟踪误差开 PlotJuggler;三者解决的不是同一类问题,混用只会增加窗口数量。

6. 远程观测与静态出图

远程看机器人画面、把实验数据落成图,是工具链里的两个外围但高频需求:前者走图像流协议,后者走出图库。

6.1 远程图像流三路线

路线 组成 适用
Foxglove WebSocket foxglove_bridge(上文「连接方式」一节)+ Foxglove 客户端 已在用 Foxglove 调话题,顺带看图像;浏览器直接开
WebRTC aiortc 起信令与媒体轨,av(PyAV)做编解码 要低延迟与双向(遥操作、远程驾驶);浏览器原生 <video> 播放
MJPEG/HTTP aiohttp 起 HTTP 服务,av 把帧编码成 JPEG 流 单流、单向、局域网;十分钟内出画面的最小实现

三条路线的区别在协议栈的厚度:Foxglove 路线复用现有话题通路,代价是带宽与延迟不为一帧图像优化;WebRTC 有拥塞控制、丢帧恢复与抖动缓冲,代价是信令与 ICE 要自己搭;MJPEG 就是一行 HTTP header + 连续 JPEG,没有重传与自适应码率——别在它上面做多路并发与弱网。

6.2 静态出图与缩略图

matplotlib 管的是离线图:把 /joint_states、/odom 一类录下的数据画成 PNG/PDF——时序曲线、误差分布、地图预览。它与 PlotJuggler 的分工是“归档图 vs 实时曲线”:前者要可复现、可入报告,后者要低延迟交互。地图侧的 PGM + YAML 预览也走这条:读 PGM 像素画进 matplotlib,比开 RViz 轻得多(地图归档格式见第 10 章「地图保存与加载」)。

一条纪律:实时回路里不用 matplotlib 画帧——每帧重建 figure 的代价远高于画布更新,也挡在循环里;实时看用 PlotJuggler/rqt_plot,事后出图用 matplotlib。

6.3 算法内部量的可视化:rerun

上面三条远程路线与静态出图都围绕 ROS 话题;而调感知/学习算法时,要看的往往是话题之外的东西:中间特征图、点云配准的对应线、策略输出的动作分布。这类需求用 rerun(pip install rerun-sdk):它在本地起一个查看器,SDK 把图像、点云、张量、时序按时间轴记下,事后拖动时间轴回放:

import rerun as rr

rr.init("perception_demo", spawn=True)          # 起本地查看器(离线改用 rr.save("run.rrd"))
rr.log("camera/image", rr.Image(rgb))           # 图像
rr.log("world/points", rr.Points3D(xyz, colors=rgb_flat))   # 点云(带颜色)
rr.log("train/loss", rr.Scalars(loss))          # 标量曲线

几何体、图像、张量、标量共用同一个时间轴,这是它相对“存图 + 存 npz”的核心差别——回放时各模态对齐到同一时刻。与 Foxglove/MCAP 的分工:话题流用 Foxglove + MCAP(ROS 消息的天然载体,录制回放与团队共享);算法中间量用 rerun(不依赖 ROS,任意张量与几何体都能记)。两者不冲突——同一个实验可以 MCAP 录话题、rerun 记中间量,各管一段。

7. 要点

  • RViz2 是三维场景观察器,不执行物理计算;配置文件的 Fixed Frame 与 TF 树一致性是"画面全黑"的第一排查点。
  • Marker 消息是程序化可视化的核心途径,ns + id 构成唯一键,lifetime=0 持久显示。
  • Foxglove 覆盖 RViz 之外的面板类型需求(表格、日志、仪表盘),同时支持 MCAP 离线回放;与 RViz 互补而非替代。
  • 时间序列分析优先 PlotJuggler(通道多、不卡顿、离线数据源);快速查看单参数变化可用 rqt_plot。
  • rqt_graph 是梳理计算图拓扑的最快方式;rqt_reconfigure 是运行期动态调参的 GUI 入口。
  • 按"连接性 → 空间几何 → 时域曲线 → 参数交互 → 离线归档"五类问题选工具,避免用单一工具解决全部需求。

参考文献与延伸阅读

  • ROS 2. Recording and Playing Back Data(ros2 bag 教程). 文档
  • ROS 2. RViz User Guide. 文档
  • ROS 2. Humble 文档. 文档