chore: initial commit — import worldmodel workspace (plans/, research/)
This commit is contained in:
@@ -0,0 +1,483 @@
|
||||
# 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点 : 机器人首次开机<br/>重定位握手
|
||||
T2 全天 : 巡逻/任务<br/>delta 累积
|
||||
T3 14点30 : 取遥控器任务
|
||||
T4 22点 : 充电桩<br/>记忆巩固
|
||||
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 分钟
|
||||
**关键收获**:把抽象架构变成"看得见的一天"
|
||||
Reference in New Issue
Block a user