两个阶段:构建与运行
构建阶段。 构建阶段读取 Run、Project、Registry Index、Component Manifest、Scenario 和插件 Manifest。它完成字段验证、版本选择、资源解析、后端 variant 选择、实体实例化计划、插件绑定、服务授权、控制优先级与 provenance 计算,最终产生不可变 ExecutionPlan。
此阶段不需要启动重量级仿真器。把结构与组合错误前移有两个直接收益:CI 可以在无 GPU 环境中检查大多数问题,用户也不会在启动后端数分钟后才发现一个拼错的组件 URI。
运行阶段。 运行阶段只消费已经编译的 Plan。FastSimApplication 构造所选 Provider、稳定服务和插件实例,随后在 owner loop 中推进生命周期。Runtime 不应回头读取原始 YAML 或根据进程环境重新解释组件选择,否则 Plan 和真实行为就会分叉。
架构层次与责任
声明与解析层。 这一层回答“要运行什么”和“精确解析成什么”。Run 负责本次实例;Project 负责解析环境;Registry 负责组件发现;Manifest 负责某个版本的稳定语义和资源。Lock 则把已经批准的解析结果固定为复现边界。
关键产物不是一个合并后的无类型字典,而是带来源、稳定身份和摘要的 Plan。config explain 能够回答某个值为何如此,verify-lock 能确认部署输入仍与锁定事实一致。
Application Runtime。 Runtime 是唯一应用权威,负责:
- 生命周期与状态转换;
- run ID、generation、revision、tick 和时间边界;
- 服务创建、授权、撤销和关闭;
- 插件 hook 顺序与失败收敛;
- 控制准入、Operation 与取消;
- 运行事件、终态和输出发布。
Server、TUI、MCP 和用户 Python 程序观察同一 Application,不单独构造后端或维护影子状态。
稳定服务层。 公共服务按用途分组:
| 服务族 | 解决的问题 | 典型稳定边界 |
|---|---|---|
| Scene / Frame / Geometry | 世界里有什么、坐标如何转换、规划几何在哪里 | entity ID、frame ID、generation、revision |
| State / Observation / Camera | 某个提交边界上的世界与传感器数据 | tick、时间、通道和校准 |
| Control / Kinematics / Planning | 可控制什么、如何求解、怎样提交物理命令 | actor、group、axis、unit、Operation |
| Visualization / Event / Metric | 怎样发布可被多种界面消费的诊断信息 | typed primitive、timestamp、scope |
| Run lifecycle / Output | 如何观察终结并安全发布产物 | terminal state、receipt、trusted root |
服务公开值对象和受控操作,不公开 Provider 的整个对象图。这样插件可以独立安装与测试,后端适配器也能在不改变上层业务的前提下演进。
官方插件层。 官方插件是产品能力的一部分。不同插件承担不同角色:
- Mission 解释任务、目标和工作流;
- Model 接入模型请求、传输与输出映射;
- Teleop 接入设备输入并生成控制意图;
- Record、Replay 与 recording format 处理在线数据生产和受控重放;
- Server、TUI、MCP、Visualizer 与 Interactive Debug 提供人机或机器接口;
- Control/Kinematics SPI 与 Provider 包提供可替换算法服务。
插件只在 Run 选择后加载,并接收编译后的 bindings 与 access。安装包存在、entry point 可发现和当前 Run 启用,是三个不同事实。
UniRoboSim 与 Provider。 UniRoboSim 定义后端中立世界合同,Provider 把合同映射到具体引擎。Provider 拥有后端启动、实体构造、物理步进、原生资源和关闭细节;上层只依赖稳定实体、frame、joint、sensor 与 control 语义。
后端并不必然能力相同。某个 Provider 缺少流体、软体、相机或特定控制空间时,能力发现应准确反映差异,编译或调用应返回明确不可用,而不是静默伪造结果。
三条关键数据流
构造流。 Run → validate → resolve → bind → ExecutionPlan → Application。每一步缩小不确定性;到 Runtime 时,关键版本、资源、实例和权限已经确定。
状态与控制流。 Provider 在权威 tick 上提交世界状态;稳定服务发布带 generation/revision 的快照;插件或调用方读取目标并计算命令;Control 服务执行单位、时序、资源与 authority 检查;通过的 Chunk 在控制边界交给 Provider;Operation 报告终态。
数据与接口流。 状态、控制、事件和媒体通过受控通道进入 Record 或 Server。Record 使用 staging 与原子发布形成 FSR;Server 映射同一 Application 到 HTTP/实时协议。离线 Viewer/Exporter 只消费封口产物,不反向修改 Runtime。
生命周期如何贯穿各层
一次 reset 不是简单把机器人 pose 写回初值。它建立新 generation,并使旧控制、订阅、资源 lease 和长时间计算结果失效。Provider 重置世界,Runtime 重建当前服务状态,插件按合同清理并进入新一轮运行。
一次 close 也不是直接杀死进程。Runtime 先停止产生新工作,使 Operation 和订阅收敛,调用插件终结逻辑,完成或拒绝输出发布,关闭 Provider,最终进入幂等关闭状态。即使中间 hook 超时,清理仍需有界继续。
故障应该落在哪一层
| 现象 | 首先检查的边界 | 原因 |
|---|---|---|
| unknown field、kind mismatch | 配置编译 | 作者输入尚未形成有效 Plan |
| component not found、digest mismatch | Project/Registry/资源解析 | 身份或供应链事实不成立 |
| plugin not found、binding invalid | 插件发现与 Plan 绑定 | 所选能力无法被构造 |
| prepare/start 超时 | Runtime、插件 hook 或 Provider 生命周期 | Plan 有效,但运行依赖未就绪 |
| reset 后旧控制生效 | generation/Operation 边界 | 旧世代工作没有被正确撤销 |
| 仅某后端实体或物理错误 | Provider/UniRoboSim 映射 | 后端实现未满足稳定合同 |
| FSR 看似存在但无法读取 | Record/输出事务 | 发布与校验边界可能被破坏 |
这种定位方法避免在 Server 页面修 Provider 错误,也避免用插件里的私有逻辑绕过 Core 合同。
扩展平台时遵守的方向
新增领域工作流,优先实现插件;新增算法实现,优先实现相应 SPI Provider;新增后端,实现在 UniRoboSim 合同下;只有所有应用都需要共享的新稳定事实,才考虑扩展 Core 服务或配置。跨层接口变化需要先冻结数据形态、版本、生命周期、错误和兼容策略,再分别实现提供方与消费方。
下一步可阅读核心设计原则理解这些边界背后的取舍,或进入Run、ExecutionPlan 与 Lock理解平台如何在启动前形成精确计划。