使用手册 - NUSNiuMu/insight-capture-dashboard GitHub Wiki

Insight Capture Dashboard — 使用手册

设备出厂前已完成全部环境配置(Docker、NVIDIA 运行时、内核参数、软件安装), 本手册不含安装步骤,只覆盖日常使用、数据采集与故障排查。 软件升级方式见 §5;开发者功能参考见 主仓库 README。


1. 系统概述

多路 Insight 相机的实时监控与数据采集系统:

Insight 相机 ×3 ──USB 网口──> Jetson 主机 ──docker 容器──> 浏览器
                                │                          http://<设备IP>:8765
                                ├─ 实时画面 + 3D 全局重定位轨迹(同一页)
                                ├─ rosbag 数据录制
                                └─ 完整性校验 / 评分
  • 服务随开机自启:容器 restart: unless-stopped,断电重启后自动恢复, 正常情况下无需任何手动启动操作;设备与相机一起上电时,系统会在开机后 自动重启一次全部相机(相机比主机先启动完成会处于错误的网络状态, 重启一次让它们在主机链路就绪后重新连接,属预期行为)——从上电到画面 就绪约 2-3 分钟;
  • 运行中掉线可自愈,但录制优先:非录制状态下,某路相机连续 15 秒无帧且 USB 网口仍在线时,后端 watchdog 会退出并由 Docker 自动重建 DDS participant; 拔插后通常等待几十秒即可恢复。录制期间不会为了单路掉线重启后端,以免中断 其他相机;应先停止当前录制,再按 §6.2 手动恢复;
  • 所有数据(录制、配置、结果)保存在设备的 rosbags/、config/、outputs/ 目录,软件升级不会触碰它们。

2. 启动与访问

服务开机自启,通常不需要任何操作、直接访问即可(见 §2.2)。需要手动确认/重启服务时:

2.1 手动启动 / 重启

情形 A:不在 Jetson 本机操作(自己电脑远程访问,或 Jetson 没接显示器)

./scripts/run_dashboard.sh             # 启动或确认后端在跑;Ctrl-C 停止前台跟随
./scripts/run_dashboard.sh --logs      # 同时跟随后端日志

脚本自带健康检查与自愈:等待服务就绪、等待全部相机出数据;若检测到 "相机网口已连接但迟迟无数据"(开机时序问题)会自动重启一次后端。可随时 重复执行,幂等。停止服务:docker compose down(在部署目录下执行)。

情形 B:就在 Jetson 本机操作,且接了显示器(要在设备屏幕上看全屏看板)

./scripts/run_dashboard.sh --jetson

2.2 浏览器访问

  • 同一局域网:http://<设备IP>:8765/
  • 或 SSH 隧道(不依赖局域网可达):
    ssh -L 8765:localhost:8765 <用户名>@<设备IP>
    # 然后浏览器打开 http://localhost:8765/

3. 页面与日常操作

路径 用途
/ 或 /3d 三路相机实时画面 + 3D 全局建图/重定位轨迹(同一页,2026-07 起合并)
/recording rosbag 录制:topic 发现、勾选、开始/停止
/bags 本地录制列表:大小/时长/消息与 topic 数、完整性/评分状态,可删除
/umi-dataset 标准 LeRobot v3 或 Legacy UMI Zarr 训练数据导出
/scoring 轨迹评分 + 录制完整性验证
/handpose 从已有 rosbag 离线提取手部 3D 关键点并按时间轴查看
/optimization COLMAP 轨迹优化:对录制的彩色图像做三维重建并与 VIO 轨迹对齐
/settings 手势录制(默认关闭)、Stick-figure 模式全局开关;逐相机开关手部叠加和有效校准的夹爪追踪;Avatar 模型选择

Recording 页的 Recording folder → Browse... 可在录制空闲时切换保存目录。弹窗只显示 Dashboard 容器已挂载的录制盘和 NVMe fallback 范围;浏览器所在电脑上未挂载进容器的普通 本地目录不会出现。确认目录时会执行实际写入和 fsync 探测,成功后 Bags、回放、评分和 数据集导出都会使用新的根目录。录制中或停止排空期间不能切换。本次选择保留到 Dashboard 重启,重启后重新采用 INSIGHT_ROSBAG_DIR、必需挂载源检查和 fallback 配置。

旧地址 /images 现在会自动跳转到 /3d(画面已合并进 Spatial 视图,收藏的旧链接不用改)。

进入 /3d 后场景会先就绪,随后依次接通三路画面、轨迹和模型;模型加载期间不会显示占位物。

Stick-figure 模式(/settings 页开关):开启后 3D 场景不再加载相机模型,改用三个角色配色的大圆点表示头/双手位置,同时叠加手臂骨骼与手部关键点骨架线(手部形状来自手部检测,手臂由固定臂长的 IK 解算合成,是合理近似而非真实追踪)。适合需要直观看操作者身体姿态(手臂弯曲、手指开合)的场景;开关状态影响所有观看者,翻转后下个刷新周期自动生效,无需刷新页面。

手势录制(/settings 页开关):默认关闭。开启后双手点赞保持动作可以开始或停止由手势创建的录制;关闭会立即停止识别新的手势,但不会停止已经进行中的网页手动录制或录制任务。该开关与其他 Settings 开关一样在当前后端进程内即时生效,后端重启后恢复设备 profile 的默认关闭状态。

Hand pose(/handpose 页):在页面内选择 rosbags/ 中已有的录制,点击 Extract hand pose。任务使用 WiLoR 直接读取原录制,不会把 bag 复制到功能 目录;相机坐标结果保存为 outputs/handpose/<bag 名>/wilor/result.json。所需 CUDA/PyTorch 推理运行时和 固定版本权重已包含在 Dashboard 镜像中,设备离线时也可以提取。提取过程会保持 双手时序身份、过滤重复检测,并用 One-Euro Filter 降低 3D 关键点抖动。完成后 可拖动 3D 视图旋转、滚轮缩放、拖动时间轴,并点击关键点查看坐标。提取期间的 进度按目标图像 topic 已处理帧数除以 rosbag 记录的该 topic 总帧数计算,不使用 耗时或动画估算。

训练数据集导出:打开 /umi-dataset,将每次完整示教对应的 rosbag 勾选为 episode,填写英文任务指令,选择单臂 A、单臂 B 或双臂采集布局和训练图像分辨率后, 点击 Build LeRobot dataset。默认输出是与 HiFi-UMI-2K 对齐的 LeRobot v3 目录: outputs/lerobot_datasets/<rosbag 名>_lerobot/。每个选中的 rosbag 会独立处理并保存在设备上。 页面当前默认训练副本为固定下部 ROI 的 224×224;需要保留采集像素时显式选择 Original resolution。

LeRobot 输出包含:

  • data/chunk-000/file-000.parquet:逐帧 observation.state、action、validity mask、 timestamp、episode/frame/task index;
  • videos/observation.images.*/chunk-000/file-000.mp4:所选相机的同步 H.264 视频;三相机 分别映射为 right_hand_up、left_hand_up、head_main;
  • meta/info.json、stats.json、tasks.parquet、modality.json 和 episode parquet: LeRobot v3 schema、归一化统计、语言任务、语义切片和视频/数据分片索引;
  • meta/manifest.json:设备端导出摘要和数据来源。

状态和动作固定使用 HiFi-UMI 风格的 20 维布局:[right_10d, left_10d],每手为 xyz + rotation_6d + gripper。Insight 的夹爪量是经实测标定的物理开口宽度(米),不是 HiFi-UMI 硬件的开口角(弧度),单位会写入 modality.json。单臂数据仍保留 20 维,缺失 手对应的 10 维填零并在 observation.state_valid / action_valid 中标为 false,训练时必须 按 mask 丢弃。action 是同一 episode 的下一帧绝对状态,末帧重复末状态;不要在标准 数据里提前写死 π0.5 的机器人相对动作约定。

所选的每个 Insight3 夹爪都必须在 config/gripper_calibration.json 中提供实测的 width_calibration;因此双臂导出要求 A、B 两侧均完成米制开口宽度标定。配置缺失会使 该 bag 保留并报告配置错误,不会输出伪造的宽度或误删源数据。

OpenPI π0.5 训练配置应把 LeRobot 相机 key、任务文本和 20 维状态映射到模型输入,并在 data transform 中将绝对下一状态转换为部署机器人需要的相对动作。训练前按相同 validity 过滤规则运行 OpenPI 的 compute_norm_stats.py,不要直接复用其他机器人或 HiFi-UMI 设备的归一化统计。

Legacy UMI Zarr:需要继续使用官方 UMI Diffusion Policy 时,在 Dataset format 中 选择 Legacy UMI · Zarr replay buffer。输出仍保存到 outputs/umi_datasets/<rosbag 名>_umi/,包含:

  • <rosbag 名>_umi.zarr.zip:可由官方 UmiDataset 直接读取的数据集;
  • <rosbag 名>_umi.umi.yaml:按所选布局生成 shape_meta;单臂动作维度为 10,双臂为 20。 复制到 UMI 仓库的 diffusion_policy/config/task/ 并修改 dataset_path 后即可用于训练;
  • <rosbag 名>_umi.manifest.json:episode、帧数、同步偏差和夹爪检测率等质量摘要。

Original resolution 保留每路相机在 rosbag 中的原始宽高,不进行缩放;224 × 224 和 384 × 384 会先固定裁剪水平居中、底部对齐的最大方形操作区,再缩放为训练副本, 不会把 portrait 图像直接拉伸成正方形。UMI Zarr 图像使用无损压缩;LeRobot 视频使用 H.264 CRF 18/yuv420p。导出的 metadata 会记录每路相机的 crop box 和编码参数。 后台会在 recorder timeline 上把所选图像、pose、TCP 外参与夹爪二维码检测统一对齐到 20 Hz。

原始分辨率模式允许多路相机使用不同尺寸;UMI 会把各自的 [C,H,W] 写入训练配置, LeRobot 会把各自的 [H,W,C] 和视频参数写入 info.json。 批量处理时某个 rosbag 导出失败不会阻止后续 rosbag,页面会逐包显示设备端保存路径或 失败原因。批处理结束后,因 VIO 连续性、有效帧数、图像解码或夹爪检测等录制数据质量 问题而无法生成任何有效 episode 的源 rosbag 会自动删除;至少生成一个有效 episode 的 rosbag 会保留。相机布局、标定、权限、磁盘或程序异常不会触发删除,避免误删可恢复数据。 原始分辨率会显著增加数据集大小、训练 I/O 和显存占用。UMI Zarr 对 JPEG compressed topic 只解码后无损保存;LeRobot 会统一转码为 H.264,因此会增加一次受控的有损编码。 两种格式都无法恢复采集时已经丢失的细节。

单臂布局的 pose 来自所选 Insight3 原生的 /<namespace>/camera/vio_100hz,每个 episode 使用自己的 VIO 坐标系;输入 bag 必须同时 包含图像和 VIO topic,且该夹爪已完成开合标定。UMI 输出 camera0 / robot0;LeRobot 仍使用 20 维双手 schema,并 mask 缺失侧。双臂布局使用右腕、左腕、头部三路图像,并用 左右 /insight_global/.../pose 保证统一坐标系。夹爪开口宽度来自实测标定,单位为米, 记录在 UMI Zarr 根属性或 LeRobot modality.json 中。默认模式下每条 rosbag 固定对应一个 episode;20 Hz 相邻 TCP 位置变化超过 5 cm、姿态变化超过 45°或 VIO pose 间隔超过 100 ms 时拒绝整条 rosbag,禁止跨越重定位、跟踪丢失或坐标重置插值。通过质量门的事件 计数写入 manifest。 录制页会默认同时勾选每路相机的原始 vio_100hz 和配置的 dashboard/global pose,确保 后续 UMI 单臂导出不依赖用户手动补选原始 VIO。

需要在一条长录制中连续完成多次示教时,可在 Dataset 页面选择 Auto-split long recording at pauses。每一小节结束后保持 TCP 和夹爪静止约 1 秒;检测阈值为连续静止至少 0.8 秒。 导出器会同时检查 20 Hz 下的 平移速度(默认不超过 0.02 m/s)、旋转速度(不超过 10°/s)和夹爪宽度变化速度 (不超过 0.005 m/s),并在静止段中点建立 episode 边界。最多 0.15 秒的单帧检测毛刺 会被忽略。

自动切分不要求每次回到同一个绝对位置。UMI 为每个 episode 单独写入自身的 demo_start_pose,训练配置继续使用 pose_repr: relative;LeRobot 保留采集坐标系的绝对 下一状态,由 π0.5 data transform 按 episode 转为所需相对动作。若某个候选小节跨越 VIO 突跳、跟踪空洞或图像同步 异常,只丢弃该小节,其他完整小节仍会导出;若坐标重置恰好发生在静止段内,边界会 对齐到重置时刻,重置前后的小节都可保留。没有检测到足够长停顿时,整条长录制仍作为 一个 episode;因此采集时应有意停稳约 1 秒。

单路离线夹爪诊断:底层 gripper_extract.py 仍可单独运行,用于检查某一路 Insight3 图像中的二维码检测质量。

底层 gripper_extract.py 直接读取 rosbag 图像,逐帧检测 UMI 夹爪的 ArUco ID 1/0。 结果默认保存到 outputs/gripper/<bag 名>/<相机名>.json,包含 recorder/header 纳秒时间戳、 左右 marker 中心、像素距离和归一化开合度(0=闭合,1=张开)。例如:

docker exec -w /workspaces/insight_capture insight-dashboard \
  /entrypoint.sh python3 scripts/gripper_extract.py \
  rosbags/insight3_a_left_20260803_115721 --camera insight3_a

提取器默认从 config/gripper_calibration.json 按相机名读取全开/全闭像素距离。UMI 数据集导出还要求每个夹爪提供实测的 width_calibration,并按标定点进行分段插值,输出 单位为米。例如(数值仅展示格式,必须替换为实测值):

{
  "insight3_a": {
    "open_px": 247.28,
    "closed_px": 54.55,
    "width_calibration": [
      {"distance_px": 54.55, "width_m": 0.0},
      {"distance_px": 140.0, "width_m": 0.038},
      {"distance_px": 247.28, "width_m": 0.083}
    ]
  }
}

不要直接把归一化开合比例乘以最大宽度;如果机械结构或成像关系不是线性的,应增加中间 实测点。gripper_calibrate.py 可通过 --closed-width-m 和 --open-width-m 写入端点, 中间点可在标定 JSON 中补充。 尚未标定时仍会输出 marker 中心和 distance_px,但 opening 为 null;需要强制 要求开合度时加 --require-calibration。也可用 --open-px <值> --closed-px <值> 临时覆盖标定。多图像 topic 的 bag 应显式传 --topic,具体参数见 scripts/gripper_extract.py --help。

3.1 标准采集流程

  1. 打开 /3d,确认三路画面都在动(面板无 stale 灰标);

  2. /recording → Refresh Topics → 勾选要录的 topic(支持按相机整组勾选)→ Start;

  3. 采集完成 → Stop,等待录包流程结束;

  4. /umi-dataset 选择一条或多条完整示教;默认导出 LeRobot v3,只有兼容旧 Diffusion Policy 训练栈时才选择 Legacy UMI Zarr;

  5. 校验数据完整性并打分:打开 /scoring 页,选中刚录的 bag,点 Scoring(一个按钮同时做两件事:先跑完整性校验,报告先出来;随后 不论完整性结果如何都自动接着跑轨迹评分)。

    • 完整性结果:逐 topic 一行,格式为「消息条数 · 实测频率/标称频率Hz · 丢失 X%」,行首 ok/FAIL 标色。顶部结论只有两种:绿色 Complete(所有 topic 丢帧都在阈值内)或红色 Incomplete (列出具体哪些 topic 丢帧,按 §6.3 排查)。结果会持久保存,/bags 列表中该 bag 会带上徽章 complete / incomplete(从没验证过的 显示 unverified)。
    • 轨迹评分:每台相机一张卡片,给出 0-100 分和一个质量等级标签, 用于横向比较不同录制/相机的相对好坏;评分完成后 /bags 列表该 bag 带上 scored 徽章(未跑过显示 unscored)。评分具体如何计算 不对外说明,仅看结果即可。

也可以在 Insight9 画面内同时做双手点赞:两只手均保持“拇指向上、其余 四指握拳”至少 0.8 秒会使用服务器默认 topics 开始录制。触发后先解除手势 至少 2 秒,再次保持双手点赞 0.8 秒会停止该段录制。手势不会停止网页手动 开始的录制;磁盘剩余低于 10% 或上一段仍在合并时也不会自动开始。Recording 页顶部的 gesture 标签显示 armed、保持、释放和录制状态。

命令行等价方式(脚本化/无浏览器时):

docker exec insight-dashboard python3 scripts/check_bag.py                # 最新一份就可以
docker exec insight-dashboard python3 scripts/check_bag.py rosbags/<目录名>
docker exec insight-dashboard python3 scripts/check_bag.py --fast rosbags/<目录名>  # SQLite COUNT/MIN/MAX 快速聚合;不读取 CDR payload

--fast 不再根据 metadata.yaml 的整包时长估算,而是直接对 SQLite 中每个 topic 执行 COUNT/MIN/MAX(timestamp);它适合快速盘点,不包含录制期间的图像 header 连续性 live audit,不能替代停止录制时生成的最终完整性结论。

3.2 磁盘管理

占用取决于勾选的图像变体和录制时长;同时选择多路 raw/rectified/depth 流时可达到 每分钟数 GB,不能再用固定的“三路默认值”估算。录制前确认空间:

df -h /                              # 剩余空间
du -sh rosbags/* | sort -h | tail    # 各录制占用

删除:/bags 页面操作,或直接删除 rosbags/ 下对应目录(确认已拷贝/不需要后)。 删除是永久操作;rosbags/_staging/ 是中断录制恢复区,不要在恢复/合包期间清理。


4. 轨迹优化(COLMAP)

/optimization 页选择 bag 和相机后启动(目前只支持insight9 彩色图)。设备端全流程运行(GPU 加速特征 提取/匹配),一段 1-2 分钟的录制约需 10-15 分钟出结果,期间页面实时显示 进度和 COLMAP 日志。优化运行时避免同时录制(两者都吃满资源)。

结果不理想时的判断依据:

  • "No good initial image pair found" 反复出现、注册率 <10% → 录制内容不适合三维重建:需要相机有充分的平移运动(不能只旋转/静止)、 场景纹理丰富、光照稳定。换一段运动更充分的录制重跑;
  • 正常成功的参考值:注册率 >50%,Sim3 对齐匹配点数 ≥ 几十个。

5. 软件升级

升级只需要一个新的镜像压缩包(insight-dashboard-vX.Y.Z.tar.gz), 在部署目录执行:

./update.sh insight-dashboard-vX.Y.Z.tar.gz

录制数据、标定结果、配置全部保留。回滚:./update.sh --rollback vX.Y.Z。 固定版本的 SuperGlue 依赖已从日常升级包拆出;只有全新设备首次安装时需要额外提供 insight-superglue-validation-25.04.tar.gz,已有设备不会重复加载或传输。

完整的升级排查步骤、回滚细节、全新设备部署方式见 部署与发布手册。


6. 常见问题排查

任何异常先跑通用三板斧(先怀疑相机是否掉线:查看对应网卡是否存在; 相机重新连上后画面仍不恢复,重启一次后端):

docker ps | grep insight                     # 1. 容器活着吗(STATUS 应为 Up)
curl -s localhost:8765/healthz               # 2. 服务活着吗(应返回 ok)
docker logs insight-dashboard --since 10m 2>&1 | grep -iE "error|warn" | tail

6.1 页面打不开

检查 命令/方法 处理
容器没起来 docker ps -a | grep insight ./scripts/run_dashboard.sh;仍失败看 docker logs insight-dashboard
网络不可达 能否 ping <设备IP> 检查设备联网,或改用 SSH 隧道(§2.2)
浏览器缓存 强制刷新 Ctrl+Shift+R —

6.2 相机画面黑 / 灰标 stale(最常见)

按顺序排查,命中即止:

  1. 物理链路:ip -4 -br addr | grep 169.254 —— 每台在线相机应对应一行。 缺行 → 检查该相机 USB 线和供电,或执行 ./scripts/reboot_cameras.sh (开发机;客户机可直接给相机断电重启);
  2. 开机时序问题(开机后所有相机一直无数据的典型原因): docker restart insight-dashboard,30 秒内应恢复。 说明:服务比相机网口先启动时会绑不上相机链路且不自愈;启动脚本和后端 看门狗已自动处理绝大多数情况,手动重启是兜底;
  3. 运行中拔插或单路停流:未在录制时先等待约 30 秒;watchdog 会在链路在线且 连续 15 秒无帧后重启后端。录制中 watchdog 不会动作,应停止录制,再执行 docker restart insight-dashboard;仍无数据则断电重启该相机;
  4. 以上无效:收集 §7 诊断信息报障。

6.3 录制掉帧 / 数据不完整

症状:/scoring 页点 Scoring 后,完整性结果面板显示红色 Incomplete(或 /bags 列表出现红色 incomplete 徽章、命令行 check_bag.py 报 FAIL)。

按 FAIL 的模式判断:

  1. 只有 image topic 丢、camera_info/IMU 完整 → 内核 UDP 接收缓冲被重置 (常见于系统重刷后)。验证与恢复:
    sysctl net.core.rmem_max          # 正常应为 67108864;若为 212992 即命中
    恢复(一次性,重启后保持):
    sudo tee /etc/sysctl.d/99-dds-rx-buffers.conf >/dev/null <<'EOF'
    net.core.rmem_max = 67108864
    net.core.rmem_default = 67108864
    net.ipv4.ipfrag_high_thresh = 134217728
    net.ipv4.ipfrag_max_dist = 4096
    EOF
    sudo sysctl -p /etc/sysctl.d/99-dds-rx-buffers.conf
    docker restart insight-dashboard
    然后重录一段用 check_bag.py 复验;
  2. 高频小消息或增加 raw image 后丢帧 → 与上一条是不同的内核层:不是 socket 接收缓冲(那个已经够大),是 NAPI 每核 backlog 与单核处理能力不足—— 这台机型相机 USB 网口的中断全部落在 CPU0(cat /proc/interrupts | grep xhci 只有一列非零可确认)。未配置 RPS 时,协议处理也全部留在 CPU0;多相机流量 突发会让该核的 backlog 溢出,包在到达任何 DDS socket 之前就已经在内核网络层被丢弃,ip -s link show <相机对应网口> 的 dropped 计数会在录制窗口内持续增长。验证与恢复:
    sysctl net.core.netdev_max_backlog   # 正常应 >= 8192;默认值 1000 即命中
    cat /proc/net/softnet_stat           # 每行第2列(16进制)=丢包数,录制前后应不变
    for f in /sys/class/net/enx*/queues/rx-0/rps_cpus; do echo "$f: $(cat "$f")"; done
                                         # 相机 cdc_ncm 网卡不能是 00;6 核 Jetson 应为 3e
    恢复(scripts/host_setup.sh 会同时持久化 sysctl,安装并立即运行 insight-camera-network.service):
    sudo ./scripts/host_setup.sh
    然后重录一段用 check_bag.py 复验;
  3. softnet/网卡/UDP 都不丢,但多路 raw image 仍缺帧 → 检查 DDS 模式与 IP 分片重组:
    python3 looper_cli/looper_cli.py --device-base-url http://<相机IP> dds show
    sysctl net.ipv4.ipfrag_max_dist     # jetson-nx 应为 4096
    nstat -az IpReasmFails IpReasmTimeout UdpInErrors UdpRcvbufErrors
    每个新 bag 的 recording_network_audit.json 已保存这些计数在录制窗口内的增量, recording_manifest.json 则保存当时实际选择的 topic。IpReasmFails 大量增长说明 大图 UDP 包已到主机、但在 DDS 之前重组失败。jetson-nx 应使用 config/cameras.json 的 camera_dds_type=cyclonedds;开机恢复流程会幂等校正设备, sudo ./scripts/host_setup.sh 会持久化内核阈值。不要通过换 SSD 或提高 SQLite 同步级别处理。保留失败 bag 与这两个 JSON 后报障;
  4. 所有 topic 在同一时间段一起断 → 录制期间设备被其他任务抢占, docker stats insight-dashboard 观察 CPU;录制时避免同时跑评分/优化任务;
  5. 某台相机自己的全部 topic(含 IMU/VIO)同时断 → 相机侧停顿, 与主机无关;若 recording_network_audit.json 全部为零且 writer queue 也未丢弃, 同一相机多个 topic 在同一 header 时间点一起缺样同样属于发布端节拍缺口。复现请 记录相机名与时间点后报障;
  6. 磁盘写满:见 §3.2。

6.4 录制无法开始 / 停止异常

  • 先看状态:curl -s localhost:8765/api/recording/status;
  • Start 无反应:点一次 Refresh Topics 再试(相机刚重启过时 topic 列表会过期);
  • 注意:录制进行中不要执行 docker restart,会中断录制。 run_dashboard.sh 已内置保护(检测到录制中不重启),手动 docker 命令没有。

6.5 画面卡顿 / 帧率低

  • 相机卡片上的数字是浏览器实际呈现帧率;鼠标悬停可查看 source → processed → IPC → appsrc → encoded → browser received/decoded/presented 的逐段速率和累计丢帧。
  • 后端原始统计也可通过 curl -s localhost:8765/api/cameras | python3 -m json.tool 查看。每路相机的 webrtc_stats 包含主进程覆盖数、worker 限频数、appsrc 失败数和编码速率。
  • source 已低于相机标称帧率时按 §6.2 查相机链路;encoded 正常但浏览器 received/decoded/presented 下降时,检查浏览器、网络和 3D/GPU 合成负载。
  • 录制期间 WebRTC 预览会主动降帧,录制数据本身仍保持相机原生帧率。

6.6 CPU 占用异常高(硬件编码回退)

正常三路相机约占一个核(docker stats insight-dashboard 的 CPU% ≈100%)。 明显偏高时检查硬件编码是否在用:

curl -s localhost:8765/api/images/capabilities | python3 -m json.tool

active_path 应为 jpeg-hardware-nvjpeg(当前该诊断只能用上面这条命令查, /settings 页面已经没有对应的图像管线诊断卡片了)。

现象 处理
hw_jpeg.disabled 里有条目 docker logs insight-dashboard | grep hw_jpeg 看原因,docker restart insight-dashboard 重试
elements.nvjpegenc: false NVIDIA 运行时未注入插件:docker inspect insight-dashboard --format '{{.HostConfig.Runtime}}' 应为 nvidia;仍异常则报障
设备为 Orin Nano 无此硬件,软件编码属预期

即使回退软件编码,功能不受影响,只是 CPU 变高。

6.7 手部叠加/骨架闪烁

  • 2D 图像叠加(画面里的手部关键点线):已做时间戳同步窗口门控,关键点帧 与图像帧差距过大时直接跳过绘制而不是画错位骨架,正常情况下不应有明显闪烁;
  • 3D 场景骨架(Stick-figure 模式或普通模式下的手臂/手部骨架线):手部检测 本身逐帧偶有漏检,已加入"连续命中几次才出现、短暂断检保持上一姿态"的 防抖逻辑,大幅减少闪烁,但检测持续丢失较长时间时骨架仍会消失(预期行为, 不是 bug);
  • 以上均不影响录制数据——叠加/骨架只作用于显示画面,bag 里保存的是 原始图像和原始检测数据;
  • 已知遗留问题:手部检测的左右手判断本身不总是稳定,偶尔可能出现骨架 挂到镜像手上的情况(即左手数据显示在右手位置,反之亦然);不影响图像 或录制数据本身。

6.8 屏幕看板(--jetson)白屏

  • 先用其他电脑的浏览器访问同一地址:能打开说明后端正常,只是本机窗口问题;
  • SSH 登录执行时需指定显示器:DISPLAY=:0 ./scripts/run_dashboard.sh --jetson;
  • 仍白屏:docker restart insight-dashboard 后重试。

6.9 时间不对(录制目录名/日志时间差 8 小时)

设备时区应为 Asia/Shanghai(容器内已配置)。若目录名时间不对,检查设备 系统时间 date;多机采集前确认各设备时间一致(影响数据对齐)。


7. 报障信息收集

报障时执行以下命令,把生成的文件发给我们:

{
  date
  cat /etc/nv_tegra_release | head -1
  sysctl net.core.rmem_max
  docker ps -a | grep insight
  ip -4 -br addr | grep 169.254
  curl -s localhost:8765/api/images/capabilities
  curl -s localhost:8765/api/cameras
  docker logs insight-dashboard --since 30m 2>&1 | tail -100
} > /tmp/insight_diag_$(date +%Y%m%d_%H%M%S).txt 2>&1
ls /tmp/insight_diag_*.txt

若问题与某次录制有关,同时附上该 bag 的检查结果:

docker exec insight-dashboard python3 scripts/check_bag.py rosbags/<目录名> > /tmp/insight_bag_check.txt
⚠️ **GitHub.com Fallback** ⚠️