解读 21 · tasks/init.py:任务注册表
解读对象:
microduck-replica/upstream/microduck_rl/src/mjlab_microduck/tasks/__init__.py(278 行)
需要的前置:解读 22(配置工厂长什么样);懂「cfg」指 dataclass 配置对象即可
这个文件是整个训练包的"门面"。mjlab 的插件加载器只认 mjlab_microduck 这一个包名,
而它 import 时执行的第一段代码,就把本仓库所有任务(33 个 task_id)注册进了全局任务表。
/train 命令行里敲的每个任务名,都是在这里挂上去的。
一个刻意为之的 import 顺序
文件第 1 行 import 的是 maybe_submit_to_hf_jobs,第 7 行就调用它(__init__.py:7)。
注释(3–6 行)解释了原因:带 --hf-jobs 时,训练任务要在任何环境配置 import 之前
就被拦截并提交到 HF Jobs 后退出——本模块是插件加载器唯一必经之路,是"任何安装顺序都抢不走"
的拦截点。这是一个把副作用写在 import 路径最前面的实战案例。
注册什么:register_mjlab_task 的五个参数
每个任务调用一次 register_mjlab_task(从 mjlab.tasks.registry import,第 9 行),
以第一个任务为例(__init__.py:81-87):
task_id="Mjlab-Velocity-Flat-MicroDuck":命令行里的任务名;env_cfg=make_microduck_velocity_env_cfg():训练用配置实例(工厂函数立即执行);play_env_cfg=make_microduck_velocity_env_cfg(play=True):回放/部署验证用配置;rl_cfg=MicroduckRlCfg:PPO 超参类(注意传的是类不是实例,由框架决定何时实例化);runner_cls=MicroduckOnPolicyRunner:训练器类。
train/play 双份配置是刻意的:训练开域随机化,play 关掉推搡(interval 缩短)便于肉眼观察。
文件共 18 个直接注册:Velocity Flat/Rough、VelStand、StandUp、SitStand、GroundPick、
BallKick、Rollers、Swizzle、RollerCrouch、RollerSlope、RollerStandUp、Spin、Roulade 各按
flat/rough(部分只有 flat)展开,全部共用同一个 MicroduckOnPolicyRunner。
MicroduckOnPolicyRunner:一个只修序列化的子类
第 13–23 行的 MicroduckOnPolicyRunner 继承 mjlab 的 VelocityOnPolicyRunner,唯一做的事:
resolve_symmetry_config 会把 _env(环境对象)原地塞进 train_cfg["algorithm"]["symmetry_cfg"],
与 PPO 内部共享同一个 dict;而 dump_yaml 要序列化这份配置时 MjSpec 不可 pickle。子类把
alg["symmetry_cfg"] 换成一个剔除 _env 的副本(20–23 行),不动 PPO 持有的原引用。
典型的"只差一行"的框架补丁写法。
表驱动批量注册:15 个 Backlash 变体
第 254–270 行的 _BACKLASH_TASKS 是一个 15 元组表,每项 (task_id, make_fn, make_kwargs,
rl_cfg, robot_cfg),第 271–278 行一个 for 循环统一注册,task_id 在基础名里插 -Backlash。
make_backlash_variant(cfg, robot_cfg)(import 于第 78 行)给配置换上带齿隙的机器人模型;
三种机器人配置按任务家族分配(251–253 行):_BL_WALK(走路模型)、_BL_GROUNDCONTACT
(地面接触模型)、_BL_ROLLERS(轮子模型)。同一张表让"加一种齿隙变体"变成加一行。
你带走的收获
- 注册表模式让任务即插即用:新任务 = 一个配置工厂 + 一次
register_mjlab_task,训练入口零改动。 - train/play 双配置分离是 sim2real 工作流的标准做法,注册时就该想好。
- import 顺序可以承载逻辑(HF Jobs 拦截),但要像注释那样写清为什么。
- 变体成批出现时改用表驱动:15 个变体若手写注册就是 90 行重复代码。
- 传类不传实例(
rl_cfg=MicroduckRlCfg)把"何时实例化"的决定权留给框架。
延伸
- 下一站:解读 22 拆开
make_microduck_velocity_env_cfg的前 87 行; - 解读 31、32(待发布)会讲
tasks/backlash.py与导出脚本,即本文件里变体注册的另一半; - 本地路径:
microduck-replica/upstream/microduck_rl/src/mjlab_microduck/tasks/__init__.py