简介#
PredActor(Predictive Action Diffusion)是开源的人形机器人扩散控制策略。它根据机器人最近几步的本体感知和可选的任务命令,同时预测未来的全身状态和关节动作:预测的状态留在策略内部,供引导使用;动作直接发给关节控制器,不需要单独的跟踪器。
在机器人机载的 Jetson Orin NX 上,PredActor 以 50 Hz 运行,完整控制回调的中位耗时为 16.790 ms,p95 为 19.383 ms,都低于 20 ms 的控制周期。
资源入口:
1. 概览#
本节介绍 PredActor 的工作原理、发布内容和环境配置。完成本节后,你可以在本机打开浏览器评测界面,用文本命令控制仿真中的机器人。
1.1 PredActor 能做什么#
| 工作流 | 做什么 | 见 |
|---|---|---|
| 浏览器评测 | 在 MuJoCo 中运行发布的模型,用文本、手柄、速度引导或目标点控制,并施加外力 | 第 2 节 |
| 数据采集 | 在 Isaac Lab 中让教师策略执行 152 段动作,记录状态–动作轨迹 | 第 3 节 |
| 数据标注 | 用 MotionCLIP 给每一帧加上 512 维、与文本对齐的动作语义向量 | 第 4 节 |
| 训练 | 行为克隆训练文本条件策略或无条件基线 | 第 5 节 |
| 训练动作编码器(实验性) | 从头训练 MotionCLIP 动作编码器,替换标注所用的模型 | 第 6 节 |
DAgger 数据聚合和真机部署代码尚未发布。在 MuJoCo 中能运行只说明软件和权重兼容,不代表真机安全;上真机需要另外做控制、安全和硬件验证。
1.2 工作原理#
读入本体感知。 控制频率 50 Hz(周期 0.02 秒)。每个周期读入最近 4 步的观测:关节位置、关节速度、重力投影、基座线速度、基座角速度和上一步动作,每步 96 维。文本条件策略再拼上 512 维的文本语义向量。
联合生成状态和动作。 一个 Transformer 扩散模型同时去噪未来 20 步(0.4 秒)的全身状态(30 个刚体的位置、速度和根节点状态)和 29 维关节动作。发布的文本条件配置每个周期做 5 步 DDIM 去噪。
只执行动作。 取当前一步的动作直接发给关节 PD 控制器。预测的未来状态不交给任何跟踪器,只留在策略内部。
两种引导。 CFG(classifier-free guidance)强化训练中学过的条件,例如文本命令;CG(classifier guidance,界面中叫全身引导)对预测的未来状态施加目标,例如前进、横向、转向速度和骨盆高度,在去噪过程中把状态推向目标,进而影响动作。
观测只用本体感知。 推理时状态流从条件中直接去噪,不需要外部估计的全身状态作为输入。
1.3 发布的模型与数据#
模型和数据放在 Hugging Face 仓库 MasterYip/PredActor_Artifacts,下载后位于仓库根目录下被 Git 忽略的 Artifacts/ 中:
| 文件 | 作用 | 大小 | 用于 |
|---|---|---|---|
checkpoints/predactor/pdp051/latest.ckpt |
发布的文本条件策略 PDP051 | 49.2 MB | 评测(第 2 节) |
checkpoints/motionclip/g1-model-xyz-clip/checkpoint_0100.pth.tar |
微调过的 MotionCLIP 动作–文本编码器 | 542.7 MB | 评测时编码文本、数据标注(第 2、4 节) |
checkpoints/rl_tracker/model_75000.pt |
RLTracker 教师策略 | 87.4 MB | 数据采集(第 3 节) |
motions/g1_152fk/ |
152 段已重定向的动作,每段一个 motion.npz |
约 87 MB | 数据采集与标注(第 3、4 节) |
1.4 两套运行环境#
| 环境 | 用途 | 创建方式 |
|---|---|---|
uv 环境(.venv) |
评测、数据标注、训练、训练动作编码器 | uv sync --locked,版本由 uv.lock 锁定 |
conda 环境 predactor-collection |
只用于数据采集(Isaac Sim 4.5.0 + Isaac Lab 2.1.0) | PredActor/collection/install.sh,见 3.2 节 |
1.5 系统要求#
| 项目 | 要求 |
|---|---|
| 操作系统 | Linux |
| Python | 3.10 |
| 包管理 | uv(必需);conda(仅数据采集需要) |
| PyTorch | 2.5.1,CUDA 12.1 版 wheel(两套环境相同) |
| GPU | 评测:有 CUDA 时使用,没有时自动用 CPU。训练:默认 cuda:0,也可改用 CPU。数据标注:默认 CUDA。数据采集:需要能运行 Isaac Sim 4.5.0 的 NVIDIA GPU |
| 网络 | 首次数据标注和动作编码器训练会下载 OpenAI 的 CLIP ViT-B/32 权重;采集环境安装需要访问 PyTorch、NVIDIA 的包索引和 GitHub |
1.6 安装#
git clone https://github.com/MasterYip/PredActor.git
cd PredActor
uv sync --lockeduv sync --locked 按 uv.lock 建好 Python 3.10 环境,其中包含评测器、MuJoCo、浏览器界面和训练所需的依赖。评测不需要 Isaac Sim。
提示 评测命令都带
--locked,保证运行时环境与锁文件一致;uv run --locked会直接使用这个环境,不需要先激活。
1.7 下载模型#
uv run --locked python scripts/hf_download.py --filter checkpoints--filter 按 Hugging Face 仓库中的路径前缀筛选,checkpoints 会下载 1.3 节表格中的三个 checkpoint,motions/g1_152fk 下载动作数据。下载完成后,脚本会核对每个文件的字节数和 SHA-256。
| 命令 | 作用 |
|---|---|
… hf_download.py --filter checkpoints |
下载三个 checkpoint(评测只需要这一步) |
… hf_download.py --filter checkpoints motions/g1_152fk |
再加上 152 段动作,复现采集和训练时用 |
… hf_download.py --list |
列出全部可下载项和对应的本地路径 |
… hf_download.py --dry-run |
只显示会下载什么,不实际下载 |
已下载且大小一致的文件会被跳过。网络中断后重跑同一命令,只会补下缺失或大小不对的文件。
1.8 跑通快速测试#
uv run --locked predactor-eval这条命令加载 PDP051 策略和 MotionCLIP 编码器,启动 MuJoCo 仿真,并在浏览器中打开 http://127.0.0.1:8765/。页面中出现机器人、步数(STEP)开始增加,说明评测环境正常。在 CLIP command 输入框中输入 walk 并回车,机器人应从站立切换为行走。
确认训练环境可以用 smoke 测试,不需要下载任何数据:
uv run python PredActor/scripts/training_smoke.py它生成一份确定性的小数据集,用缩小的模型跑一步优化并检查保存的 checkpoint。通过时打印 PREDACTOR_TRAINING_SMOKE_PASS 和记录文件路径。smoke 只确认代码路径能跑通,不代表模型质量。
1.9 目录布局#
PredActor/ # 仓库根目录,所有命令在这里运行
├── Artifacts/ # 下载的模型和数据,以及采集、标注产物
│ ├── checkpoints/
│ ├── motions/g1_152fk/
│ └── dataset/ # 第 3、4 节写入
├── outputs/ # 训练输出(第 5 节)
├── eval_output/web/ # 默认评测输出(第 2 节)
└── PredActor/ # 源码
├── diffusion_policy/ # 策略、训练器、评测器、Web 界面
├── collection/ # 数据采集与标注
└── motion_encoder/ # 动作编码器训练2. 评测#
本节在浏览器评测界面中运行策略:用文本命令选择行为,用速度引导、手柄或目标点控制方向,并用鼠标施加外力。命令都在仓库根目录运行。
2.1 启动评测#
uv run --locked predactor-eval不带参数时使用发布的 PDP051 策略。常用选项:
| 选项 | 作用 | 默认值 |
|---|---|---|
-c, --checkpoint |
策略 checkpoint | Artifacts/checkpoints/predactor/pdp051/latest.ckpt |
--config |
评测配置;只写文件名时到 PredActor/diffusion_policy/config_files/ 中查找 |
g1prdp_cond_diffuse.yaml |
-o, --output_dir |
结果输出目录 | eval_output/web |
-d, --device |
推理设备 | 有 CUDA 时为 cuda:0,否则 cpu |
--precision |
推理精度,fp32 或 fp16 |
配置中的 training.precision,没有时为 fp32 |
--checkpoint-replica |
使用 agent 还是 ema_agent 权重 |
agent |
--web-port |
界面端口 | 8765 |
--web-host |
界面绑定地址 | 127.0.0.1 |
--web-no-browser |
不自动打开浏览器 | 关闭 |
--headless |
不打开 MuJoCo 窗口和其他图形界面 | 不覆盖配置 |
--web-perturb |
允许在界面中用鼠标施加外力(见 2.7 节) | 关闭 |
完整选项用 uv run --locked predactor-eval --help 查看。
在没有显示器的服务器上,用无头方式启动,再把端口转发到本机浏览器:
# 服务器上
uv run --locked predactor-eval --headless --web-no-browser
# 本机上,转发后打开 http://127.0.0.1:8765/
ssh -L 8765:127.0.0.1:8765 <用户名>@<服务器地址><用户名>@<服务器地址> 换成你登录服务器的账号。端口 8765 已被占用时,加 --web-port 8766 换一个端口。
2.2 用文本命令选择行为#
在右侧 CLIP command 面板中选择 TEXTOP。
在输入框中输入动作描述,按回车或点击 ↑。界面提示的示例有
walk、jog、run、squat down、jump up、raise hand、kick。面板中显示当前生效的命令。启动时的默认命令是
stand。
文本经 MotionCLIP 编码成 512 维向量,作为策略的条件输入。
注意 训练数据只有 152 段动作,描述越复杂越可能得不到预期的行为。先用上面列出的简单命令确认效果。
2.3 在两个行为之间插值#
INTERP 模式把多条"起点 → 终点"语义方向按权重叠加,得到连续变化的条件:
在 CLIP command 面板中选择 INTERP,面板列出默认的命题:零向量 →
stand、stand→walk、walk→run、stand→squat down、get down→raise hand。默认只有第一条的权重为 1,其余为 0。拖动某一行的权重滑块。起点或终点为零向量(Ø)时,权重范围是 0–1;两端都是文本时为 −1 到 1。
用 + 添加命题,最多 16 条;可以改写每条的起点和终点文本。
点击 APPLY。各条命题按权重相加并归一化后,作为新的条件。
2.4 用全身引导控制速度#
Whole-body guidance 面板直接对预测的未来状态施加速度目标:
确认面板标题旁的开关为 Enabled。
SOURCE OWNER 选 WEB,用界面滑块控制;选 JOY,用手柄控制(见 2.6 节)。
拖动 Forward、Lateral、Yaw,分别设定前进、横向和转向速度目标。
Gain Kp 是引导强度,默认 1.00,范围 0–4;设为 0 相当于不引导。
Activation manager 中的高级选项可以按引导类型选择作用的身体部位和观测项,一般不需要改动。点击其中的 ↺ 恢复默认。
文本命令和全身引导可以同时使用:文本选择"怎么动"(如行走或慢跑),引导决定"往哪走、多快"。
2.5 走到目标点#
Destination follow 根据目标点自动生成速度目标:
在 X、Y、Z 中输入世界坐标系中的目标位置。
点击 SET,设定目标并开启跟随。机器人转向并朝目标移动;水平距离进入到达半径后,速度目标归零,机器人停下。
到达后如果机器人被推离目标超过重新跟随半径,会再次开始跟随。
点击 CANCEL 关闭跟随并清除目标。
Controller tuning 中的参数点击 APPLY 后生效:
| 参数 | 作用 | 默认值 |
|---|---|---|
| Forward gain / Lateral gain / Heading gain | 前进、横向、朝向的跟随增益 | 2.00 / 0.80 / 6.00 |
| Forward min / max | 前进速度目标范围 | 0 / 8 |
| Lateral min / max | 横向速度目标范围 | −1 / 1 |
| Yaw min / max | 转向速度目标范围 | −10 / 10 |
| Heading dead zone | 朝向误差死区 | 0.01 |
| Arrival radius | 到达半径 | 0.30 |
| Rearm radius | 重新跟随半径,不能小于到达半径 | 0.60 |
2.6 用手柄控制#
评测器默认自动查找 Linux 手柄设备(--web-joystick-device auto),按 Xbox 手柄的键位解析(--web-joystick-type xbox_new)。启动时检测到手柄,全身引导的来源会自动设为 JOY;Controller 面板显示按键状态。以下操作在来源为 JOY 时生效:
| 操作 | 手柄 |
|---|---|
| 前进 / 后退 | 左摇杆上下 |
| 左右平移 | 左摇杆左右 |
| 转向 | 右摇杆左右 |
| 骨盆高度 | 右摇杆上下 |
切换到 stand / walk / jog / squat down |
方向键 上 / 右 / 下 / 左 |
| 减弱引导 | 按下 LT(L2):引导强度随按压程度从 1 降到 0,松开恢复为 1 |
| 开启或关闭全身引导 | LB |
点击 Controller 面板的 ? 可以查看当前手柄的键位。
2.7 施加外力和重置#
用 --web-perturb 启动后,可以在仿真画面中用鼠标推机器人:
| 操作 | 作用 |
|---|---|
| 双击 | 选中一个刚体 |
| Ctrl + 右键拖动 | 在选中点施加力 |
| Ctrl + 左键拖动 | 对选中的刚体施加力矩 |
橙色箭头显示拖动的方向和大小。力和力矩的上限默认为 120 和 30,可用 --web-perturb-max-force 和 --web-perturb-max-torque 调整。仿真画面工具栏中的 ↺(Reset MuJoCo robot)重置机器人;勾选 AUTO RESET 后,机器人跌倒时自动重置。页面顶部的 ❚❚ 暂停评测。
2.8 评测自己训练的模型#
把 run_dir 设为训练时打印的输出目录(见 5.4 节):
run_dir="outputs/<训练输出目录>"
uv run --locked predactor-eval \
--checkpoint "$run_dir/checkpoints/latest.ckpt" \
--config "$run_dir/resolved_config.yaml" \
--output_dir "$run_dir/eval" \
--web-ui训练时保存的 resolved_config.yaml 决定加载哪种策略和文本编码器。无条件基线(见 5.2 节)同样可以输入文本命令,但文本对它没有作用。
2.9 评测输出#
评测结束后,输出目录中有:
| 文件 | 内容 |
|---|---|
eval_results.json |
评测结果 |
eval_config.yaml |
本次评测实际使用的配置 |
eval_summary.txt |
结果摘要 |
3. 数据采集#
本节在 Isaac Lab 中让发布的 RLTracker 教师策略执行动作库中的动作,记录 PredActor 训练所需的状态–动作轨迹。采集使用单独的 conda 环境,命令在仓库根目录运行。
3.1 准备输入#
在 uv 环境中下载教师策略和 152 段动作:
uv run --locked python scripts/hf_download.py \
--filter checkpoints/rl_tracker motions/g1_152fk下载后的默认位置:
Artifacts/
├── checkpoints/rl_tracker/model_75000.pt
└── motions/g1_152fk/
├── <动作名>/motion.npz
└── ... # 共 152 段3.2 安装采集环境#
conda create --override-channels -c conda-forge -n predactor-collection python=3.10 -y
conda activate predactor-collection
bash PredActor/collection/install.sh安装脚本依次完成:
确认当前 Python 是 3.10,否则退出。
安装 PyTorch 2.5.1(CUDA 12.1)和 Isaac Sim 4.5.0。
把 Isaac Lab v2.1.0 的固定提交下载到
PredActor/collection/.deps/IsaacLab,只安装采集用到的 4 个扩展。安装仓库自带的 RLTracker 任务、RSL-RL 运行时和 CUDA 正向运动学库。
全程使用
PredActor/collection/constraints.txt锁定版本,最后运行pip check。
成功时最后一行是 PredActor collection environment is ready.。
提示 访问 PyPI 较慢时,用阿里云镜像安装 Python 包;PyTorch 和 Isaac Sim 仍从各自的 CUDA / NVIDIA 索引下载:
PIP_INDEX_URL=https://mirrors.aliyun.com/pypi/simple bash PredActor/collection/install.sh网络中断后重跑同一命令,已完成的下载和 Isaac Lab 代码会被复用。
3.3 检查输入#
在采集环境中运行:
python PredActor/collection/scripts/collection_preflight.py脚本检查采集代码、教师策略和动作文件是否就位,输出一段 JSON。status 为 PASS、motion_count 为 152 时可以开始采集。
3.4 运行采集#
bash PredActor/collection/collect_dataset.sh \
--mode deterministic \
--samples_per_motion 50 \
--num_envs 1000 \
--headless确定性模式(deterministic)让每段动作从头到尾执行指定次数:152 段 × 50 次 = 7,600 个 episode。执行失败的 episode 会重新分配,不计入总数。结果写入 Artifacts/dataset/g1_152fk_raw/motion.zarr。
3.5 采集参数#
| 选项 | 作用 | 默认值 |
|---|---|---|
--mode |
deterministic(每段动作固定次数)或 standard(随机采样并过滤) |
deterministic |
--samples_per_motion |
确定性模式下每段动作的执行次数 | 50 |
--num_envs |
并行环境数 | 1000 |
--min_episode_length |
保留 episode 的最短长度 | 100 |
--len_to_save |
standard 模式下要采集的总步数 |
1000000 |
--noise_sigma / --no_noise |
动作噪声(OU 过程)的强度 / 关闭噪声 | 0.2 / 噪声开启 |
--checkpoint、--motion_file、--output_dir |
教师策略、动作匹配模式、输出目录 | 见 3.1 节和 3.4 节 |
--headless / --visualize |
无界面运行 / 打开 Isaac Sim 窗口 | 无界面 |
--livestream 2 |
与 --headless 一起用,通过 WebRTC 在浏览器中查看 |
0(关闭) |
完整选项用 bash PredActor/collection/collect_dataset.sh --help 查看。
注意 确定性模式在进度超过 90% 后,如果连续 1800 秒没有新 episode 完成,会提前结束,避免卡在执行不了的动作上。因此实际 episode 数可能少于 7,600,训练前看一下采集日志中的最终数量。
3.6 使用自己的动作集#
把动作放在
Artifacts/motions/<动作集名>/<动作名>/motion.npz。采集时加
--motion_file "<动作集名>/*"。episode 总数为匹配到的动作数乘以--samples_per_motion。标注时用同一个匹配模式设置
input.motion_pattern(见 4.3 节)。
4. 数据标注#
本节给采集到的每一帧加上 512 维、与文本对齐的 MotionCLIP 语义向量,作为文本条件训练的标签。项目把这一步叫作"数据染色"(data dyeing)。在 uv 环境中运行,先退出采集环境(conda deactivate)。
4.1 准备#
确认以下文件就位:
Artifacts/checkpoints/motionclip/g1-model-xyz-clip/checkpoint_0100.pth.tar # MotionCLIP 编码器
Artifacts/dataset/g1_152fk_raw/motion.zarr # 第 3 节的采集结果
Artifacts/motions/g1_152fk/*/motion.npz # 原始动作4.2 运行标注#
uv run python PredActor/collection/scripts/data_dyeing/data_dyeing.py结果写入 Artifacts/dataset/g1_152fk/motion_dyed_text_t0.01.zarr,新增字段 motion_latent,每帧 512 维。
发布的配置直接编码原始动作,而不是采集到的样本:每段原始动作只编码一次,再按 motion_idx 附加到这段动作的所有 episode 上。编码时把 50 Hz 的轨迹重采样到 30 Hz,取 60 帧窗口,使用 xyz 位置表示,再以温度 0.01 对齐到文本词表的 CLIP 文本向量。
提示 第一次运行会下载 OpenAI 的 CLIP
ViT-B/32权重到 CLIP 缓存目录(通常是~/.cache/clip),需要能访问外网。
4.3 标注参数#
参数写成 Hydra 覆盖项加在命令末尾,例如 input.zarr_path=/path/to/motion.zarr:
| 参数 | 作用 | 默认值 |
|---|---|---|
input.zarr_path |
采集得到的原始 zarr | Artifacts/dataset/g1_152fk_raw/motion.zarr |
input.motion_pattern |
原始动作的匹配模式 | g1_152fk/* |
input.motion_base_path |
原始动作的根目录 | Artifacts/motions |
input.length_mismatch_policy |
样本与原始动作长度不一致时的处理:clip_or_drop、drop_all 或 interpolate |
clip_or_drop |
motionclip.checkpoint_path |
MotionCLIP checkpoint | 发布的 checkpoint_0100.pth.tar |
motionclip.device |
编码设备 | cuda |
encoding.text_alignment_temperature |
文本对齐的温度 | 0.01 |
output.zarr_path |
输出 zarr | Artifacts/dataset/g1_152fk/motion_dyed_text_t0.01.zarr |
clip_or_drop 的含义:样本比原始动作短时,把原始动作截到样本长度;样本更长时,丢弃这个 episode。
5. 训练#
本节用标注后的数据做行为克隆训练,得到可以在第 2 节界面中评测的策略。在 uv 环境中、仓库根目录运行。
5.1 训练文本条件策略#
uv run python PredActor/train.py \
--cfg g1prdp_cond_diffuse.yaml \
--exp_name predactor_bc \
dataset_dir="$PWD/Artifacts/dataset/g1_152fk" \
dataset.zarr_path=motion_dyed_text_t0.01.zarr \
training.num_epochs=50 \
training.seed=42 \
dataloader.num_workers=16 \
logging.mode=offline \
training.save_terminal_checkpoint=true除最后一行外,这条命令与仓库文档中的论文配置训练命令相同;最后一行 training.save_terminal_checkpoint=true 让训练结束时保存最终权重,原因见下面的"注意"。
--cfg 选择 PredActor/diffusion_policy/config_files/ 中的配置,其后的 键=值 覆盖配置项。logging.mode=offline 让 Weights & Biases 只在本地记录;默认的 online 需要先登录 W&B。
注意 训练每 10 个 epoch 保存一次
checkpoints/latest.ckpt,epoch 从 0 开始计数。不加training.save_terminal_checkpoint=true时,50 个 epoch 的训练结束后latest.ckpt是第 40 个 epoch 的权重,而不是最终权重。
训练时,配置中的所有引导会被自动关闭;引导只在推理时生效。
5.2 训练无条件基线#
无条件基线使用同一份标注数据,但不以文本为条件:
uv run python PredActor/train.py \
--cfg g1prdp_diffuse.yaml \
--exp_name predactor_bc_unconditional \
dataset_dir="$PWD/Artifacts/dataset/g1_152fk" \
dataset.zarr_path=motion_dyed_text_t0.01.zarr \
training.seed=42 \
dataloader.num_workers=16 \
logging.mode=offline两份配置的区别:
文本条件(g1prdp_cond_diffuse.yaml) |
无条件(g1prdp_diffuse.yaml) |
|
|---|---|---|
| 每步条件 | 96 维本体感知 + 512 维文本 | 96 维本体感知 |
| 推理时的 DDIM 步数 | 5 | 2 |
| 训练 epoch 数 | 命令中设为 50(配置默认 400) | 配置中为 100 |
两次训练用不同的 --exp_name,输出目录才不会混淆。
5.3 常用训练参数#
| 参数 | 作用 | 默认值 |
|---|---|---|
training.num_epochs |
训练 epoch 数 | 400(无条件配置为 100) |
training.seed |
随机种子 | 42 |
training.device |
训练设备;设为 cpu 用 CPU 训练 |
cuda:0 |
--gpu N |
选择第 N 张 GPU | 不设置 |
dataloader.batch_size |
batch size | 256 |
dataloader.num_workers |
DataLoader 进程数 | 8 |
optimizer.learning_rate |
学习率,余弦衰减,前 10000 步线性预热 | 0.0001 |
training.checkpoint_every |
每隔多少个 epoch 保存 latest.ckpt |
10 |
training.use_ema |
是否维护 EMA 权重 | true |
training.save_terminal_checkpoint |
训练结束时保存最终权重 | false |
dataset.load_to_memory |
把整份数据载入内存;内存不够时设为 false,速度变慢 |
true |
dataset.val_ratio |
验证集比例 | 0.02 |
logging.mode |
W&B 记录方式:online、offline 或 disabled |
online |
5.4 训练产物#
训练开始时打印输出目录,格式为 outputs/<月份-日-时-分-秒>-<配置名>-<exp_name>/,例如 outputs/October-16-22-30-05-g1prdp_cond_diffuse-predactor_bc/。目录中有:
| 文件 | 内容 |
|---|---|
resolved_config.yaml |
合并了默认值和命令行覆盖项的完整配置,评测时传给 --config |
checkpoints/latest.ckpt |
最新保存的权重,评测时传给 --checkpoint |
logs.json.txt |
训练日志 |
接下来按 2.8 节在浏览器界面中评测这个模型。
6. 动作编码器#
本节从头训练 MotionCLIP 动作编码器,它把 60 帧动作和文本描述映射到同一个 512 维空间,第 4 节的标注用的就是它。这一流程目前是实验性的;只想复现策略训练时,直接使用发布的编码器即可。
6.1 准备数据#
需要两份数据,按各自的许可获取:
已重定向到本机器人 29 个关节的 AMASS 动作,每段一个 NPZ 文件;
BABEL 标注的
train.json和val.json。
1.3 节中的 152 段动作不是完整的编码器训练数据。在 PredActor/motion_encoder/ 下按以下布局放置:
PredActor/motion_encoder/
└── data/
├── g1_retargeted_amass/
│ ├── ACCAD/<subject>/<sequence>_poses_120_jpos.npz
│ ├── CMU/<subject>/<sequence>_poses_120_jpos.npz
│ └── ...
└── babel_v1.0_release/
├── train.json
└── val.json目录名和原始序列名必须与 BABEL 的 feat_p 路径对应,例如 ACCAD/<subject>/<sequence>_poses_120_jpos.npz 对应 BABEL 中 ACCAD/<subject>/<sequence>_poses.npz 的标注。文件名中的数字后缀可以不同。每个 NPZ 必须包含:
| 字段 | 形状 | 含义 |
|---|---|---|
dof_positions |
(T, 29) |
关节角,单位弧度 |
body_positions |
(T, 30, 3) |
世界坐标系中的刚体位置,单位米 |
fps |
标量或单元素数组 | 原始帧率 |
30 个刚体必须按 src/datasets/g1_amass_utils.py 中定义的顺序排列,pelvis 在首位;Isaac Lab 的刚体顺序不同,要先重排。
注意 轨迹要事先处理成 30 Hz。解析器会跳过帧率与 30 Hz 相差超过 5 Hz 的文件,它不负责 120 Hz 到 30 Hz 的转换;文件名中的数字后缀也不代表帧率。仓库 docs/motion_encoder.md 提到的公开重定向数据集,使用前要核对格式是否与上表一致,只改文件名不会转换坐标和刚体顺序。
6.2 解析数据#
uv sync --locked
source .venv/bin/activate
cd PredActor/motion_encoder
python src/datasets/g1_amass_parser.py \
--input_dir ./data/g1_retargeted_amass \
--output_dir ./data/g1_amass_db \
--dataset_name amass \
--babel_dir ./data/babel_v1.0_release \
--target_fps 30本节之后的命令都在 PredActor/motion_encoder/ 中运行。解析器只收录有 BABEL 标注的动作,写出三个划分:
| 文件 | 包含的 AMASS 子集 |
|---|---|
amass_30fps_train.pt |
BioMotionLab_NTroje、Eyes_Japan_Dataset、TotalCapture、KIT、ACCAD、CMU、MPI_Limits、TCD_handMocap、EKUT |
amass_30fps_vald.pt |
HumanEva、MPI_HDM05、SFU、MPI_mosh |
amass_30fps_test.pt |
Transitions_mocap、SSM_synced |
空的划分不会保存。重新生成时换一个新的输出目录。
6.3 检查训练数据#
python - <<'PY'
from src.datasets.g1_amass import G1AMASS
dataset = G1AMASS(
datapath='./data/g1_amass_db/amass_30fps_db.pt',
split='train', use_g1=True, num_frames=60, pose_rep='xyz')
print('Dataset size:', len(dataset))
print('Sample shape:', dataset[0]['inp'].shape) # 应为 [30, 3, 60]
print('Caption:', dataset[0]['clip_text'])
PYamass_30fps_db.pt 是加载器的占位名,它会自动换成 _train.pt、_vald.pt 或 _test.pt,不需要创建这个文件。加载器把序列切成 100 帧的块,每个训练样本取其中连续 60 帧,所以短于 100 帧的序列不会产生训练样本。
6.4 运行训练#
先用 smoke 测试确认能跑通,输出放在单独的目录:
bash scripts/train_g1_xyz.sh \
--folder ./exps/g1-xyz-smoke \
--num_epochs 1 --snapshot 1 --batch_size 2 --max_steps 1smoke 只检查能否执行,不代表模型质量。数据中至少要有两个描述不同的样本,文本–动作对比损失才有意义。
正式训练(也可以不激活环境,在仓库根目录运行 uv run --locked bash PredActor/motion_encoder/scripts/train_g1_xyz.sh):
bash scripts/train_g1_xyz.sh脚本使用原始配方:训练 100 个 epoch,batch size 20,学习率 1e-4,8 层 Transformer,512 维隐空间,16 个 DataLoader 进程,每 10 个 epoch 保存一次。动作模型从随机初始化开始,CLIP 文本塔一起训练;不会加载发布的编码器。第一次运行会下载 CLIP ViT-B/32 权重。
完成后,exps/g1-model-xyz-clip/ 中有 checkpoint_0100.pth.tar、opt.yaml、training.log、TensorBoard 事件文件和 training_receipt.json。checkpoint 包含动作模型和训练后的 CLIP 权重,不含优化器状态。
6.5 用新编码器标注数据#
回到仓库根目录,把新 checkpoint 传给第 4 节的标注脚本:
uv run --locked python PredActor/collection/scripts/data_dyeing/data_dyeing.py \
motionclip.checkpoint_path=PredActor/motion_encoder/exps/g1-model-xyz-clip/checkpoint_0100.pth.tar之后按第 5 节重新训练策略。
注意 评测时输入的文本必须用标注数据时的同一个编码器编码。
resolved_config.yaml在训练开始时记下评测所用的编码器路径,默认是发布的 MotionCLIP checkpoint。用新编码器标注的数据训练时,在第 5 节的训练命令末尾加上env_runner.task_cond_providers.clip_teleop.checkpoint_path=PredActor/motion_encoder/exps/g1-model-xyz-clip/checkpoint_0100.pth.tar, 让训练输出记录新编码器的路径,2.8 节的评测命令才会加载它。