---
title: "Chapter 08 — 端到端运行时序"
date: 2026-05-20
draft: false
tags: ["PRISM", "世界模型", "空间记忆", "机器人", "iOS", "ZED2i"]
categories: ["PRISM"]
---
# Chapter 08 — 端到端运行时序
> 本章目标:把 Chapter 04–07 的四个管线**串成一条完整的时间线**,用一个具体酒店场景的"剧本"展示 PRISM 如何在 T0 到 T4 的全生命周期工作。
---
## 8.1 场景设定
> 某商务酒店 3 楼,共 8 间客房 + 走廊 + 电梯厅,约 300 m²。
> 部署一台轮式服务机器人「Robo-Concierge」,搭载 ZED 2i,需要:
> - 自主巡逻
> - 接受客人语音指令"去 308 取一下遥控器"
> - 早晨给打扫清单上的房间送备品
> - 检测家具异常移动(防盗 / 维护提醒)
---
## 8.2 时间线全景
```mermaid
timeline
title PRISM 端到端运行时序 T0 -- T6
section 部署前
T0 D-7 : iPhone 离线扫描 → 灌入 LTM
section 开机当天
T1 9点 : 机器人首次开机
重定位握手
T2 全天 : 巡逻/任务
delta 累积
T3 14点30 : 取遥控器任务
T4 22点 : 充电桩
记忆巩固
section 长期维护
T5 D+30 : 月度深度巩固
T6 D+90 : 装修后部分重扫
```
---
## 8.3 T0:iPhone 离线扫描(D-7,运维人员)
### 物理动作
```
09:00 运维进入 3 楼电梯厅
09:01 放置 ArUco 标识在地面(id=42, 30 cm×30 cm)
09:03 打开 PRISMScanner App
09:05 ── 单 session 开始 ──
1) 在电梯厅扫一圈,看到 ArUco ✓
2) 沿走廊缓慢推进
3) 进 301,扫描 12 分钟
4) 退出 301,沿走廊
5) 进 302...... 重复直到 304
09:55 暂停 session(4 个房间)
10:00 换电池 + 第二 session(305–308)
10:50 全部完成
```
### 数据落地(D-6,工作站)
```
data/scans/
├── 2026-05-09_3F_session1/ # 301-304
│ ├── Hotel.usdz
│ ├── roomplan.json
│ └── arkit/ (rgb + depth + pose)
└── 2026-05-09_3F_session2/ # 305-308
└── ...
```
### Ingest(D-5,工程师)
```bash
# Session 1
python -m tools.prism_ingest_iphone \
--scan data/scans/2026-05-09_3F_session1/ \
--out robot_memory/ltm/ \
--aruco-id 42
# Session 2(追加进同一 LTM)
python -m tools.prism_ingest_iphone \
--scan data/scans/2026-05-09_3F_session2/ \
--out robot_memory/ltm/ \
--aruco-id 42 \
--merge
# 检查
python -m tools.check_anchors # 期望 ≥ 16 个 anchor(每房 2 个)
python -m tools.viz_octomap # 人眼检查走廊可通行
```
输出:
```yaml
nodes: 289 (8 房 + 8 走廊 + ~273 家具)
edges: 312
anchors: 21
LTM size: 3.4 GB
```
### 部署
```
D-3: 把 robot_memory/ 拷贝到机器人 SSD
D-2: 机器人在测试间预演重定位(不到现场)
D-1: 机器人运到 3 楼电梯厅,关机待命
```
---
## 8.4 T1:机器人首次开机(D 早上 9:00)
### 时序(精确到毫秒)
```mermaid
sequenceDiagram
autonumber
participant U as 用户 电源
participant R as ROS 2 PRISM
participant Z as ZED 2i SDK
participant FP as Frame Producer
participant RL as Relocalizer
participant NAV as Avoidance Nav
participant FSM as 状态机
U->>R: 09:00:00.000 Power on
R-->>R: 09:00:02.500 节点 launch 完成
R->>Z: 09:00:02.600 启动 ZED 2i SDK
Z->>FP: 09:00:03.100 第一帧到达
FP->>RL: 09:00:03.150 触发 cold_start
RL-->>RL: 09:00:03.230 CLIP 编码当前帧
RL-->>RL: 09:00:03.310 L3 Top-3 lobby_3F 0.82 room_308 0.41 hallway_3F 0.39
RL-->>RL: 09:00:03.320 几何配准 FPFH+RANSAC 0.74 ICP refine 0.91 通过
RL->>R: 09:00:03.510 发布 TF map to zed2i_init
R->>NAV: 09:00:03.550 Avoidance Nav 上线
R->>FSM: 09:00:03.600 状态机 to IDLE
FSM-->>U: 09:00:04.000 开始默认任务 巡逻
Note over U,FSM: 总冷启动约 3.6 秒 其中 PRISM 握手约 400 ms
```
**总冷启动时间:~ 3.6 秒**(其中 PRISM 的握手 ~ 400 ms)
### 内部状态变化
| 时刻 | L1 | L2 局部 | L3 当前位置 | L4 缓存 | TF |
|------|----|---------|-------------|---------|----|
| 09:00:00 | 空 | 空 | 未知 | 全部从盘加载 | base_link→? |
| 09:00:03.1 | 1 帧 | 空 | 未知 | 已加载 | 仍未对齐 |
| 09:00:03.5 | 多帧 | 开始融合 | lobby_3F | — | **map→zed2i_init 发布✓** |
---
## 8.5 T2:日间巡逻(持续 ~ 8 小时)
### 高频循环(30 Hz 主循环)
```
每帧 33.3 ms:
ZED grab → FrameProducer.append → 局部避障 → 30Hz 控制循环
```
### 中频循环(5 Hz TSDF)
```
每 200 ms:
取一个关键帧 → TSDFWorker.integrate
- 检查 prior_mask: 卫生间镜面区被跳过
- 检查 prior_weight: 走廊墙面 weight=0.1(轻微校准)
- 走廊地面新发现的"水迹"区域:正常融合,weight=1.0
```
### 低频循环(2 Hz 检测)
```
每 500 ms:
YOLO-World on 当前 RGB
→ 检出: bed_room_303, lamp_room_303, person, slipper
Person → 隐私过滤,丢弃这帧的语义写入(只保留几何)
bed_303 → 命中 LTM,更新 last_seen + EMA pose(微调)
lamp_303 → 命中 LTM,OK
slipper → 未在 LTM,propose_new → DeltaEvent(object_added,
payload=...),写 delta/pending.jsonl
```
### 异常事件(11:34)
```
机器人巡逻到 305:
- TSDF 在沙发区域显示"空"
- LTM mesh 显示"有沙发"
- ChangeDetector 1 Hz 跑:
diff > 5 cm → 聚类 → DeltaEvent(
event_type="object_removed",
target_uid="sofa_305",
evidence=[kf_305_1134_01, kf_305_1134_07])
- 写入 delta/pending.jsonl
但机器人 *不立刻*认为沙发没了:
- LTM 中 sofa_305 仍在
- 后续路径规划仍把它当障碍(保守)
- 等下次累计观测足够 + 充电时巩固才真删
```
### Anchor 校正(11:42)
```
机器人路过 304 床前:
- YOLO 检到 'bed' (high conf)
- 与 LTM bed_304 关联成功
- 在线触发 fine_register_anchor:
fitness=0.88 → 更新 T_zed→map
drift 估计归零
- 自此重新校准过;与上次校准间隔 38 分钟(< 1 h 健康)
```
### 任务级中断(13:00)
```
语音:"去 306 把客人遗忘的伞拿到前台"
LLM Agent 查 PRISM API:
find("伞", room="room_306")
→ L4 检索: umbrella_xxx (source=zed2i, conf=0.5,
last_seen=今早 10:21, parent=nightstand_306)
→ L3 路径: cur(hallway) → 306
→ L2 度量路径
→ 执行
```
---
## 8.6 T3:完整任务剧本——"取遥控器"
### 13:00:00 用户输入
```
客人在 308 房间说:"请帮我去 308 桌上拿遥控器"
(机器人当前位于 hallway 走廊中段)
```
### 13:00:01 LLM Agent 查询
```python
# Agent 不直接访问数据库;用 PRISM API
api = SpatialMemoryAPI("robot_memory/ltm/")
# 1) find 物品
result = api.find("remote control", filters={"parent_room": "room_308"})
# → [SpatialNode(uid='remote_xx33', label='remote_control',
# parent_uid='tv_stand_308', confidence=0.6,
# last_seen=2026-05-16T08:14:22)]
# 2) describe(给 LLM 看的自然语言)
print(api.describe(result[0].uid))
# "A black remote_control on tv_stand_308 in room_308 (Bedroom),
# last seen 4h 45min ago, confidence 0.6."
# 3) 检查最近 delta(是否被搬过)
recent = api.changes_since(time.time() - 3*3600)
# 关于这个遥控器的 delta? → 没有
# OK,假定还在
# 4) 路径规划
path_rooms = api.path_rooms(src="hallway_3F", dst="room_308")
# → ["hallway_3F", "room_308"]
metric_path = api.l2.plan(start=cur_pose, goal=result[0].pose)
```
### 13:00:02 执行
```
13:00:02.300 开始驱动,沿走廊向东
13:00:14.200 到达 308 门前
13:00:14.300 ChangeDetector 注意到 308 的门 LTM 标 closed 但实际开着
→ 写 delta(object_state_change, door_308)
13:00:14.500 进入 308
13:00:16.800 到 tv_stand_308 前 0.5 m
13:00:17.000 ZED 视野中检出 remote_xx33 ✓(YOLO conf=0.78)
位置与 LTM 偏 12 cm(在桌面被人挪过 12 cm)
EMA 更新 pose,不写 delta(< 20 cm 阈值)
13:00:18.000 机械臂伸出抓取
13:00:20.000 抓握成功,撤回
13:00:25.000 返回走廊
13:00:40.000 抵达前台,交接
```
**任务耗时 38 秒;查询 PRISM 总耗时 < 50 ms。**
---
## 8.7 T4:充电时记忆巩固(D 22:00)
### 触发
```
21:55:00 机器人电量 < 25%
21:55:05 返回充电桩(导航 ~ 8 min)
22:03:00 上桩,开始充电
22:13:00 静止 > 10 min,触发 prism consolidate --mode=full
```
### 巩固内容(当天积累)
```
pending.jsonl 当天总计 1234 条事件:
├── object_added (slippers, towels, ...) 413
├── object_moved (人挪过的小物) 382
├── object_removed 91
├── geometry_changed (走廊积水/物件堆放) 38
└── 重复信号 310
```
### Step 1: 筛选
```
观察累积 > 5 + 时间跨度 > 5 min + 多视点 > 2:
→ 162 条通过 confirm
→ 798 条 reject(< 5 min 的短暂物)
→ 274 条 keep(继续等待第二天)
```
### Step 2-3: 应用
```
其中:
- sofa_305 的 object_removed: 累积 47 次观测,跨越 6 小时
→ 通过 ✓,标记 sofa_305 state=removed,confidence ×= 0.3
- 12 个新增的 small_item(拖鞋、毛巾、水瓶)→ 加入 L4
- 41 个家具位置微调
```
### Step 4: 锚点 / 索引刷新
```
21 → 20 个 anchor(sofa_305 被淘汰)
受影响的 12 个新节点:渲染图像 + CLIP → 入 Faiss 索引
room_305 的房间 CLIP 重算(因为 sofa 不再)
```
### Step 5: 增量重训
```
受影响房间:room_305
3DGS warmstart from outputs/room_305/last.ckpt
3000 iter (~ 4 min on Orin AGX)
→ ply 替换 ltm/dense/3dgs/room_305.ply
TSDF 在 sofa_305 bbox 内 reset → 用今日 keyframes 重融合
```
### Step 6: 验证 + 切换
```
sanity_relocalize on 10 历史关键帧:
10/10 成功,RMSE 4.2 cm ✓
validate(new_mem):
0 errors ✓
snapshot: robot_memory/snapshots/20260516_2230.tar.zst (3.4 GB)
原子切换:ltm.staging → ltm;旧 ltm → ltm.prev(next day 删除)
22:34:00 consolidate 完成,总用时 31 min
22:34:01 机器人继续充电
```
### 第二天早晨
```
07:00:00 机器人启动,加载新 LTM
07:00:03 重定位(在充电桩,看天花板灯)→ Top-1 = hallway_3F ✓
07:00:04 IDLE 等待任务
```
---
## 8.8 T5:月度深度巩固(D+30 凌晨)
```
01:00:00 定时任务触发 prism consolidate --mode=deep
01:00:30 完整巩固 + 全场景 3DGS 重训(每房间 5000 iter)
03:45:00 全部完成 (8 房 × ~ 20 min)
03:46:00 自检:sanity_relocalize 20 张历史帧 → 19/20 通过 ✓
```
---
## 8.9 T6:装修后部分重扫(D+90)
```
酒店在 D+85 改造了 307 房间(新家具)
D+90: 运维带 iPhone 重扫 307 + 走廊端
ingest 时指定 --only-rooms room_307:
- 仅替换 LTM 中 room_307 相关的 nodes/edges
- 其他房间保持不变
- 重新生成 room_307 的 anchor + CLIP
- 重训 room_307 的 3DGS
ltm_version 从 v15 → v16
```
---
## 8.10 全生命周期 KPI(连续运行 90 天后回看)
```yaml
重定位:
冷启动成功率: 98.4% (1230/1250 次)
平均冷启动时长: 670 ms
绑架恢复成功率: 93% (用 ArUco 兜底后 100%)
记忆维护:
pending 平均长度: ~ 800 条/日
每日 confirmed: ~ 150 条
reject 率: ~ 64%(健康,说明门槛起作用)
错误巩固撤销次数: 2 次(手工回滚)
任务表现:
"取物"任务成功率: 94% (n=412)
错误归因:
- 物品已被移走 (delta 未及时巩固): 4%
- 抓取失败: 2%
- 重定位失败: < 1%
资源占用 (Jetson Orin AGX):
CPU 平均: 37%
GPU 平均: 52%
内存: 12.3 GB / 64 GB
磁盘增长: + 0.2 GB / 月(snapshots)
```
---
## 8.11 完整状态图
```mermaid
stateDiagram-v2
[*] --> BOOTING: power
BOOTING --> IDLE: relocalize ok
IDLE --> EXECUTING_TASK: task assigned
EXECUTING_TASK --> IDLE: done
IDLE --> RELOCALIZING: relocalize lost
EXECUTING_TASK --> RELOCALIZING: relocalize lost
RELOCALIZING --> IDLE: recovered
RELOCALIZING --> FALLBACK_HUMAN: failed > N
FALLBACK_HUMAN --> IDLE: human help
IDLE --> CONSOLIDATING: charging + idle > 10min
CONSOLIDATING --> IDLE: done
note right of IDLE
巡逻或待命
end note
note right of CONSOLIDATING
Background (并行):
• FrameProducer (30 Hz, always)
• TSDFWorker (5 Hz when moving)
• DetectorWorker (2 Hz when moving)
• ChangeDetector (1 Hz when stationary)
• HealthMonitor (0.2 Hz)
end note
```
---
## 8.12 本章小结
| 阶段 | 时间 | 主体 | PRISM 角色 |
|------|------|------|-----------|
| **T0** D-7 | 人工 | iPhone 扫描 | LTM 灌入 |
| **T1** D 9:00 | 机器人 | 冷启动 | 重定位握手 |
| **T2** D 全天 | 机器人 | 巡逻 | 在线感知 + delta 累积 |
| **T3** D 13:00 | 机器人 | 任务 | 查询四层记忆 + 路径 |
| **T4** D 22:00 | 机器人 | 充电 | 巩固 |
| **T5** D+30 | 机器人 | 深夜 | 深度巩固 |
| **T6** D+90 | 人工 | 重扫部分 | 增量 LTM 更新 |
读完本章你应能:
- ✅ 在脑中"播放"完整的 PRISM 一天
- ✅ 解释为什么 sofa_305 不会被"瞬间删除"
- ✅ 估算系统的资源占用
- ✅ 设计 PRISM 的状态机
下一章 [`09_roadmap.md`](09_roadmap.md) 给出 8 周内把这一切跑通的具体里程碑。
---
**章节版本**:v1.0
**估计阅读时间**:18 分钟
**关键收获**:把抽象架构变成"看得见的一天"