# Chapter 13 — 评测指标 > 本章目标:给出 PRISM **每一层、每一管线**的客观评测指标、测试数据集、自动化脚本,确保"做得对"而不是"看起来对"。 --- ## 13.1 评测哲学 ``` 指标分为四类: ① Layer-wise 每层自身的健康指标(L1/L2/L3/L4 各自达标) ② Pipeline-wise 每条管线 A/B/C/D 的端到端指标 ③ System-wise 整体可靠性(72h 压测、健康分) ④ Task-wise 上层任务(取物、巡逻、问答)成功率 测试三种数据: • Synthetic Isaac Sim 仿真,可控、可重复 • Replay 录制的真实数据回放 • Live 机器人真实运行 ``` --- ## 13.2 Layer-wise 指标 ### L1 感知缓冲 | 指标 | 目标 | 怎么测 | |------|------|--------| | 帧到达频率 | 30 ± 1 Hz | 时间戳直方图 | | 写入延迟 | < 50 ms (P95) | grab→ring.append 计时 | | 关键帧采样均匀性 | 间隔 STD < 100 ms | 关键帧时间序列 | | 内存稳定 | < ±5% 漂移/h | RSS 长时间日志 | ### L2 度量 | 指标 | 目标 | 怎么测 | |------|------|--------| | 几何精度(Chamfer) | < 3 cm(静态区域) | 与 iPhone Mesh GT 对比 | | 占据栅格 free/occ 准确 | F1 > 90% | 人工标 GT 随机 100 体素 | | 局部 → 全局合并延迟 | < 5 s | 时间戳跟踪 | | 先验区被错误更新 | 0 次 | prior_mask 写入计数 | | 镜面区噪声 | TSDF noise level < 阈值 | 卫生间专项测 | ### L3 拓扑 | 指标 | 目标 | 怎么测 | |------|------|--------| | 房间识别正确 | 100% | 与 RoomPlan label 对比 | | 门窗连边完整 | Recall > 95% | 与平面图对照 | | 路径规划成功率 | > 99% | 随机起终点 1000 次 | ### L4 语义 | 指标 | 目标 | 怎么测 | |------|------|--------| | 家具识别 mAP@0.5 | > 70% | YOLO 内置 eval | | 物品-家具关系正确 | > 80% | 人工标 100 关系 | | CLIP 检索 Recall@1 | > 85%(房间) / 70%(家具) | 人写 100 个 query | | 隐私过滤召回 | 100%(人不入 LTM) | 录制有人帧专项 | --- ## 13.3 Pipeline-wise 指标 ### 管线 A — iPhone ingest | 指标 | 目标 | |------|------| | 扫描 → LTM 时长 | < 30 min / 房间 | | 节点数 | 单房 30–80 | | Anchor 数 | 每房 ≥ 2 | | Schema validate | 0 errors | | Coverage(mesh 覆盖墙体面积) | > 90% | ### 管线 B — 重定位([`05_pipeline_B_relocalization.md`](05_pipeline_B_relocalization.md) §5.10) | 指标 | 目标 | |------|------| | 冷启动 Recall@1 | > 90% | | 冷启动延迟 | < 1 s | | 位置误差 | < 10 cm | | 朝向误差 | < 5° | | 绑架恢复时间 | < 30 s | ### 管线 C — 在线感知 | 指标 | 目标 | |------|------| | 30 Hz 主循环稳定 | 99% 帧不超时 | | 检测时延 (frame→delta) | < 500 ms | | Detector mAP@0.5 | > 65%(开放词表) | | Change Detector 查准 | > 85% | | Change Detector 查全 | > 70% | | 4 h 运行无崩溃 | 100% | ### 管线 D — 巩固 | 指标 | 目标 | |------|------| | 巩固耗时 (full mode) | < 1 h | | 应用事件 / pending 比 | 10–30% | | Sanity reloc 通过率 | > 90% | | 回滚触发率(健康下降) | < 1 / 月 | --- ## 13.4 System-wise 指标 ### 健康分 (Health Score) ```python def compute_health(mem: SpatialMemory) -> float: """0–100""" s = 100.0 # 锚点数:每房间应 ≥ 2 个 anchor rooms = mem.nodes_of_level(MemoryLevel.L3) weak_rooms = sum(1 for r in rooms if len(r.anchors) < 2) s -= 5 * weak_rooms # 节点新鲜度:3 个月未观测的节点占比 now = time.time() stale = sum(1 for n in mem.nodes.values() if now - n.last_seen > 90*86400) s -= 20 * (stale / max(1, len(mem.nodes))) # delta 积压 pending = len(load_pending()) if pending > 2000: s -= 10 # validate 错误 errs = validate(mem) s -= 5 * len(errs) return max(0.0, min(100.0, s)) ``` 每天 23:55 跑一次,写入 `logs/metrics.parquet`。 | 健康分 | 含义 | 行动 | |--------|------|------| | 90+ | 优秀 | 无需干预 | | 70–90 | 良 | 关注趋势 | | 50–70 | 警告 | 安排巡检 | | < 50 | 危险 | 强制重扫 / 回滚 | ### 长时压测(72 小时) | 指标 | 目标 | |------|------| | 累计运行时长 | ≥ 72 h 无 crash | | 内存 / GPU 内存 | < 5% 增长 | | 重定位漂移(重启对比) | < 30 cm | | LTM 节点数 | 仅微增(< 5%) | | delta 处理无堆积 | pending 周期性归零 | ### SLO / SLI | SLI | SLO(月度) | |-----|------------| | 重定位成功率 | ≥ 95% | | 任务完成率 | ≥ 90% | | 平均无故障时长 (MTBF) | ≥ 48 h | | 错误巩固率 | ≤ 0.5% | | 隐私违规事件 | 0 | --- ## 13.5 Task-wise 指标(上层应用) ### 任务 1:取物("去 X 房间取 Y") | 指标 | 目标 | |------|------| | 整体成功率 | > 90% | | 子任务:物品定位 | > 95% | | 子任务:导航到位 | > 98% | | 子任务:抓取成功 | > 90% | | 平均耗时 | < 60 s | ### 任务 2:巡逻 + 异常检测 | 指标 | 目标 | |------|------| | 完整覆盖率(24 h 内) | > 95% | | 真实异常检出 | > 80% | | 误报率 | < 5 / 天 | ### 任务 3:自然语言问答("床头柜在哪?") | 指标 | 目标 | |------|------| | Top-1 正确 | > 85% | | Top-3 召回 | > 95% | | 平均响应延迟 | < 1 s | --- ## 13.6 测试数据集 ### 13.6.1 HotelScene-Bench v0.5(自建) ``` HotelScene-Bench/ ├── splits/ │ ├── train/ 6 个房间扫描 │ ├── val/ 2 个房间扫描 │ └── test/ 2 个房间扫描(hold-out) ├── annotations/ │ ├── object_3d_bbox.json │ ├── room_polygons.json │ ├── relocalize_gt/ 500 张 frame + 6DoF GT │ └── change_events_gt/ 50 个搬动/搬入事件 ├── traces/ │ ├── trace_normal_24h.bag │ ├── trace_with_changes.bag │ └── trace_kidnap.bag └── tasks/ ├── fetch_100.jsonl 100 条取物任务 ├── qa_200.jsonl 200 条问答 └── patrol_routes.json ``` ### 13.6.2 公开 benchmarks(用于横向对比) | Benchmark | 用途 | |-----------|------| | ScanNet++ | 几何精度对比 | | Replica | 重定位评测 | | Habitat-Matterport 3D | 任务级评测 | | HM3D-Semantic | 语义对比 | | OpenEQA | 问答评测 | --- ## 13.7 自动化评测脚本 ```bash # 单一指标 prism eval reloc --bench HotelScene-Bench/splits/test prism eval change --bench HotelScene-Bench/annotations/change_events_gt prism eval consolidate --bench HotelScene-Bench/traces/trace_normal_24h.bag # 全套(生成 HTML 报告) prism eval all --output reports/$(date +%F)/ ``` 实现:每个 sub-command 是一个 Python 脚本,统一输出 JSON + Markdown + PNG 图表: ```python # tools/prism_eval_reloc.py def main(bench): gt_frames = load_gt(bench/"relocalize_gt/") mem = load("robot_memory/ltm/spatial_memory.json") results = [] for frame, gt_pose in gt_frames: pred = relocalize(frame, mem) results.append(dict( frame_id=frame.id, success=pred is not None and pred.fitness > 0.85, pos_err=np.linalg.norm(pred.T[:3,3] - gt_pose[:3,3]) if pred else None, rot_err=quat_angle(pred.T[:3,:3], gt_pose[:3,:3]) if pred else None, latency_ms=pred.latency_ms)) df = pd.DataFrame(results) print(df.describe()) df.to_parquet(f"reports/reloc_{datetime.now():%Y%m%d}.parquet") save_markdown_report(df) ``` --- ## 13.8 持续监控(Grafana / 飞书报表) 将 `logs/metrics.parquet` 接入 Grafana,监控板包含: | Panel | 数据源 | 阈值 | |-------|--------|------| | 重定位成功率 (7d) | reloc.parquet | < 90% 报警 | | Delta confirm 率 | consolidation.log | 10–30% 正常 | | LTM 健康分 | health.parquet | < 70 报警 | | Anchor 失活数 | health.parquet | 周增 > 3 提醒重扫 | | Jetson 负载 | tegrastats.csv | CPU > 80% 持续 5 min 报警 | | 任务成功率 (7d) | tasks.parquet | < 85% 报警 | | MTBF | crash.log | < 24 h 报警 | --- ## 13.9 A/B 测试框架 当要试新算法(如把 CLIP 换 SigLIP),先 A/B: ```python # tools/prism_ab.py @click.command() @click.option("--variant-a", required=True) # 配置文件 A @click.option("--variant-b", required=True) @click.option("--bench", required=True) def main(variant_a, variant_b, bench): res_a = run_eval_with_config(variant_a, bench) res_b = run_eval_with_config(variant_b, bench) print(compare(res_a, res_b)) significance_test(res_a, res_b) ``` 只有 A/B 显著优于现状才合并 main。 --- ## 13.10 失效案例库 (Failure Case Repo) 每次发现失败,按下表归档: ``` failures/ ├── F0023_reloc_failed_in_303_at_dusk/ │ ├── description.md │ ├── frames/ # 失败时的 RGB+depth │ ├── ltm_snapshot.tar.zst │ ├── log.txt │ └── root_cause.md ``` 每月把这一目录跑一遍当回归测试,确保已修复的不再回归。 --- ## 13.11 关键报告模板 ```markdown # PRISM Weekly Report — Week 23 ## Layer Health - L1: 30.0 Hz ✓ ; P95 latency 32 ms ✓ - L2: Chamfer 2.4 cm ✓ ; no_update_zone hits 0 ✓ - L3: 路径成功率 99.6% ✓ - L4: mAP 71.3% ✓ ; CLIP@1 86% ✓ ## Pipelines - Reloc: success 96.4%, mean pos_err 7.8 cm ✓ - Online: 30 Hz稳定; CPU 38% / GPU 47% ✓ - Consolidate (3 runs): applied 412, rejected 1.3k, rollback 0 ✓ ## System - Health Score: 88 (last week 86) ↑ - 72 h smoke: ✓ - SLO breach: none ## Tasks - Fetch: 92/100 ✓ - QA: Top-1 87%, latency 0.6 s ✓ ## Open Risks - R1.3 卫生间 305 镜面 noise 仍偏高,待修 - R6.1 房间 308 anchor 仅 1,下次重扫优先级 P1 ## Next Week - 部署 DINOv2 重排(A/B) - 修复 R1.3 ``` --- ## 13.12 与 [`09_roadmap.md`](09_roadmap.md) Gate 的强绑定 每个 Gate 都要跑相应 eval 才能通过: | Gate | 必跑 eval | |------|-----------| | W2 | `prism eval ingest` | | W4 | `prism eval reloc` | | W6 | `prism eval online` + 4h soak | | W7 | `prism eval consolidate` + rollback test | | W8 | `prism eval all` | | M4 | 72 h `prism eval all` | | M6 | 全套 + 公开 benchmark 对比 | --- ## 13.13 本章小结 | 评测层级 | 关键指标 | 工具 | |----------|----------|------| | Layer | Chamfer / mAP / CLIP@1 | 逐层脚本 | | Pipeline | Success rate / latency / coverage | `prism eval X` | | System | Health Score / MTBF / SLO | Grafana | | Task | Fetch success / QA Top-1 | `prism eval all` | 读完本章你应能: - ✅ 一行命令出周报 - ✅ 设置 SLO 与报警阈值 - ✅ 把"是否要合并某 PR"建立在数据而非感觉上 下一章 [`14_mvp.md`](14_mvp.md) 把 PRISM 浓缩成 **5 步最小可复现 demo**,让任何工程师周末就能跑通核心闭环。 --- **章节版本**:v1.0 **估计阅读时间**:12 分钟 **关键收获**:建立可量化、可监控、可回归的评测体系