5.5.4 数据可视化
Foxglove 可视化
使用 Foxglove Studio 对机器人话题数据进行实时可视化。
机器人端运行 foxglove_bridge,将话题数据通过 WebSocket 发布;上位机(PC)运行 Foxglove 客户端订阅并可视化。两者需处于同一网络中。
安装 Foxglove
上位机安装 Foxglove 桌面版或使用网页版,均可用任意账号登录:
备注
使用网页版连接机器人(ws:// 明文连接)时,浏览器可能因安全策略拦截而无法连接;此时在网页右上角选择启用不安全脚本即可。
启动 foxglove_bridge
在开发计算单元(PC2,10.0.1.41)启动 foxglove_bridge(环境中已预装):
# source 环境变量
source /opt/ros/humble/setup.bash
source ~/aimdk/install/setup.bash
# 启动 foxglove_bridge(默认配置文件)
ros2 launch foxglove_bridge foxglove_bridge_launch.xml
连接到机器人
在上位机的 Foxglove 桌面版 / 网页版中进入控制台,选择 打开连接。
选择 Foxglove WebSocket 协议(可连接 ROS 1、ROS 2 或自定义系统),将默认地址 ws://localhost:8765 中的 localhost 替换为目标机器 IP,点击 打开 建立连接。
添加面板
完成连接后,在右上角选择添加面板,根据目标 topic 选择相应面板——例如雷达点云选3D面板,TF 关系选变换树。
话题设置
单击对应面板,即可在左侧选择可视化所需的 topic、参考系等面板配置。
导入布局
除手动添加面板外,也可以直接导入预设布局(URDF 显示仅限桌面版)。在 Foxglove 右上角点击布局图标:
导入下面的配置文件(使用前需将配置文件中的 $URDF_DIR 改为本地 urdf 实际路径):foxglove_layout.json
foxglove_layout.json(点击展开查看)
{
"configById": {
"Image!3uaqfl": {
"cameraState": {
"distance": 20,
"perspective": true,
"phi": 60,
"target": [
0,
0,
0
],
"targetOffset": [
0,
0,
0
],
"targetOrientation": [
0,
0,
0,
1
],
"thetaOffset": 60,
"fovy": 45,
"near": 0.5,
"far": 5000
},
"followMode": "follow-pose",
"scene": {},
"transforms": {},
"topics": {},
"layers": {},
"publish": {
"type": "point",
"poseTopic": "/move_base_simple/goal",
"pointTopic": "/clicked_point",
"poseEstimateTopic": "/initialpose",
"poseEstimateXDeviation": 0.5,
"poseEstimateYDeviation": 0.5,
"poseEstimateThetaDeviation": 0.26179939
},
"synchronize": false,
"imageMode": {
"imageTopic": "/aima/hal/sensor/rgb_head_front_center/rgb_image/compressed",
"calibrationTopic": "/aima/hal/sensor/rgb_head_front_center/camera_info"
}
},
"TransformTree!1x6xlz3": {},
"3D!4h2shil": {
"cameraState": {
"distance": 7.169718448166827,
"perspective": true,
"phi": 51.81818181819366,
"target": [
0,
0,
0
],
"targetOffset": [
1.925555282550379,
-0.29000302203140244,
-3.7627255213825705e-17
],
"targetOrientation": [
0,
0,
0,
1
],
"thetaOffset": 111.27272727272965,
"fovy": 45,
"near": 0.5,
"far": 5000
},
"followMode": "follow-pose",
"scene": {
"transforms": {
"visible": false
},
"ignoreColladaUpAxis": true,
"meshUpAxis": "z_up"
},
"transforms": {},
"topics": {
"/aima/hal/sensor/lidar_chest_front/lidar_pointcloud": {
"visible": true,
"colorField": "intensity",
"colorMode": "colormap",
"colorMap": "turbo"
},
"/perception/debug/obstacle_cluster": {
"visible": false
},
"/aima/hal/sensor/rgb_head_rear/camera_info": {
"visible": false
},
"/aima/hal/sensor/rgb_head_front_center/rgb_image/compressed": {
"visible": false,
"cameraInfoTopic": "/aima/hal/sensor/rgb_head_front_center/camera_info"
}
},
"layers": {
"grid": {
"visible": true,
"drawBehind": false,
"instanceId": "d3834cc3-4c3e-40a9-8929-a318e6037634",
"layerId": "foxglove.Grid",
"size": 10,
"divisions": 10,
"lineWidth": 1,
"color": "#248eff",
"position": [
0,
0,
0
],
"rotation": [
0,
0,
0
]
},
"44530a1b-44f8-4bf8-beb2-0a9e2df95e96": {
"controlMode": "transforms",
"jointStatesTopic": "",
"displayMode": "auto",
"fallbackColor": "#ffffff",
"showAxis": false,
"axisScale": 1,
"showOutlines": true,
"opacity": 1,
"visible": true,
"instanceId": "44530a1b-44f8-4bf8-beb2-0a9e2df95e96",
"layerId": "foxglove.Urdf",
"label": "URDF",
"sourceType": "filePath",
"url": "",
"filePath": "$URDF_DIR/x2_ultra.urdf",
"parameter": "",
"topic": "",
"framePrefix": "",
"order": 1
}
},
"publish": {
"type": "point",
"poseTopic": "/move_base_simple/goal",
"pointTopic": "/clicked_point",
"poseEstimateTopic": "/initialpose",
"poseEstimateXDeviation": 0.5,
"poseEstimateYDeviation": 0.5,
"poseEstimateThetaDeviation": 0.26179939
},
"synchronize": false,
"imageMode": {},
"followTf": "base_link"
}
},
"globalVariables": {
"globalVariable": 3
},
"userNodes": {},
"playbackConfig": {
"speed": 1
},
"layout": {
"direction": "row",
"first": {
"first": "Image!3uaqfl",
"second": "TransformTree!1x6xlz3",
"direction": "column"
},
"second": "3D!4h2shil"
}
}
该布局同时显示雷达点云、URDF、交互相机、TF 实时数据:
更多配置可参考 Foxglove 官方文档。
建图与重定位
高程图、动态障碍物等感知话题依赖建图与重定位就绪。前置条件:
机器人为稳定站立模式
以下 app 已启动(通常随系统自动启动,可通过
ros2 node list确认):slam—— 建图与重定位map_manager—— 地图管理perception—— 感知pnc—— 规划与控制auto_integrated—— 导航集成
警告
请勿进入开发者模式中的自主开发模式,否则上述 app 可能不会自动启动,导致感知话题无数据。
若前置未就绪,相关话题将无数据发布。可通过以下方式确认:
# 检查节点是否启动
ros2 node list | grep -E "slam|perception|pnc"
# 检查话题是否有数据(应有持续输出)
ros2 topic hz /perception/grid_map
感知可视化话题说明
话题名称 |
数据类型 |
描述 |
QoS |
频率 |
|---|---|---|---|---|
|
左目图像实例分割可视化结果(调试用,理解机器人识别到了什么) |
|
10Hz |
|
|
语义点云(避障输入,区分可通行/障碍/行人) |
|
10Hz |
|
|
高程图(地形可通行性,判断台阶/坑/斜坡) |
|
10Hz |
|
|
动态障碍物(动态避障,追踪移动的人/物) |
|
10Hz |
所有话题 QoS 详细配置:history=keep_last, depth=10, reliability=reliable, durability=volatile
坐标系说明
机器人各部件坐标系遵循 ROS 标准的 FLU 约定(X 轴向前、Y 轴向左、Z 轴向上),详见 坐标系。本章话题涉及两个关键坐标系:
坐标系 |
含义 |
特点 |
|---|---|---|
|
全局世界坐标系,由 SLAM 建图时确定 |
固定不动,Z 轴朝上,X/Y 在水平面;高程图、动态障碍物使用此坐标系 |
|
机器人本体坐标系(重力对齐) |
随机器人移动而平移、转向而旋转;X 轴指向机器人正前方,Y 轴指向左侧,Z 轴指向上方;语义点云使用此坐标系 |
两者的关系:map 是固定的世界参考系,gravity_aligned_base_link 随机器人运动。机器人在 map 中的位置和朝向,通过 TF 变换 map → gravity_aligned_base_link 查询,例如:
# 查询机器人在全局地图中的位姿(平移=位置,旋转=朝向)
ros2 run tf2_ros tf2_echo map gravity_aligned_base_link
对可视化数据的影响:
高程图、动态障碍物等话题的坐标值是相对
map的,方向固定于世界,不随机器人转向而变。语义点云的坐标值是相对
gravity_aligned_base_link的,随机器人转向而变化(X 轴始终指向机器人正前方)。若需在两个坐标系间转换坐标,使用 TF(
tf2_ros/tf2_geometry_msgs)。
图像实例分割可视化结果
绘制了左目图像的实例分割结果,包含类别名称、置信度、边界框、分割图等可视化信息。
语义点云
当前传感器 FOV 内的点云,frame_id 为 gravity_aligned_base_link(机器人本体坐标系,X 轴指向正前方,见上方坐标系说明)。使用颜色区分不同语义,各类别颜色(BGR)如下:
语义类别 |
BGR |
颜色 |
|---|---|---|
可通行区域 |
|
蓝色 |
静态障碍物 |
|
紫色 |
行人 |
|
绿色 |
颜色值存储在 PointCloud2 的 rgb 字段中(float32 位域打包为 uint32,格式为 0x00RRGGBB),解包方式参考 ROS2 sensor_msgs_py/point_cloud2.py。
高程图
基于当前传感器输入生成的栅格高程图,frame_id 为 map(坐标系原点与方向固定,见上方坐标系说明),分辨率 0.05m,尺寸 8m×8m(160×160 栅格)。地图是一个跟随机器人移动的滑动窗口:每帧将窗口中心对准机器人位置(info.pose.position 即机器人在 map 下的位置),机器人始终位于图中心,实际覆盖范围为机器人周围约 ±4m;超出窗口的旧栅格数据会被丢弃。需要注意的是,平移的是地图窗口(可见范围),而非坐标系本身——各栅格的坐标值始终是 map 绝对坐标,不随机器人移动而变化。包含三个层:
层名 |
数据类型 |
内容 |
|---|---|---|
|
|
栅格高度值( |
|
|
高程方差,反映该栅格高度估计的不确定度;未观测为 |
|
|
语义类型,取 |
每个栅格的语义由多帧观测累积得到:新观测会更新该栅格的语义置信度,长时间未观测的栅格置信度会逐渐降低。消息解析使用 GridMapRosConverter::fromMessage,参考 grid_map_ros 官方文档。
动态障碍物
每个障碍物对应 4 个 marker,按命名空间(ns)与类型(type)区分:
marker 命名空间( |
类型( |
内容 |
|---|---|---|
|
|
障碍物中心点位置,保存在 |
|
|
障碍物速度:方向保存在 |
|
|
障碍物 ID 与速率大小,保存在 |
|
|
二维包围多边形顶点,保存在 |
每个障碍物的 4 个 marker 共享同一种颜色,颜色按障碍物 ID 自动分配,与语义点云按类型着色的方式不同。
每条 MarkerArray 消息的 markers 数组按以下顺序构造:
先追加 4 个
action = DELETEALL(3)的 marker,分属上述 4 个命名空间,清空上一帧画面再为每个障碍物依次追加 4 个
action = ADD(0)的 marker(cylinder→arrow→text→polygon)重绘当前帧
因此每条消息自包含完整画面,订阅者直接使用最新一帧替换即可,无需跨帧累积;话题以 10Hz 整帧刷新。所有 marker 的 header.frame_id 为 map(全局世界坐标系,见上方坐标系说明),header.stamp 为当前帧时间戳。与高程图不同,动态障碍物的坐标是 map 绝对坐标,不随机器人移动而平移或裁剪——只要传感器观测到的障碍物都会在 map 中标出,机器人位置不编码在消息中(需通过 TF 查询)。
图中细圆柱表示障碍物中心点(cylinder marker),外圈多边形表示障碍物轮廓(polygon marker)。
RSView 可视化
RSView 是 RoboSense 提供的激光雷达数据可视化工具,可实时显示 E1R 点云数据,也支持从 .pcap 文件离线回放。
软件功能
通过以太网实时显示数据
将实时数据记录保存为 PCAP 文件
从记录的 PCAP 文件中回放(不支持
.pcapng格式)多种可视化模式:距离、时间、水平角度、反射强度、激光线束序号等
用表格显示点的数据
将点云数据导出为 CSV 格式文件
测量距离工具
将回放数据的连续多帧同时显示
裁剪显示
安装 RSView
RSView 支持在 Windows 64 位、Ubuntu 18.04 及以上操作系统上运行。
从 RoboSense 官网下载最新版本:https://www.robosense.cn/resources-160
软件无需安装,解压后运行可执行文件即可使用。解压路径请勿出现中文字符。
在线模式
注意
在集成的 X2 机器人上,RSView 在线模式不可用——请改用 Foxglove / RViz 实时查看点云。原因有二:
单播:机器人上的 E1R 点云为单播,只发往机器人本机(如
10.11.1.1),同网段的其他电脑收不到这份数据;端口被占:MSOP / DIFOP 端口(
6699/7788)已被机器人 HAL 驱动独占,RSView 无法再 bind。
实时查看点云的正确方式:HAL 驱动已把雷达 UDP 实时转成 ROS topic,直接在 Foxglove 3D 面板(或 RViz)订阅即可——同源数据、同样实时、零改动、不打断机器人:
/aima/hal/sensor/lidar_chest_front/lidar_pointcloud # sensor_msgs/PointCloud2
用法见上文「Foxglove 可视化」的添加面板 / 导入布局。若只想离线分析录制数据,见下文「离线回放(pcap 文件)」。
离线回放
通过
dumpcap指定雷达网口抓包:
dumpcap -i sensor0 -f "udp port 6699 or udp port 7788" \
-w ~/lidar_capture.pcap
在 RSView 中选择左上角 File → Open PCAP File,选择已录制的
.pcap文件,并且选择对应的sensor type进行回放。
RViz 可视化
RViz 通过 DDS 直接订阅机器人话题,可实时观测机器人模型、运动行为、TF、雷达点云、地图等信息。
注意
RViz 依赖 DDS 网络直连,目前仅支持有线直连方式(无法跨 VPN / 无线),网口配置详见网络连接。
按网络连接完成有线直连、并设 ROS_DOMAIN_ID 与机器人一致后,启动 RViz2 即可:
source /opt/ros/humble/setup.bash
rviz2
TF、雷达点云、地图、运动行为等均通过 DDS 直接订阅,无需额外发布。当想查看 URDF(机器人模型)时,需另开一个终端发布 robot_description:
source install/local_setup.bash
ros2 run robot_state_publisher robot_state_publisher \
--ros-args -p robot_description:="$(
sed "s#filename=\"\\./meshes/#filename=\"file://$URDF_DIR/meshes/#g" \
"$URDF_DIR/x2_ultra.urdf"
)" # $URDF_DIR 换成 urdf 文件实际路径
系统状态、日志、通信可视化
机器人调试 TUI 工具。SSH 友好,不需要图形界面。一个统一菜单驱动的 Textual app,把开发现场最常看的几类信息聚到一起,不依赖 rviz / Foxglove,纯终端可用。
主要功能
系统状态仪表盘(dash)
五格实时面板,集中展示五大子系统状态:
MC Action:当前运动行为(如
STAND_DEFAULT/LOCOMOTION_DEFAULT)及运行/切换状态System:SystemState 业务状态(如
IN_READY/IN_MOVE)Faults / HDS:活跃诊断码、告警码、post-proc 信号计数及最近一条码
PMU / Battery:PMU 温度、Orin 电压电流、电池容量、错误位
Orin:Jetson Orin CPU/GPU/MEM/温度,由独立 orin-monitor 进程发布
日志聚合(logs)
将多路日志统一到一个 TUI 页面,支持实时查看、历史查询和过滤:
ROS2 节点日志:
~/.ros/log/<latest_session>/(默认源,可--no-ros跳过)其他日志文件:
--add-path FILE添加可选订阅:
/rosout(--rosout,仅实时模式)自动解析多种时间戳格式并统一时区
支持
--since 10m、"yesterday 18:00"、绝对时间等查询方式支持过滤 DSL,如
level>=WARN node~=slam connect
通信可视化(comm)
展示当前 ROS graph 中的 topic / service;默认过滤隐藏 topic,行为与
ros2 topic list一致。支持对选中 topic 按需测频,启动时零订阅负载,QoS 自动匹配发布者。故障 / HDS(faults)
健康诊断系统专屏:
Live:实时展示 Diag / Alert / PostProc 三类数据
History:通过
GetHdsEventHistory查询历史故障,支持按时间窗、状态、诊断码过滤和分页
Orin 监控发布器(orin-monitor)
独立 ROS2 节点,采集 Jetson Orin 的 CPU/GPU/MEM/温度等资源信息,并以
diagnostic_msgs/DiagnosticArray发布到/orin/stats。采集基于 psutil + tegrastats ,可供 dash、bag 记录或其他节点订阅。
统一入口:ros2 run robotop robotop 不带参数进菜单,方向键选屏,Enter 进入,子屏 q 回菜单,菜单 q 退出,Ctrl+C 任意位置强退。也可以走直接子命令:robotop dash / robotop logs --since 1h 等。
安装
依赖工作区已包含 aimdk_msgs、rclpy、diagnostic_msgs。运行时 Python 包装在用户目录:
pip3 install --user typer textual dateparser
构建:
cd ~/aimdk
colcon build --packages-select robotop
source ~/aimdk/install/setup.bash
注意:
dash的 Orin 卡片需要独立的orin_monitor_node后台发布/orin/stats,否则会显示 stale:ros2 run robotop orin_monitor_node
命令总览
命令 |
功能 |
|---|---|
|
顶层菜单,统一入口 |
|
系统状态面板(MC / System / Faults / PMU / Orin) |
|
聚合 ROS / app 日志,实时或历史 |
|
topic/service 列表 + 按需测频 |
|
HDS 诊断/告警实时表; |
|
发布 |
ros2 run robotop robotop # 进菜单(推荐)
ros2 run robotop robotop <subcmd> [options] # 直接进某屏
ros2 run robotop orin_monitor_node # 独立 node,适合 systemd
dash — 系统状态
ros2 run robotop robotop dash
五个卡片 :
卡片 |
数据来源 |
说明 |
|---|---|---|
MC Action |
|
当前 MC 模式 + 状态(RUNNING / TRANSITION / IDLE) |
System |
|
业务状态名(IN_READY / IN_MOVE 等) |
Faults / HDS |
|
活跃 diag/alert 数 + 最近一条码 |
PMU / Battery |
|
PMU 温度、电压电流、电池容量、错误位 |
Orin |
|
需先启 orin_monitor_node |
键位:q 回菜单,r 立即刷新,Ctrl+C 强退。卡片显示 [stale] 表示对应数据源没接通。
logs — 日志聚合
实时(默认)
ros2 run robotop robotop logs --follow
ros2 run robotop robotop logs -f --rosout # 加 /rosout 订阅
ros2 run robotop robotop logs -f --add-path ~/.aima/log/aima.log # 加入 AIMA 日志
ros2 run robotop robotop logs -f --no-ros # 跳过 ROS session 日志源
默认源:最新 ROS session 的最新 .log 文件(~/.ros/log/<latest_session>/<最新>.log)。AIMA、AIMRT 等其他日志需用 --add-path 显式加入。
历史查询
ros2 run robotop robotop logs --since 1h
ros2 run robotop robotop logs --since 7d --level WARN
ros2 run robotop robotop logs --since "2026-06-04 14:00" --until "2026-06-04 16:00"
ros2 run robotop robotop logs --since 30m --grep "fall"
--since / --until 支持:相对(30s / 10m / 1h / 2d)、now、自然语言("yesterday 18:00")、绝对时间("2026-06-04 14:00")。
TUI 键位
键 |
动作 |
|---|---|
|
进顶部过滤输入框 |
|
退出过滤框回 log 区 |
|
应用当前过滤 |
|
清屏 |
|
退出 |
过滤 DSL:顶部输入框,空格分隔,全部命中才显示。
表达 |
含义 |
|---|---|
|
消息同时含 “error” 和 “connect”(大小写不敏感) |
|
等级正好等于 ERROR |
|
WARN 及以上(DEBUG < INFO < WARN < ERROR < FATAL) |
|
来源含 “slam” |
|
同上( |
faults — HDS 故障
Live(默认)
ros2 run robotop robotop faults
三个 tab 分别对应:Diag(/aima/hds/diag_code_list)、Alert(/aima/hds/alert_code_list)、PostProc(/aima/hds/post_proc/signal)。
History
ros2 run robotop robotop faults --history --since 1h
ros2 run robotop robotop faults --history --since 1d --state active
ros2 run robotop robotop faults --history --diag-code 0x6300000001
ros2 run robotop robotop faults --history --alert-code battery_low --asc
参数 |
含义 |
|---|---|
|
时间窗,同 logs 解析规则 |
|
状态过滤 |
|
按诊断码过滤(可重复) |
|
按告警字符串过滤(可重复) |
|
最多返回条数(默认 200) |
|
时间正序(默认倒序) |
comm — 通信可视化
ros2 run robotop robotop comm # 默认与 ros2 topic list 一致
ros2 run robotop robotop comm --include-hidden # 显示所有,含 _* 隐藏路径
两个 tab:Topics(列 M / topic / type / pub / sub / hz / count)和 Services(列 service / type)。
键 |
动作 |
|---|---|
|
toggle 测频:开始 subscribe + 计数 / 停止并销毁订阅 |
|
一键停掉所有正在测频的 topic |
|
进顶部过滤栏(子串匹配 name 或 type) |
|
退出过滤回表格 |
|
立即重新枚举 |
|
退出 |
orin-monitor — Orin 资源 publisher
ros2 run robotop orin_monitor_node # 1 Hz,默认
ros2 run robotop orin_monitor_node --rate 2 # 2 Hz
采集基于 psutil + tegrastats。发布到 /orin/stats,类型 diagnostic_msgs/msg/DiagnosticArray。Key 包含:cpu_pct_avg、cpu_cores、cpu_pct_core_0..N、gpu_pct、mem_used_mb、mem_total_mb、mem_pct、temp_cpu、temp_gpu、temp_thermal、power_total_mw。
持久化运行(tmux):
tmux new -d -s orin 'source /opt/ros/humble/setup.bash && source ~/aimdk/install/setup.bash && ros2 run robotop orin_monitor_node'
# 看输出:tmux attach -t orin (Ctrl-b d 退出 attach,不杀进程)
# 停掉:tmux kill-session -t orin