## Owner summary 方向已确认:UniLab 采用 **社区兼容 API + UniLab NumPy runtime**。实现不重新设计 manager,而以 mjlab 1.6.0 固定 commit 的 `src/mjlab/managers/` 为迁移源,尽量保留目录、命名、配置和生命周期,只做 Torch→NumPy、`SimBackend`/Hydra/`NpEnvState` 适配及不适用代码删除。允许彻底重构和大量清理,最终不能长期保留新旧双实现;新增 UniLab glue 必须少而薄。能力缺口一律 fail-closed,在 init/materialization 等最近边界直接报错,不 warning + skip、不 no-op、不回退旧路径。source-aligned port 与集中删除可放宽默认 child 预算,但新的公共 contract、lifecycle、backend capability、IPC 仍必须单独确认。 > 只做 **社区 Manager-Based task API 在 UniLab NumPy runtime 上的直接迁移与收口**;不做 **UniLab 自有 manager 方言、第二套 env/runner/IPC、Omniverse/Isaac 依赖、Torch manager 热路径或永久兼容层**。 ## 已确认决策 1. **产品方案:** 采用“社区兼容 API + UniLab NumPy runtime”,不再比较 B/C 方案。 2. **迁移方法:** 以 mjlab `1.6.0`、commit [`0fb8a681`](https://github.com/mujocolab/mjlab/commit/0fb8a681136be94ffc636a3dd423cabb97d91f10) 的 `src/mjlab/managers/` 作为 source of truth,先迁移,再最小适配;不重新发明等价接口。 3. **代码形态:** 优先保留上游 12 个 manager 模块的职责与公共表面;NumPy support primitive 和 UniLab facade 只在没有现有 owner 可复用时新增。 4. **重构策略:** 接受破坏内部私有实现的彻底重构;task 迁移完成后,大量删除旧 dispatch、重复 reward/config、临时 bridge 和 dead code是预期结果。 5. **错误策略:** 任何配置请求但 backend/manager 尚不具备的能力直接 raise;不静默降级、不自动跳过、不猜默认值、不 fallback 到旧 env 实现。 6. **外部不变量:** 保留 NumPy 热路径、`NpEnvState`、`SimBackend` 多后端隔离、Hydra owner YAML、registry、sim2sim、现有算法和 IPC 数据面。 7. **授权边界:** 本次确认 roadmap 方向与 scope 例外,不等于授权整单实施;开始开发仍只授权 maintainer 明确确认的当前 child issue。 ## 一句话问题 UniLab 还没有采用机器人学习社区已经熟悉的 Manager-Based task 接口;用户迁移 Isaac Lab/mjlab 风格 task 时必须把 term、配置和生命周期重写成各 env 的私有单体方法,而遇到 backend 缺口时还可能得到 warning/skip 而不是明确失败。 ## 为什么现在做 ### 仓库内证据 - `src/unilab/base/np_env.py` 的 `NpEnv.step()` 统一拥有 action、physics、state update、done 和 autoreset,但 `src/unilab/envs/locomotion/go2/joystick.py` 等 task 仍各自维护 `_init_reward_functions()`、`_compute_obs()`、`_compute_reward()` 与 termination 组装。 - `src/unilab/envs/locomotion/common/rewards.py` 已有 NumPy reward 函数和 dispatch,但 term 名、参数、shape、reset hook、日志与 lifecycle 不是公共 manager contract。 - Hydra owner YAML、registry、`NpEnvState`、backend capability 和 IPC observation contract 已有明确 owner 与测试;它们是需要保留的 UniLab 优势,不是 MBA 重写对象。 - 当前 `DomainRandomizationManager` 对部分 unsupported reset term 存在过滤并 warning 的行为。新的 Manager-Based API 不得继承这种静默能力降级;若要统一改变旧 task 行为,必须作为 DR contract child 明确实施。 - #627 已记录 mjlab manager-based reward/event/contact term 比当前 task contract 更丰富,但 raycaster issue 不负责重写 manager API。 ### 论文带来的产品目标 [`arXiv:2601.22074v2`](https://arxiv.org/abs/2601.22074) 将 mjlab 定位为 Isaac Lab Manager-Based API 的轻量实现:两者 MDP 结构相同,多数 task 迁移是机械改写,主要差异在 config 容器与 scene/simulator。论文将收益落在减少多 task/robot 重复代码、提高测试和调试能力、加快 reward/curriculum/policy 迭代,同时明确承认 manager abstraction 有 overhead。 因此本 roadmap 的目标不是“代码里出现 Manager 类”,而是: - 用户复用社区已有 manager/term 心智模型,不学习 UniLab-only dialect; - mjlab manager 代码的主要 diff 可被约束为 import、Torch→NumPy 与正式的 scene/backend adapter; - UniLab 用 NumPy、多 backend、Hydra 与 IPC 保留自己的优势; - manager overhead、额外 allocation 和初始化成本必须被测量,不能靠架构口号掩盖。 Isaac Lab 用来定义共同接口来源,mjlab `0fb8a681` 提供可直接迁移、逐项测试的具体行为。上游后续变化不会自动扩大本 roadmap。 ## 迁移原则:source-aligned port,不重新实现 迁移源固定为 `/home/user/ws/simulator/mjlab/src/mjlab/managers` 对应 commit 的 12 个 Python 文件,约 2,920 行。mjlab 与 UniLab 均采用 Apache-2.0;实施 PR 必须记录 upstream commit、来源路径和 license/provenance,并保留适用 notice。 推荐工作顺序: 1. 按上游模块布局迁移 `manager_base`、action/observation/reward/termination/event/command/curriculum/metrics/recorder manager、`scene_entity_config` 与 package exports。 2. 先做可机械审查的 import rename、类型替换和 Torch→NumPy 运算转换;避免同时改公开语义。 3. 删除 `.device/.to()/.cpu()`、Torch-only storage、Warp/MuJoCo-Warp model mutation、上游 viewer glue 等不属于 UniLab contract 的实现。 4. manager 对 env/scene/sim 的访问收敛到少量 typed context/facade;这些 facade 只能调用正式 `SimBackend`,不能复制一套 backend abstraction。 5. 适配 upstream tests 为 NumPy,并为每项 intentional difference 增加 focused test;不只依赖 pilot smoke。 6. 每个 PR 报告四类规模:**原样/source-derived 行、机械 NumPy 转换行、UniLab-specific 新增行、删除行**。目标是最小化第三类,而不是追求小 diff 数字。 7. production task 迁移后直接删除被替代的旧代码;只有仍有未迁移 consumer 的 bridge 可以暂留,并必须声明最后使用者和删除 child。 禁止采用以下捷径: - 另写一套“更适合 UniLab”的同义 managers,再包一层兼容 facade; - 为了少改上游代码而把 Torch 引入 manager 热路径; - 把 scene/backend/task 规则塞进 manager base 或 scripts; - 对缺失方法使用 `getattr/hasattr`、try/except warning、返回零数组或旧路径 fallback; - 长期 vendor 两套 source tree 或维护 upstream mirror tooling。 ## 产品目标:具体减少哪些 friction | Friction | 完成后用户体验 | 不能牺牲的 UniLab 优势 | | --- | --- | --- | | 学习 | 使用 observation/action/reward/termination/event/command/curriculum 的社区概念、term cfg 与 manager 字典。 | 名称兼容只指向一套实现。 | | Task authoring | task 由 function/class term 和 typed config instance 组成;stateful term 在 init 缓存 selector,并可局部 reset。 | 热路径只用 NumPy array/缓存 ID。 | | Porting | mjlab 纯 manager 代码主要改 import 与 Torch→NumPy;Isaac Lab task 再做 config-container 与 scene/backend 的机械转换。 | 不承诺 USD/Omniverse/MuJoCo-Warp implementation parity。 | | Config | callable 在 task-owned Python config/factory 声明;Hydra owner YAML 按 term 名覆盖可序列化字段。 | 保留现有 CLI、owner YAML、registry、算法 YAML 和 backend identity。 | | Debugging | shape/NaN/Inf 或 capability error 指向 manager、term、backend 和请求能力。 | 诊断不扩散到 runner/learner/IPC。 | | Installation | manager core 随基础安装可用,不要求 Isaac Lab、Omniverse、Warp 或新重量级 runtime。 | 继续使用 `uv run` 与 optional backend 依赖。 | | Runtime | config/class/selector/buffer 只在冷路径解析/分配;step/reset 使用预分配 NumPy buffer。 | 保留 CPU physics → IPC → accelerator learner。 | | Ecosystem | API、示例与迁移表对应社区资料;添加 task 不修改 scripts/IPC。 | support claim 仍基于 registry/config/test/benchmark。 | ## 社区兼容 contract ### P0:共同 task API - `ManagerBasedRLEnv` / config、`ManagerBase`、`ManagerTermBase`、`func + params` term config 心智模型。 - Observation、Action、Reward、Termination、Event、Command、Curriculum 七类共同 manager;dict 插入顺序、`None` 显式禁用、function/class term、局部 `reset(env_ids)`、shape/finite fail-fast 和 per-term diagnostics。 - term 可见的稳定 env context:`num_envs`、physics/control dt、episode counters、各 manager 属性和正式 scene/entity NumPy view。 - `SceneEntityCfg` name/regex → cached ID 语义是 P0;owner boundary 必须与 #586 对齐。 - Isaac Lab/mjlab 仅拼写不同的高价值名称可以提供无行为分叉 alias;canonical spelling/alias 由首个 ADR 固定。 ### P1:低摩擦扩展 - mjlab Metrics/Recorder manager,以及 observation delay/history/NaN policy 等实际使用扩展。 - 一组由 UniLab 已注册 task 和 migration fixture 证明需要的 common built-in terms/actions;优先沿用社区名称。 - manager-native task 教程、Isaac Lab/mjlab migration matrix、Hydra override 示例和 per-term debug 输出。 - 新 task 只注册 env/config 和 owner YAML,不修改训练脚本、runner 或 IPC。 ### Intentional differences | 边界 | UniLab 目标 | | --- | --- | | 数值 | manager-facing buffer、term return、env ids、entity view 全部为 `np.ndarray`/`slice`;无 Torch device API。 | | Env return | 保留 `NpEnvState`、`reset() -> (obs_dict, info_dict)`、final observation、`obs_groups_spec`。 | | Observation | manager 内接受 community policy/actor/critic group;env owner 显式映射到 `obs` + optional `critic`,IPC 不推断。 | | Scene/entity | 提供 term 所需 NumPy view 和 selector,不复制 scene composer,不暴露 backend 私有对象。 | | Config | 采用 plain config instances + typed dictionaries;Hydra owner YAML 覆盖字段,不引入第二套 CLI/config runtime。 | | Event/DR | 对齐调度语义;实际 mutation 必须通过 DR payload 与 backend capability。 | | Training | managers 对 IPC/learner/runner/scripts 零依赖;现有 adapter 消费 `NpEnvState`。 | | Performance | 内部可预解析、预分配和批量 NumPy 优化,但不得要求用户改 community-facing term API。 | 不声称任意外部 task 可以零改动运行。只有 compatibility fixture/迁移 task 覆盖的表面才能标为 Compatible;其余为 Adapted 或 Unsupported + error。 ## Fail-closed 能力规则 - 配置为空或 term 明确设为 `None` 属于用户显式选择,可使用 upstream Null manager/no-op 语义。 - **配置请求了能力但实现缺失**不属于 optional:在 manager 构造、config validate、scene materialization 或 backend capability resolution 的最近边界直接 raise。 - error 至少包含 manager 类型、term 名、请求能力与 backend;应优先使用已有 contract error,确需公共 exception 时单独在 ADR 中确认。 - 不允许 warning 后跳过 term、返回全零/旧值、自动选择其他 backend、禁用 feature,或 fallback 到旧单体 env。 - backend 不对等时允许明确 `NotImplementedError`/compatibility error;不要求伪造 feature parity。 - 热路径不做能力探测。所有可预知缺口在冷路径失败;只有真正运行时才出现的非法 term 输出在调用点 fail-fast。 - upstream Null manager、base hook 的合法 no-op 与“能力缺口静默回退”必须在 compatibility matrix 中区分并测试。 ## In scope - 直接迁移 pinned mjlab managers source tree 并完成 NumPy 改写、依赖收缩和 provenance 记录。 - 建立 Isaac Lab ↔ mjlab 1.6.0 ↔ UniLab 的 P0/P1 API、命名、term context、lifecycle、error 和 intentional-difference matrix/ADR。 - 提供最小 scene/entity NumPy facade 与 cold-path `SceneEntityCfg` selector,只调用 `SimBackend`。 - 在不破坏 `NpEnvState` 的前提下,将 managers 接入唯一 `NpEnv` lifecycle。 - 保留 Hydra owner YAML,同时允许按 manager/term 名覆盖 config;禁止 scripts 解释 task 业务规则。 - 以 `Go2JoystickFlat` 为首个纵向 pilot,保持 registry 名、observation/action 维度和当前注册 backend。 - 根据迁移 task 证据补最小 built-in term/action 集,不预先搬运完整 catalog。 - 为 mjlab/Isaac Lab 各提供一个 migration fixture,量化机械改写以外差异。 - 接受 task-family 迁移后的大规模旧代码删除;最终消除新旧双实现和过渡 shim。 ## Non-goals - 不读取、恢复或兼容 UniLab 历史 MBA 实现、分支、ABI 或专项入口。 - 不创建依赖外部安装的 `isaaclab`/`mjlab` namespace shim;UniLab 内 alias 只能指向同一实现。 - 不引入 Omniverse、USD、Warp 或 Torch manager runtime,不复制完整 Scene/Simulation/Viewer/Terrain 系统。 - 不无证据迁移全部 built-in observation/reward/event/DR/action catalog。 - 不新增或绕开 runner lifecycle、collector、replay、shared-memory、权重同步、learner 或 checkpoint protocol。 - 不通过 `training.sim_backend` 单独切 backend,不把 config/task 规则写入 scripts。 - 不把文件/LOC 放宽解释为可将公共 contract、production integration、task migration 和 cleanup 混在一个 PR。 - 不自动新增常规 CI、support 等级、upstream sync bot 或长期 benchmark infrastructure。 - #627 raycaster scope 保持独立。 ## Child issue / PR 规模例外 本 roadmap 获得 maintainer 对默认 15 文件/800 行预算的显式放宽,但只适用于可审计的 source migration 和集中清理。所有 child 仍必须只有一个主要结果、一个 PR,并在开始前写明所属类别。 | 类别 | 建议上限 | 计数与约束 | | --- | --- | --- | | 普通行为 child | ≤25 个非删除文件;≤1,500 行 UniLab-specific 手写改动 | 只覆盖一个 manager/owner 结果;新公共 contract 仍单独确认。 | | Source-aligned manager port | ≤40 个非删除文件;≤5,000 行 source-derived/机械适配;≤800 行 UniLab-specific glue | 允许一次迁移完整 12-file manager package + adapted tests;不得接 production task/lifecycle。 | | Task migration + cleanup | ≤30 个非删除文件;≤1,500 行新增/改写 | 纯删除文件和删除 LOC 不设数值上限,但必须只删除已被本 child 替代且有回归证据的代码。 | | Public contract/backend/lifecycle/IPC | 不因本例外合并 | 每个仍需独立 issue、明确 owner、stop condition 和 maintainer 确认。IPC 默认不改。 | 所有 child/PR 必须分别报告 source-derived、机械转换、UniLab-specific glue、modified existing 和 deleted LOC/files。达到任一声明预算即暂停;不能临时把改动重新分类来规避。 ## 最近 3 个可执行 child issue ### Child 1 — 社区兼容与直接迁移 ADR(Small,先做) **主要结果:** 固定公共表面、迁移方式、provenance、错误策略和删除终态,不含 runtime 实现。 - 落点:ADR、env/config contract、compatibility matrix、最小 migration diff 示例。 - 固定 canonical names/aliases、P0/P1、term context、plain-instance config、NumPy 差异、fail-closed error 和四类 LOC 报告方法。 - 预计:5–10 文件,≤500 行,1 PR。 - 验收:maintainer 可逐项说明迁移自何处、只改什么、删什么、遇到缺口如何失败。 - Stop:#586 无法为 P0 entity view/selector 给出不泄漏 backend 的 owner boundary。 ### Child 2 — 直接迁移 mjlab managers 并转换为 NumPy(Source-aligned exception) **主要结果:** `src/unilab/managers/` 在不接 production env 的情况下,以 NumPy 通过 upstream-derived manager tests。 - 迁移 pinned 12-file package,保留模块职责/exports;记录 upstream provenance。 - 做 import rename、Torch→NumPy、buffer/RNG/finite 适配;删除 device/Warp/viewer-specific 实现。 - 只允许最小 fake env/scene context 与必需 NumPy support primitive;不改 `NpEnv.step()`、真实 backend、task、scripts 或 IPC。 - 预算:≤40 个非删除文件、≤5,000 行 source-derived/机械适配、≤800 行 UniLab-specific glue、1 PR。 - 验收:upstream-derived tests 覆盖所有迁移 manager;intentional diff 有 focused tests;manager package 无 Torch/IPC/runner/scripts import。 - Stop:需要新的 production lifecycle/backend public method,或 glue 超过预算,说明 adaptation seam 不够薄。 ### Child 3 — `SceneEntityCfg` + NumPy entity facade 的真实 owner 接入(普通/公共 contract) **主要结果:** manager term 可通过冷路径 selector 和稳定 NumPy view 访问真实 UniLab scene/backend,缺口 fail-closed;不接 production task。 - 与 #586 形成同一明确决策,落点优先复用 `src/unilab/base/scene.py`、`SimBackend` 名称/ID/state contract,不创建第二套 scene composer。 - selector 在 init/materialization 解析;term 热路径只持有缓存 ID/view。 - 每个 backend 对请求能力显式 validate;不支持直接 error,不 warning/skip/fallback。 - 预算:≤25 个非删除文件、≤1,500 行 UniLab-specific 改动、1 PR;任何新增 `SimBackend` 方法必须先单独确认,不能塞入本 child。 - 验收:MuJoCo/Motrix/Drake fake/conformance tests 证明 selector 与 capability error;无 XML/asset 热路径访问。 - Stop:需要完整 scene runtime、backend 私有对象或多套 entity implementation。 批准本 umbrella 本身不等于无限授权;maintainer 已于 2026-08-18 另行授权按“本地 gate → 自动合并 → 继续下一 child”连续执行既定 roadmap 内的常规 child。开发分支规则列出的高风险边界与 stop condition 仍需单独确认。 ## 后续方向(只记录启动条件) 1. 前三项通过后,单独接入 `NpEnv` 的唯一 ManagerBased lifecycle;不同时迁移 production task。 2. lifecycle fixture 通过后迁移 `Go2JoystickFlat` pilot,并对 MuJoCo/Motrix/Drake 当前注册事实逐一回归;任一 backend 缺口直接 error 或留在未支持矩阵,不静默关闭 feature。 3. Event/DR 接入时审计现有 warning+filter;若改变共享 DR contract,单独 child。 4. `per_substep` metrics/action 若需要 backend hook,作为新的 `SimBackend` contract 单独确认。 5. pilot correctness、Hydra compose、migration diff 和同机 A/B throughput 经接受后,按 task family 迁移并同步删除旧代码。 6. 所有 consumer 迁移后,集中删除旧单体 dispatch、重复 config/reward helper 和 bridge;删除规模可大,但每个 cleanup child 只收一个 owner 结果。 ## Owner、预计规模与永久维护成本 - **Umbrella owner:** Env + Config maintainer;暂不指派。 - **参与 owner:** Backend maintainer 负责 entity/substep capability;Training/IPC 只做回归确认,不拥有 manager 规则。 - **上游迁移基线:** 12 个 manager source 文件、约 2,920 行,加 adapted tests;这些与 UniLab-specific glue 分开报告。 - **Core + entity facade + pilot:** 预计 8–12 PR;UniLab-specific 新增目标控制在约 3k–5k 行,source-derived/机械转换另计。 - **全量 task migration/cleanup:** 超过 100 个 touched files、约 15–25 PR;允许大量删除,期望最终净代码量显著低于“新 managers + 全部旧实现并存”。 - **永久维护:** compatibility matrix、单一 manager API/测试、NumPy buffer/RNG/finite 语义、Hydra term bridge、entity facade、跨 backend capability/conformance。 - **必须删除:** 旧 `reward_config`/单体 env bridge、fallback、duplicate manager helper;只有 maintainer 明确接受的 consumer 才能延长生命周期。 - **不新增:** 第二套 runner/IPC/learner、Isaac/Omniverse runtime、Torch manager path、upstream mirror/sync infrastructure。 ## Umbrella acceptance criteria - ADR 记录已确认方案、pinned upstream source/provenance、Apache-2.0 处理与直接迁移策略。 - `src/unilab/managers/` 的公共模块/类型/行为可追溯到 pinned mjlab source;每项偏离归类为 NumPy、UniLab contract、explicit unsupported 或删除。 - P0 七类 manager、term cfg/context 与 `SceneEntityCfg` 有实现或 construction-time error;Metrics/Recorder 等 P1 按迁移代码与 evidence 提供。 - manager-facing buffer、term return、env ids、entity view 全部为 NumPy;manager/env 热路径无 Torch import。 - mjlab-style fixture 除 import 与 Torch→NumPy 外不重写 term 结构;Isaac-Lab-style fixture 的额外改动限于记录的 config-container 与 scene/backend adapter。 - 新用户仅通过 manager config、registry 和 Hydra owner YAML添加/运行 fixture,不修改 scripts/runner/IPC。 - 任一配置能力缺口都在最近边界 raise,error 包含 manager/term/capability/backend;测试禁止 warning+skip、zero fallback、旧 env fallback。 - `Go2JoystickFlat` pilot 保持 `NpEnvState`、reset/step/final observation、action/observation 维度、sim2sim 与现有 backend registration;不支持项显式失败。 - shape/NaN/Inf diagnostics 指向具体 manager/group/term;日志命名稳定。 - manager package/owner 对 IPC/learner/runner/scripts 零依赖,并有 repository-boundary test。 - callable、asset/model metadata、selector、buffer allocation 只在 cold path;热路径只用预分配 NumPy buffer、缓存 ID 和正式 backend contract。 - core 不新增重量级必选依赖;import/startup 不要求 Isaac Lab、mjlab、Omniverse 或 Warp。 - pilot 报告同 commit/config/hardware 的旧/新吞吐、初始化与主要 allocation。若 overhead 不可接受,优化或缩 scope,不静默改语义。 - task migration 后删除对应旧实现;umbrella 完成时不存在生产新旧双路径或未声明 fallback。 - 文档按 Compatible / Adapted / Unsupported 列真实表面,并提供 `uv run` manager-native 示例。 - 每个 child PR 在最终提交上本地执行 focused tests 与 `make test-all`;未通过不得创建或合并 PR,除非 maintainer 明确 override。 - 为节省时间,#1042 的 child PR 不在远程 CI/Docs 服务器触发或等待验证;PR 以本地 gate 记录为准。 - 独立 dev → `main` 集成 PR 的 gate 仍按届时仓库规则执行,不由本条自动豁免。 ## Dependencies / blockers - ADR-0001:唯一 runtime 与层级边界。 - ADR-0002:manager/event/entity facade 不得绕过 backend capability。 - ADR-0003:task owner YAML 与 backend identity。 - ADR-0004:registry bootstrap。 - ADR-0005:`obs` + optional `critic` 与 IPC observation contract。 - #586:P0 scene/entity/`SceneEntityCfg` owner boundary;纯 source port 可先行,production compatibility 不能绕过。 - `SimBackend.step(ctrl, nsteps)` 当前封装 substeps;per-substep hook 若需要新 contract,单独确认。 - 现有 DR unsupported-term warning/filter 与本 roadmap fail-closed 目标不同;接入 EventManager 前必须明确解决,不能继承。 - #627:独立 raycaster 能力,不是 core 前置依赖。 ## Stop conditions - source-aligned port 偏离上游结构到无法逐文件审查,或 UniLab-specific glue 超过声明预算。 - 为兼容而出现两套有行为差异的 managers/runtime,或 alias/fallback 承载独立逻辑。 - manager 调用 backend 私有方法、热路径解析 asset/XML/name,或用 `getattr/hasattr` 探测私有能力。 - lifecycle 对齐要求第二套 `NpEnvState`、runner、collector 或 IPC 协议。 - Hydra 兼容只能靠 scripts 解释 term/algo 规则。 - backend 缺口开始向通用 manager、runner 或 learner 扩散。 - 缺失能力被 warning、skip、zero/no-op 或旧路径掩盖。 - fixture 仍需重写 manager term 结构,说明社区兼容目标未达到。 - pilot 改变现有 observation/action/termination/final observation 或 sim2sim contract。 - manager overhead 不可接受,且优化需要未批准的 compiler/runtime/CI infrastructure。 - task 已迁移但旧实现无法删除,形成无明确 owner/期限的永久双路径。 ## 开发分支与 PR 规则 - 绑定集成分支:[`dev/issue-1042-manager-based-api`](https://github.com/unilabsim/UniLab/tree/dev/issue-1042-manager-based-api)。 - 每个 child issue 从最新集成分支新建 `<type>/issue-<child>-<slug>`;一个 child、一个分支、一个 PR。 - Child PR 的 base 必须是 `dev/issue-1042-manager-based-api`,不能直接投向 `main`;不直接向 dev 分支提交实现。 - 全部已批准 child 合并并验证后,再用一个独立的 dev → `main` PR 完成集成。创建 dev 分支不自动授权任何 child 开发。 - #1042 child PR 通过本地 gate 后自动 squash 合并到绑定 dev,并立即同步 dev、继续下一个依赖已满足且仍在既定 roadmap scope 内的 child;无需为常规 child 逐项暂停。 - 遇到 child stop condition,或需要新公共 contract、backend capability、共享 lifecycle、runner/IPC、support 升级及其他 roadmap 明确要求单独确认的边界时,仍必须停止并请求 maintainer 决策。 ## 性能与设计优先级 UniLab 是面向生产使用的高性能开源 RL training infrastructure。在现有 Heterogeneous RL runtime scope 内,高性能和高效率是必要目标,但本 roadmap 的优先级固定为: 1. **Manager-Based API 的社区语义一致性与结构通用性。** 不为局部性能改写公共语义、形成 UniLab-only 方言,或破坏可迁移的 manager/term/config 结构。 2. **迁移时避免明显低效。** 热路径不引入可直接避免的重复解析、无意义复制、逐环境 Python 循环或临时分配;发现明显性能问题时在当前 owner boundary 内修正。 3. **性能优化必须证明值得。** 只有收益明确、实现通用且不会显著增加长期复杂度时才加入;低收益但增加分支、缓存协议、专用 fast path 或维护负担的设计不做。 先完成语义一致、结构清晰的 NumPy MBA,再用同配置、同硬件 benchmark 定位真实瓶颈。性能不足时优先做不改变用户 API 的内部优化;若优化必须牺牲社区语义或引入复杂专用设计,暂停并交由 maintainer 单独决策。
Owner summary
方向已确认:UniLab 采用 社区兼容 API + UniLab NumPy runtime。实现不重新设计 manager,而以 mjlab 1.6.0 固定 commit 的
src/mjlab/managers/为迁移源,尽量保留目录、命名、配置和生命周期,只做 Torch→NumPy、SimBackend/Hydra/NpEnvState适配及不适用代码删除。允许彻底重构和大量清理,最终不能长期保留新旧双实现;新增 UniLab glue 必须少而薄。能力缺口一律 fail-closed,在 init/materialization 等最近边界直接报错,不 warning + skip、不 no-op、不回退旧路径。source-aligned port 与集中删除可放宽默认 child 预算,但新的公共 contract、lifecycle、backend capability、IPC 仍必须单独确认。已确认决策
1.6.0、commit0fb8a681的src/mjlab/managers/作为 source of truth,先迁移,再最小适配;不重新发明等价接口。NpEnvState、SimBackend多后端隔离、Hydra owner YAML、registry、sim2sim、现有算法和 IPC 数据面。一句话问题
UniLab 还没有采用机器人学习社区已经熟悉的 Manager-Based task 接口;用户迁移 Isaac Lab/mjlab 风格 task 时必须把 term、配置和生命周期重写成各 env 的私有单体方法,而遇到 backend 缺口时还可能得到 warning/skip 而不是明确失败。
为什么现在做
仓库内证据
src/unilab/base/np_env.py的NpEnv.step()统一拥有 action、physics、state update、done 和 autoreset,但src/unilab/envs/locomotion/go2/joystick.py等 task 仍各自维护_init_reward_functions()、_compute_obs()、_compute_reward()与 termination 组装。src/unilab/envs/locomotion/common/rewards.py已有 NumPy reward 函数和 dispatch,但 term 名、参数、shape、reset hook、日志与 lifecycle 不是公共 manager contract。NpEnvState、backend capability 和 IPC observation contract 已有明确 owner 与测试;它们是需要保留的 UniLab 优势,不是 MBA 重写对象。DomainRandomizationManager对部分 unsupported reset term 存在过滤并 warning 的行为。新的 Manager-Based API 不得继承这种静默能力降级;若要统一改变旧 task 行为,必须作为 DR contract child 明确实施。论文带来的产品目标
arXiv:2601.22074v2将 mjlab 定位为 Isaac Lab Manager-Based API 的轻量实现:两者 MDP 结构相同,多数 task 迁移是机械改写,主要差异在 config 容器与 scene/simulator。论文将收益落在减少多 task/robot 重复代码、提高测试和调试能力、加快 reward/curriculum/policy 迭代,同时明确承认 manager abstraction 有 overhead。因此本 roadmap 的目标不是“代码里出现 Manager 类”,而是:
Isaac Lab 用来定义共同接口来源,mjlab
0fb8a681提供可直接迁移、逐项测试的具体行为。上游后续变化不会自动扩大本 roadmap。迁移原则:source-aligned port,不重新实现
迁移源固定为
/home/user/ws/simulator/mjlab/src/mjlab/managers对应 commit 的 12 个 Python 文件,约 2,920 行。mjlab 与 UniLab 均采用 Apache-2.0;实施 PR 必须记录 upstream commit、来源路径和 license/provenance,并保留适用 notice。推荐工作顺序:
manager_base、action/observation/reward/termination/event/command/curriculum/metrics/recorder manager、scene_entity_config与 package exports。.device/.to()/.cpu()、Torch-only storage、Warp/MuJoCo-Warp model mutation、上游 viewer glue 等不属于 UniLab contract 的实现。SimBackend,不能复制一套 backend abstraction。禁止采用以下捷径:
getattr/hasattr、try/except warning、返回零数组或旧路径 fallback;产品目标:具体减少哪些 friction
uv run与 optional backend 依赖。社区兼容 contract
P0:共同 task API
ManagerBasedRLEnv/ config、ManagerBase、ManagerTermBase、func + paramsterm config 心智模型。None显式禁用、function/class term、局部reset(env_ids)、shape/finite fail-fast 和 per-term diagnostics。num_envs、physics/control dt、episode counters、各 manager 属性和正式 scene/entity NumPy view。SceneEntityCfgname/regex → cached ID 语义是 P0;owner boundary 必须与 Work: 评估面向场景和任务 API 的 entity abstraction #586 对齐。P1:低摩擦扩展
Intentional differences
np.ndarray/slice;无 Torch device API。NpEnvState、reset() -> (obs_dict, info_dict)、final observation、obs_groups_spec。obs+ optionalcritic,IPC 不推断。NpEnvState。不声称任意外部 task 可以零改动运行。只有 compatibility fixture/迁移 task 覆盖的表面才能标为 Compatible;其余为 Adapted 或 Unsupported + error。
Fail-closed 能力规则
None属于用户显式选择,可使用 upstream Null manager/no-op 语义。NotImplementedError/compatibility error;不要求伪造 feature parity。In scope
SceneEntityCfgselector,只调用SimBackend。NpEnvState的前提下,将 managers 接入唯一NpEnvlifecycle。Go2JoystickFlat为首个纵向 pilot,保持 registry 名、observation/action 维度和当前注册 backend。Non-goals
isaaclab/mjlabnamespace shim;UniLab 内 alias 只能指向同一实现。training.sim_backend单独切 backend,不把 config/task 规则写入 scripts。Child issue / PR 规模例外
本 roadmap 获得 maintainer 对默认 15 文件/800 行预算的显式放宽,但只适用于可审计的 source migration 和集中清理。所有 child 仍必须只有一个主要结果、一个 PR,并在开始前写明所属类别。
所有 child/PR 必须分别报告 source-derived、机械转换、UniLab-specific glue、modified existing 和 deleted LOC/files。达到任一声明预算即暂停;不能临时把改动重新分类来规避。
最近 3 个可执行 child issue
Child 1 — 社区兼容与直接迁移 ADR(Small,先做)
主要结果: 固定公共表面、迁移方式、provenance、错误策略和删除终态,不含 runtime 实现。
Child 2 — 直接迁移 mjlab managers 并转换为 NumPy(Source-aligned exception)
主要结果:
src/unilab/managers/在不接 production env 的情况下,以 NumPy 通过 upstream-derived manager tests。NpEnv.step()、真实 backend、task、scripts 或 IPC。Child 3 —
SceneEntityCfg+ NumPy entity facade 的真实 owner 接入(普通/公共 contract)主要结果: manager term 可通过冷路径 selector 和稳定 NumPy view 访问真实 UniLab scene/backend,缺口 fail-closed;不接 production task。
src/unilab/base/scene.py、SimBackend名称/ID/state contract,不创建第二套 scene composer。SimBackend方法必须先单独确认,不能塞入本 child。批准本 umbrella 本身不等于无限授权;maintainer 已于 2026-08-18 另行授权按“本地 gate → 自动合并 → 继续下一 child”连续执行既定 roadmap 内的常规 child。开发分支规则列出的高风险边界与 stop condition 仍需单独确认。
后续方向(只记录启动条件)
NpEnv的唯一 ManagerBased lifecycle;不同时迁移 production task。Go2JoystickFlatpilot,并对 MuJoCo/Motrix/Drake 当前注册事实逐一回归;任一 backend 缺口直接 error 或留在未支持矩阵,不静默关闭 feature。per_substepmetrics/action 若需要 backend hook,作为新的SimBackendcontract 单独确认。Owner、预计规模与永久维护成本
reward_config/单体 env bridge、fallback、duplicate manager helper;只有 maintainer 明确接受的 consumer 才能延长生命周期。Umbrella acceptance criteria
src/unilab/managers/的公共模块/类型/行为可追溯到 pinned mjlab source;每项偏离归类为 NumPy、UniLab contract、explicit unsupported 或删除。SceneEntityCfg有实现或 construction-time error;Metrics/Recorder 等 P1 按迁移代码与 evidence 提供。Go2JoystickFlatpilot 保持NpEnvState、reset/step/final observation、action/observation 维度、sim2sim 与现有 backend registration;不支持项显式失败。uv runmanager-native 示例。make test-all;未通过不得创建或合并 PR,除非 maintainer 明确 override。main集成 PR 的 gate 仍按届时仓库规则执行,不由本条自动豁免。Dependencies / blockers
obs+ optionalcritic与 IPC observation contract。SceneEntityCfgowner boundary;纯 source port 可先行,production compatibility 不能绕过。SimBackend.step(ctrl, nsteps)当前封装 substeps;per-substep hook 若需要新 contract,单独确认。Stop conditions
getattr/hasattr探测私有能力。NpEnvState、runner、collector 或 IPC 协议。开发分支与 PR 规则
dev/issue-1042-manager-based-api。<type>/issue-<child>-<slug>;一个 child、一个分支、一个 PR。dev/issue-1042-manager-based-api,不能直接投向main;不直接向 dev 分支提交实现。mainPR 完成集成。创建 dev 分支不自动授权任何 child 开发。性能与设计优先级
UniLab 是面向生产使用的高性能开源 RL training infrastructure。在现有 Heterogeneous RL runtime scope 内,高性能和高效率是必要目标,但本 roadmap 的优先级固定为:
先完成语义一致、结构清晰的 NumPy MBA,再用同配置、同硬件 benchmark 定位真实瓶颈。性能不足时优先做不改变用户 API 的内部优化;若优化必须牺牲社区语义或引入复杂专用设计,暂停并交由 maintainer 单独决策。