背景
对照参考仓库 mjlab v1.6.0(/home/user/ws/simulator/mjlab)做了完整架构对比。结论:mjlab 是"Isaac Lab API + MuJoCo-Warp 单后端"的垂直整合,UniLab 是"多后端契约 + 多算法 + 可观测性"的平台型架构。架构治理层面(SimBackend fail-closed 契约、sim2sim DENYLIST/ALLOWLIST 审计、Hydra owner YAML)UniLab 更成熟,方向不回退。
但 mjlab 在性能机制 和开发体验 两类局部点上有明确优势,且都能在不触动 UniLab 核心契约的前提下落到 backend 层或 tooling 层:
CUDA graph capture :mjlab Simulation.create_graph()(src/mjlab/sim/sim.py)把 step/forward/reset/sense 捕获成 CUDA graph 反复 replay,是其性能核心;UniLab mjwarp/backend.py(约 830 行)目前只是普通 batch 封装,无 graph capture。
DR 模型字段声明式展开 :mjlab event 用 @requires_model_fields 声明随机化哪些 mjModel 字段,env 收集后 expand_model_fields() tile 成 per-world (nworld, ...) Warp 数组,再按 RecomputeLevel 分级重算常量(src/mjlab/envs/mdp/dr/、src/mjlab/sim/randomization.py);UniLab DR 目前是 provider → capability 过滤 → set_state,缺少 per-world 模型字段展开的显式机制。
标准化 play variant :mjlab 每个 task 工厂带 play=True 分支(剥掉 corruption/pushes/curriculum),registry 成对注册 env_cfg / play_env_cfg;UniLab play 靠 Hydra override 现场拼,五个 play 入口各自组装。
第三方 task 包 entry-point 注册 :mjlab 用 mjlab.tasks entry-point group 挂载外部 task 包;UniLab 靠 UNILAB_EXTRA_REGISTRY_PACKAGES 环境变量,对第三方包不友好。
viewer 体验 :mjlab viser viewer 支持 checkpoint 热切换 + 每个 reward term 实时面板(src/mjlab/viewer/viser/);UniLab 已有 viser 播放和 per-term reward extras 数据,缺前端呈现。
checkpoint 持久化 curriculum/step 计数器 :mjlab MjlabOnPolicyRunner 把 common_step_counter 写进 checkpoint,resume 后 curriculum 状态正确恢复;UniLab 有 patch_rsl_rl_resume_state,但 curriculum manager 的 resume 完整性未审计。
CI 安装冒烟 :mjlab CI build wheel/sdist 后用 tests/smoke_test.py 验证安装产物,防 package data(XML/资产)漏打包;UniLab 资产同样走包内分发,面临相同风险。
总目标与边界
做什么 :从 mjlab 借鉴上述 7 个局部改进点,全部落在 backend 适配层、registry、visualization 或 CI 层,不触动 env / config / 训练语义契约。
不做什么 :
不用 dataclass+tyro 替代 Hydra(与 config first 原则冲突,且 sim2sim 静态审计依赖 YAML);
不向单后端垂直整合回退(多后端契约是差异化价值);
不把 env 层改成 torch-native(违反 NpEnvState 不变量);
不影响已完成的 manager-based API 移植(Roadmap: 将 UniLab 迁移为社区通用的 Manager-Based API #1042 系列),本 roadmap 只补移植范围之外的 mjlab 优势点。
预计总规模 :7 个候选 sub-issue,各自独立、可独立取舍;单点净改动预计都在 15 文件 / 800 行以内(第 1、2 项接近上限,第 4、7 项很小)。
永久维护成本 :低到中。第 1、2 项引入 mjlab 上游机制的本地适配,mjlab 升级时需要 diff 跟进(与 manager 移植的维护模式一致);其余各项均为一次性收敛,之后维护成本持平或下降。
候选 Sub-issues(按投入产出排序,均需单独确认后才启动开发)
明确未授权、需单独确认的扩张点
上述每一项均为候选,批准本 roadmap 只授权规划;任何一项"开始开发"前需单独确认并拆成独立 implementation issue;
第 1 项若需要在 SimBackend 抽象接口新增 graph 相关声明,属新公共 contract,需单独确认;
第 3 项若引入新的 play 执行入口(而非复用现有 playback session 工厂),属新 execution path,需单独确认。
背景
对照参考仓库 mjlab v1.6.0(
/home/user/ws/simulator/mjlab)做了完整架构对比。结论:mjlab 是"Isaac Lab API + MuJoCo-Warp 单后端"的垂直整合,UniLab 是"多后端契约 + 多算法 + 可观测性"的平台型架构。架构治理层面(SimBackendfail-closed 契约、sim2sim DENYLIST/ALLOWLIST 审计、Hydra owner YAML)UniLab 更成熟,方向不回退。但 mjlab 在性能机制和开发体验两类局部点上有明确优势,且都能在不触动 UniLab 核心契约的前提下落到 backend 层或 tooling 层:
Simulation.create_graph()(src/mjlab/sim/sim.py)把 step/forward/reset/sense 捕获成 CUDA graph 反复 replay,是其性能核心;UniLabmjwarp/backend.py(约 830 行)目前只是普通 batch 封装,无 graph capture。@requires_model_fields声明随机化哪些 mjModel 字段,env 收集后expand_model_fields()tile 成 per-world(nworld, ...)Warp 数组,再按RecomputeLevel分级重算常量(src/mjlab/envs/mdp/dr/、src/mjlab/sim/randomization.py);UniLab DR 目前是 provider → capability 过滤 →set_state,缺少 per-world 模型字段展开的显式机制。play=True分支(剥掉 corruption/pushes/curriculum),registry 成对注册env_cfg/play_env_cfg;UniLab play 靠 Hydra override 现场拼,五个 play 入口各自组装。mjlab.tasksentry-point group 挂载外部 task 包;UniLab 靠UNILAB_EXTRA_REGISTRY_PACKAGES环境变量,对第三方包不友好。src/mjlab/viewer/viser/);UniLab 已有 viser 播放和 per-term reward extras 数据,缺前端呈现。MjlabOnPolicyRunner把common_step_counter写进 checkpoint,resume 后 curriculum 状态正确恢复;UniLab 有patch_rsl_rl_resume_state,但 curriculum manager 的 resume 完整性未审计。tests/smoke_test.py验证安装产物,防 package data(XML/资产)漏打包;UniLab 资产同样走包内分发,面临相同风险。总目标与边界
做什么:从 mjlab 借鉴上述 7 个局部改进点,全部落在 backend 适配层、registry、visualization 或 CI 层,不触动 env / config / 训练语义契约。
不做什么:
NpEnvState不变量);预计总规模:7 个候选 sub-issue,各自独立、可独立取舍;单点净改动预计都在 15 文件 / 800 行以内(第 1、2 项接近上限,第 4、7 项很小)。
永久维护成本:低到中。第 1、2 项引入 mjlab 上游机制的本地适配,mjlab 升级时需要 diff 跟进(与 manager 移植的维护模式一致);其余各项均为一次性收敛,之后维护成本持平或下降。
候选 Sub-issues(按投入产出排序,均需单独确认后才启动开发)
mjwarp/backend.py内部实现,不动SimBackend契约;需 CUDA driver ≥12.4 + mempool 条件检测与降级路径)@requires_model_fields+ per-world 字段 tile + 分级 recompute,落在 backend 适配层,与现有DomainRandomizationCapabilities过滤衔接)unilab.tasksentry-point group 注册路径(保留环境变量方式作 fallback)明确未授权、需单独确认的扩张点
SimBackend抽象接口新增 graph 相关声明,属新公共 contract,需单独确认;