Owner summary
UniLab 的 interval domain randomization 已由 provider 生成 plan,但 DomainRandomizationManager 仍在热路径逐项判断 push、线/角速度、body force、body torque 五个固定字段。新增一种 interval term 会同时牵动 unisim.dr.types、capability 字段、manager 和各 backend dispatch,term 扩展成本与 manager 耦合。参考 mjlab 的 EventManager,推荐把 interval term 改为可注册的声明式 descriptor:term 在 owner/provider 层声明 payload、所需 backend capability 和 apply 入口,manager 只负责计时、统一校验和调度;能力仍由 unisim/SimBackend 维护并 fail-closed。交付覆盖 unisim-core 与 UniLab 的 contract、兼容迁移、测试和文档,不改变 reset model-field 声明 issue #1498 的边界。
问题与证据
当前实现存在两类耦合:
src/unilab/dr/manager.py:91-124 直接枚举五个 IntervalRandomizationPlan 字段,并绑定五个 DomainRandomizationCapabilities 布尔字段。
src/unilab/dr/provider.py:33-36 的 provider 只能返回一个固定 schema 的 IntervalRandomizationPlan。
unisim/src/unisim/dr/types.py:137-150 的 plan schema 固定为 push_perturbation_limit、两类 velocity delta、body_force、body_torque;MuJoCo/Motrix backend 仍在 apply_interval_randomization() 内按字段分支。
- 当前任务行为已经由 owner/provider 产生:locomotion provider 构造 push plan,Sharpa provider 构造 body-force plan。因此问题不是任务逻辑进入 manager,而是 contract/dispatch 层对 term 类型封闭。
- mjlab 的对应路径是配置注册任意
EventTermCfg,EventManager 仅按 mode 调度 callable;模型字段通过 term 的 requires_model_fields metadata 汇总,不在 manager 中列出具体随机化项。
主要交付结果
引入 interval term 的声明式 dispatch contract,使 manager 不再包含具体 term 名称或字段分支:
- 定义可扩展的 interval term descriptor/operation(推荐由
unisim.dr owner),至少包含稳定 term 名、payload/shape contract、所需 capability、以及 backend apply 入口;descriptor 必须可被 spawn/pickle 使用。
- provider 返回 descriptor 集合或兼容的 operation plan;manager 只遍历 operation,执行统一的空 plan、能力校验、错误诊断和 backend dispatch。
- 将现有 push、linear/angular velocity delta、body force/torque 迁移为内置 descriptor,保留现有行为和 public
SimBackend 边界。
- capability 校验在 env/provider 初始化或 term bind 的 cold path 完成;热路径不通过
getattr/hasattr 探测 backend 私有能力。后端不支持时继续 fail-closed,并给出 term 名和 backend 名。
- 提供旧
IntervalRandomizationPlan provider 的适配/弃用路径,避免一次性破坏现有 task owner。
方案选择
推荐方案 A:
- A. Descriptor/operation registry(推荐):manager 完全 generic;新增 term 只需增加 descriptor、backend contract 和 owner/provider 实现。扩展性最好,改动约 2 个仓库、20 文件以内,新增长期 contract 维护责任。
- B.
capabilities.validate_interval_plan(plan):把现有字段判断从 UniLab manager 移到 unisim capability 对象。改动较小,但 plan schema 仍封闭,新增 term 仍需修改统一类型和 backend,作为短期过渡可接受。
- C. EventManager-style callable callbacks:provider 直接注册可调用 term,manager 只做 lifecycle 调度。最接近 mjlab,但会较大幅度改变当前 provider/plan API,并需要重新定义跨进程序列化和 backend apply 边界。
若 maintainer 选择 B,应把它明确标记为过渡方案,并保留后续迁移到 A 的接口方向。
范围与边界
本 issue 包含:
unisim-core 的 interval term/operation 与 capability contract;
- MuJoCo、Motrix 及已有相关 backend 的适配;
- UniLab
DomainRandomizationProvider / DomainRandomizationManager 的兼容迁移;
- 现有 locomotion、Sharpa term 的迁移;
- 单元、backend smoke、跨 backend 行为测试和 DR contract 文档;
- 追加一个自定义 interval term 测试,证明新增 term 不需要修改 manager。
关联但不包含:
Owner 与 contract 影响
主要 owner 为 unisim-core DR/backend contract 与 UniLab src/unilab/dr/。本工作新增长期维护的 interval term descriptor、capability 映射、backend adapter 兼容层;不改变 SimBackend 已声明的 public entity write API。若 descriptor 引入新的 public SimBackend 方法,需按 ADR-0002 先更新 contract 和各 backend 的 fail-closed 实现。
Roadmap relationship and target branch
这是 roadmap #1252(已关闭)中 mjlab DR 借鉴工作的独立遗留切片;reset model-field 方向已在 #1498 单独跟踪。本 issue 从 main 开始,若拆分为跨仓库 child PR,建议先合入 unisim-core contract,再合入 UniLab adapter/provider,最终在 main 边界运行完整 gate。
规模与 review 计划
预计 2 个仓库、约 15–20 个文件、手写 600–900 LOC。建议拆为:
- unisim-core descriptor/capability contract 与 backend adapter;
- UniLab manager/provider 兼容迁移与内置 term;
- 测试、文档和旧 API deprecation 收口。
需要 unisim DR/backend owner、UniLab env/DR owner 以及至少一名跨后端 reviewer。
Acceptance criteria
DomainRandomizationManager 不再出现具体 interval term 字段名或逐项 capability if 分支。
- 新增一个 fake/custom interval term 时,只新增 descriptor/provider/backend contract 测试,不修改 manager。
- push、两类 velocity delta、body force、body torque 在支持的 backend 上保持现有数值和时序语义。
- 不支持的 term 在 cold path 或统一 dispatch 边界 fail-closed,错误包含 term 与 backend;不发生静默丢弃。
- 现有 provider 和 task owner 通过兼容适配运行,且明确弃用期限/迁移文档。
- 覆盖 MuJoCo、Motrix、mjwarp 及 capability-negative fake backend;验证 partial env ids、空 plan、term 组合和异常路径。
- 更新 DR contract 文档,明确 term registration、capability ownership、pickle/spawn 要求和 backend isolation。
- 最终实现 head 通过
make test-all;interval 热路径 benchmark 相对基线无明显回退并记录结果。
Dependencies and blockers
Proposed owner
unisim-core DR/backend owner + UniLab DR/env owner(具体 GitHub handle 待确认)。
Validation plan
先运行现有 uv run pytest tests/dr/test_manager.py tests/base/test_sim_backend_smoke.py -q 建立基线;迁移后补充 descriptor extensibility、capability-negative、backend parity 和 spawn/pickle 测试,再运行 make test-all。对 interval apply 路径记录支持 backend 的吞吐/延迟对比,确认 manager generic 化没有引入热路径分配或额外 backend round-trip。
Owner summary
UniLab 的 interval domain randomization 已由 provider 生成 plan,但
DomainRandomizationManager仍在热路径逐项判断push、线/角速度、body force、body torque 五个固定字段。新增一种 interval term 会同时牵动unisim.dr.types、capability 字段、manager 和各 backend dispatch,term 扩展成本与 manager 耦合。参考 mjlab 的 EventManager,推荐把 interval term 改为可注册的声明式 descriptor:term 在 owner/provider 层声明 payload、所需 backend capability 和 apply 入口,manager 只负责计时、统一校验和调度;能力仍由 unisim/SimBackend 维护并 fail-closed。交付覆盖 unisim-core 与 UniLab 的 contract、兼容迁移、测试和文档,不改变 reset model-field 声明 issue #1498 的边界。问题与证据
当前实现存在两类耦合:
src/unilab/dr/manager.py:91-124直接枚举五个IntervalRandomizationPlan字段,并绑定五个DomainRandomizationCapabilities布尔字段。src/unilab/dr/provider.py:33-36的 provider 只能返回一个固定 schema 的IntervalRandomizationPlan。unisim/src/unisim/dr/types.py:137-150的 plan schema 固定为push_perturbation_limit、两类 velocity delta、body_force、body_torque;MuJoCo/Motrix backend 仍在apply_interval_randomization()内按字段分支。EventTermCfg,EventManager 仅按 mode 调度 callable;模型字段通过 term 的requires_model_fieldsmetadata 汇总,不在 manager 中列出具体随机化项。主要交付结果
引入 interval term 的声明式 dispatch contract,使 manager 不再包含具体 term 名称或字段分支:
unisim.drowner),至少包含稳定 term 名、payload/shape contract、所需 capability、以及 backend apply 入口;descriptor 必须可被 spawn/pickle 使用。SimBackend边界。getattr/hasattr探测 backend 私有能力。后端不支持时继续 fail-closed,并给出 term 名和 backend 名。IntervalRandomizationPlanprovider 的适配/弃用路径,避免一次性破坏现有 task owner。方案选择
推荐方案 A:
capabilities.validate_interval_plan(plan):把现有字段判断从 UniLab manager 移到 unisim capability 对象。改动较小,但 plan schema 仍封闭,新增 term 仍需修改统一类型和 backend,作为短期过渡可接受。若 maintainer 选择 B,应把它明确标记为过渡方案,并保留后续迁移到 A 的接口方向。
范围与边界
本 issue 包含:
unisim-core的 interval term/operation 与 capability contract;DomainRandomizationProvider/DomainRandomizationManager的兼容迁移;关联但不包含:
requires_model_fields风格声明与需求驱动展开(DR 声明式模型字段声明层:requires_model_fields 风格的 per-term 声明与需求驱动展开(roadmap #1252 第 2 点遗留) #1498);EventManager已有的 generic interval event 调度重写;Owner 与 contract 影响
主要 owner 为
unisim-coreDR/backend contract 与 UniLabsrc/unilab/dr/。本工作新增长期维护的 interval term descriptor、capability 映射、backend adapter 兼容层;不改变SimBackend已声明的 public entity write API。若 descriptor 引入新的 publicSimBackend方法,需按 ADR-0002 先更新 contract 和各 backend 的 fail-closed 实现。Roadmap relationship and target branch
这是 roadmap #1252(已关闭)中 mjlab DR 借鉴工作的独立遗留切片;reset model-field 方向已在 #1498 单独跟踪。本 issue 从
main开始,若拆分为跨仓库 child PR,建议先合入 unisim-core contract,再合入 UniLab adapter/provider,最终在main边界运行完整 gate。规模与 review 计划
预计 2 个仓库、约 15–20 个文件、手写 600–900 LOC。建议拆为:
需要 unisim DR/backend owner、UniLab env/DR owner 以及至少一名跨后端 reviewer。
Acceptance criteria
DomainRandomizationManager不再出现具体 interval term 字段名或逐项 capabilityif分支。make test-all;interval 热路径 benchmark 相对基线无明显回退并记录结果。Dependencies and blockers
Proposed owner
unisim-core DR/backend owner + UniLab DR/env owner(具体 GitHub handle 待确认)。
Validation plan
先运行现有
uv run pytest tests/dr/test_manager.py tests/base/test_sim_backend_smoke.py -q建立基线;迁移后补充 descriptor extensibility、capability-negative、backend parity 和 spawn/pickle 测试,再运行make test-all。对 interval apply 路径记录支持 backend 的吞吐/延迟对比,确认 manager generic 化没有引入热路径分配或额外 backend round-trip。