安装、选择与授权是三件事

  1. 安装包通过静态 Manifest 和 Python entry point 声明自己。
  2. Run 在 plugins 中选择一个具体实例。
  3. 编译器根据 Manifest、Run access 与部署上限计算最终 binding。

只有三步都成立,Plugin Host 才会创建实例并授予服务。已安装但未选择的插件不会被导入或启动。

插件角色与公共服务

角色 典型插件 核心职责
control_producer Rule-based、Model、Teleop、Replay、Agent 读取授权状态并提交控制 Chunk
data_consumer Record、评价、监控 消费事件、观测和输出
extension 几何、运动学或项目能力 在稳定服务边界上增加功能
interface Server、TUI、Debug、MCP 把同一 Application 能力呈现给用户或外部系统

一个插件可有多个角色,但权限仍按服务逐项计算。

范围化服务。 常见服务包括 scenario.read、scene、frames、planning geometry、kinematics、observations、control.targets、control、visualization、artifact/output 与 run info。服务对象绑定到插件实例和 generation,并可在生命周期结束时撤销。

公共服务不暴露后端对象。 若插件直接持有 Isaac Lab 或 MuJoCo 对象,它就能绕过 pause、reset、记录、权限与控制仲裁,也无法跨后端工作。FastSim 只允许后端特有行为通过明确的 Provider 能力或独立扩展合同出现。

插件也不是页面开关。TUI、Server 等接口插件仍是完整运行时参与者,需要声明生命周期和访问范围。独立 Web Client 通过 Server 公共协议工作,不直接导入仿真 SDK。

现有软件包见官方插件目录。

从发行包到运行实例

FastSim 插件从发行包发现、编译绑定到运行时 scoped service 的能力流程
FastSim 插件从发行包发现、编译绑定到运行时 scoped service 的能力流程放大查看

插件形成有效运行实例要经过四个条件:发行包已安装;Manifest entry point 可读取;Run 选择了兼容 Plugin ID;Compiler 为该实例建立合法 bindings/access。只有这些条件成立,Runtime 才按 Plan 导入 factory、核对 descriptor 并创建实例。

这种顺序保证未选择插件不被导入,也避免“安装一个包就自动执行代码”。plugins list 和 plugins inspect 可以只读取发行元数据;需要定位 factory 导入与构造问题时才使用 diagnose。

Manifest、Factory 与 Instance。 Manifest 描述可编译的身份、角色、兼容版本、所需 Scenario 区域、服务和能力;Factory 是安装包公开的构造入口;Instance 是某份 Run 中带配置、bindings、access 与生命周期的具体对象。

同一个插件类型可以在一个 Run 中出现多个实例,只要其合同允许且实例 ID、绑定与资源 authority 不冲突。领域默认值可以属于插件配置,但具体机器人或控制 group 不应硬编码在 Manifest 中。

Binding 与 Access。 Binding 把插件使用的角色名连接到 Scenario 实体,例如 arm 绑定到 robots.g2.left_arm。Access 再限制能读取或操作的服务范围。两者解决不同问题:绑定说明“指谁”,授权说明“能做什么”。

默认行为仍受 Manifest 和选中实体范围约束;生产部署需要隔离或最小权限时显式收窄。插件请求未获授权服务应得到明确拒绝,不能通过另一服务绕行或直接抓取 Application 内部对象。

生命周期与多控制源协作

scoped service 与插件实例及当前 generation 绑定。prepare 时服务就绪后才能交给插件;reset、stop 或 close 会撤销旧 grant。插件不得把服务对象放进全局单例并跨 Application 复用,也不得在 close 后继续后台提交。

插件创建的 worker、订阅和 Operation 必须在 stop/close 中有界收敛。重复 close 应安全;异常清理也必须运行。官方插件一致性测试应覆盖 hook 顺序、超时、任务清理、服务撤销和 wheel 安装发现。

多个控制源通过公共仲裁共存。 Mission、Model、Teleop、Replay 或远程客户端可能同时产生控制。Run 必须给出完整 control.precedence,Compiler 检查覆盖同一资源的来源;Runtime 在公共 Control 边界执行准入和抢占。

插件之间不应互相调用私有方法决定谁覆盖谁,也不应把优先级实现成“最后一个线程写 joint target”。公共仲裁让选择可解释、可记录,并能在 reset 或来源断开时正确释放 authority。

开发新插件的最小闭环

  1. 明确角色、领域语义和所需公共服务;
  2. 设计 Manifest、Plugin ID、配置 schema 与兼容范围;
  3. 提供 Manifest 和 Factory 两组安装 entry point;
  4. 只通过 PluginRuntimeContext 使用授权服务;
  5. 实现 prepare/start/stop/close 与异常清理;
  6. 构建 wheel,在干净环境验证发现与一致性;
  7. 只对真实验证过的 Provider、设备或算法能力作支持声明。

官方开发流程见官方插件目录中的仓库文档。理解插件产生的控制如何进入 Runtime,请继续阅读状态、控制与 Operation。