194 lines
8.1 KiB
Markdown
194 lines
8.1 KiB
Markdown
# Earth Motion Capture Gesture Control Plan
|
||
|
||
> Update: Motion Agent process/device control, UE/Web shared command protocol, dual-camera redundant fusion, and the next 3D calibration route are now tracked in [Motion Agent v2 Control Protocol And 3D Calibration Roadmap](/home/ray/dev/linkong/planet/docs/plans/motion-agent-v2-control-protocol-plan.md). This document remains useful for the original provider split and gesture-control intent.
|
||
|
||
## Goal
|
||
|
||
为 Planet Earth 大屏和未来 3D 展示增加一套解耦的动作捕捉手势控制能力。实时输入分成两条路线:网页端可直接通过浏览器 `getUserMedia` 在本机识别;高级设备可继续使用本机 Motion Capture Edge Agent。两条路线都只输出轻量语义事件,客户端负责把“手势事件”映射到“具体交互函数”。
|
||
|
||
首版面向两颗 Logitech C1000 RGB 摄像头,但必须保持单摄像头兼容。后续任何 USB 摄像头、手机摄像头、RTSP/HTTP/WebRTC 视频源都应通过输入适配器接入,而不是改 Earth 渲染端。
|
||
|
||
## Architecture
|
||
|
||
实时链路分两种 provider,但进入 Earth 后协议一致:
|
||
|
||
```text
|
||
Browser camera -> browser-local recognizer -> Motion Provider events -> Earth control functions
|
||
Camera(s)/RTSP/HTTP -> Local Motion Capture Agent -> local WebSocket -> Motion Provider events -> Earth control functions
|
||
```
|
||
|
||
关键原则:
|
||
|
||
- 实时控制不经过 SaaS 云端。
|
||
- 实时控制不复用现有新闻、RSS、聚合数据接口。
|
||
- 浏览器 provider 和 Agent provider 都不向云端上传视频帧,只输出低带宽语义事件。
|
||
- Web/3D 客户端只消费统一事件并执行映射,不把具体输入源写进 Earth 交互逻辑。
|
||
- 双摄首版用于冗余和稳定性,不承诺完整 3D 姿态重建。
|
||
|
||
## Motion Providers
|
||
|
||
Earth 使用统一 Motion Provider 抽象:
|
||
|
||
- `browser_camera`:默认 provider。使用 `getUserMedia` 获取摄像头,在浏览器本地加载 MediaPipe Tasks Vision,输出 `gesture` / `skeleton` / `status` 事件。适合 SaaS、WSL、Windows 浏览器、大屏演示和“不安装 app”的用户。
|
||
- `motion_agent`:连接本地 Agent WebSocket。适合双摄、USB index、RTSP/HTTP 视频源、边缘设备和客户端集成。
|
||
|
||
设置项保存在 `planet.earth.settings.v2.shared.motionProvider`。`?motionProvider=browser` 强制浏览器摄像头,`?motionProvider=agent` 或 `?motionAgent=ws://...` 强制 Motion Agent。
|
||
|
||
## Motion Capture Agent
|
||
|
||
Agent 是本地 Edge 服务,职责包括:
|
||
|
||
- 读取摄像头:默认 USB index,支持单摄、双摄和未来 URL 视频源。
|
||
- 运行识别:首版使用 OpenCV + MediaPipe;识别引擎藏在接口后,未来可替换为 ONNX、TensorRT、C++ 或 Rust worker。
|
||
- 输出事件:通过 WebSocket 推送 `gesture`、`status`、`heartbeat`。
|
||
- 控制节流:负责置信度阈值、防抖、冷却时间和连续手势限频。
|
||
- 健康状态:报告摄像头数量、当前模式、识别 FPS、最近手势和错误。
|
||
- 明确失败:缺少 CV 依赖、摄像头打不开、无可用输入时给出可读错误。
|
||
|
||
Python 不应成为性能瓶颈:重计算在 OpenCV/MediaPipe 原生代码中完成,Python 只做编排、状态机和事件推送。事件消息通常小于 1KB,频率不超过 20Hz。
|
||
|
||
## Event Protocol
|
||
|
||
本地默认地址:
|
||
|
||
```text
|
||
ws://127.0.0.1:8765/ws/gestures
|
||
```
|
||
|
||
事件类型:
|
||
|
||
- `gesture`
|
||
- `status`
|
||
- `heartbeat`
|
||
|
||
手势语义:
|
||
|
||
- `rotate_left`:左挥手,地球向左旋转。
|
||
- `rotate_right`:右挥手,地球向右旋转。
|
||
- `zoom_in`:双手张开,地球放大。
|
||
- `zoom_out`:双手合拢,地球缩小。
|
||
- `confirm`:握拳或确认动作,触发当前交互确认。
|
||
|
||
最小事件字段:
|
||
|
||
```json
|
||
{
|
||
"type": "gesture",
|
||
"gesture": "rotate_left",
|
||
"phase": "discrete",
|
||
"confidence": 0.92,
|
||
"intensity": 0.8,
|
||
"timestamp_ms": 1770000000000,
|
||
"seq": 42,
|
||
"source": "motion-agent",
|
||
"mode": "single",
|
||
"payload": {}
|
||
}
|
||
```
|
||
|
||
## Earth Client Integration
|
||
|
||
Earth 前端新增 motion-control adapter:
|
||
|
||
- 连接本地 Agent WebSocket。
|
||
- 处理断线、重连、心跳和状态。
|
||
- 过滤低置信度事件。
|
||
- 将手势映射到 Earth 控制函数。
|
||
- Agent 离线时不影响普通鼠标、触摸、巡航和图层交互。
|
||
|
||
Earth 端只暴露最小动作入口:
|
||
|
||
- `applyMotionRotate(direction, intensity)`
|
||
- `applyMotionZoom(direction, intensity)`
|
||
- `applyMotionConfirm()`
|
||
|
||
动作捕捉不直接操作 Three.js 内部对象,也不修改图层业务模块。
|
||
|
||
## SaaS Strategy
|
||
|
||
未来网页端做成 SaaS 后,默认实时手势链路仍在浏览器本地完成,不走云端 RPC。高级现场设备可选本地 Agent:
|
||
|
||
```text
|
||
Browser SaaS page -> getUserMedia -> browser-local recognizer
|
||
Browser SaaS page -> local secure bridge -> Local Motion Capture Agent (advanced)
|
||
Cloud SaaS -> config/auth/status only
|
||
```
|
||
|
||
原因:
|
||
|
||
- 云端 RPC 会增加网络 RTT 和抖动。
|
||
- 上传摄像头帧有隐私和带宽风险。
|
||
- 大屏交互需要稳定体感延迟,云端只适合做配置、授权、设备状态和审计。
|
||
|
||
浏览器摄像头要求 HTTPS 或 localhost。Agent 模式在本地部署可使用 `ws://127.0.0.1:8765`;生产 HTTPS SaaS 若要接 Agent,需要补 `wss://127.0.0.1` 或等价本地安全桥接,避免浏览器混合内容限制。
|
||
|
||
## Latency Budget
|
||
|
||
目标体感延迟:
|
||
|
||
- 摄像头采集:16-33ms。
|
||
- 识别:8-25ms。
|
||
- 状态机:小于 2ms。
|
||
- 本地 WebSocket:1-5ms。
|
||
- 浏览器渲染:约 16ms。
|
||
|
||
实验室目标:从动作被识别到 Earth 响应 p95 小于 50ms;摄像头到画面响应端到端小于 120ms。
|
||
|
||
## Implementation Milestones
|
||
|
||
1. 保存本计划并注册到 `docs/plans/README.md`。
|
||
2. 新增独立 motion agent 包,提供 CLI、配置、摄像头输入抽象、事件模型和 WebSocket server。
|
||
3. 新增手势状态机,支持阈值、防抖、冷却和限频。
|
||
4. 新增 Earth motion-control provider manager,默认接浏览器摄像头 provider,可切换到 Motion Agent provider。
|
||
5. 增加 Agent 单元测试、协议测试和前端 adapter 静态验证。
|
||
6. 更新中英文用户手册和 Earth 前端开发上下文。
|
||
|
||
## Debug Mode Addition
|
||
|
||
**当前状态**:Browser Camera provider 会在调试面板中显示本地 `<video>` 预览并叠加骨架;`只显示骨骼` 可关闭视频底图。Motion Agent provider 仍只发送 `skeleton` 事件,不传原始摄像头帧。
|
||
|
||
Earth 设置中增加“动捕调试模式” switch,并增加“动捕输入源”选择。开启后,Earth 会启动当前 provider 并显示独立 HUD 调试面板。Browser Camera 模式下调试面板可以显示本机浏览器视频预览;Motion Agent 模式下只画归一化骨架点和关节连线,不传原始摄像头画面。
|
||
|
||
Motion Agent 增加 `skeleton` 事件:
|
||
|
||
```json
|
||
{
|
||
"type": "skeleton",
|
||
"camera_id": "usb:0",
|
||
"matched_gesture": "rotate_left",
|
||
"confidence": 0.91,
|
||
"joints": [{ "id": "left_wrist", "x": 0.42, "y": 0.61, "confidence": 0.98 }],
|
||
"bones": [["left_shoulder", "left_elbow"]]
|
||
}
|
||
```
|
||
|
||
调试颜色约定:
|
||
|
||
- 未匹配动作:红色骨架。
|
||
- 已匹配动作:绿色骨架,并显示匹配到的动作名。
|
||
|
||
权限先预留 `data-gatekeeper-permission="earth.motion_debug"` 标记,后续由 Gatekeeper 决定 switch 是否可见/可用。
|
||
|
||
## Test Plan
|
||
|
||
- Agent 单元测试:
|
||
- 事件模型可序列化。
|
||
- 低置信度手势被忽略。
|
||
- 冷却期内重复手势被忽略。
|
||
- 冷却后新手势可再次输出。
|
||
- 无摄像头/缺依赖时错误可读。
|
||
- Agent 协议测试:
|
||
- `gesture`、`status`、`heartbeat` 字段稳定。
|
||
- WebSocket 广播只发送语义事件。
|
||
- Earth 前端验证:
|
||
- motion-control provider manager 能消费浏览器 provider 和 Agent provider 的 mock 消息。
|
||
- browser provider 在 mock `getUserMedia` 成功时进入 active 状态。
|
||
- browser provider 在权限拒绝、无摄像头或非安全上下文时给出可读错误。
|
||
- `skeleton` 事件能触发 `earth:motion-debug-frame`。
|
||
- Agent 离线时不抛异常。
|
||
- `rotate_left/right`、`zoom_in/out`、`confirm` 映射到 Earth 动作函数。
|
||
- 文档验证:
|
||
- 计划文档存在。
|
||
- `docs/plans/README.md` 有入口。
|
||
- 中英文使用说明不互相矛盾。
|