GRAIL-Min-SMPLX:GRAIL 到 SMPL-X/PHC-X 的最小适配实验计划
Material Passport
- Origin Skill:
ars-codex:academic-research-suite - Origin Workflow:
experiment-agent - Origin Mode:
plan - Origin Date: 2026-07-24
- Verification Status:
UNVERIFIED - Version Label:
code_plan_v15_single_condition_runtime_evidence - Revision Note: 保留当前左手、跨 support 主 case;将 GRAIL release 中硬编码的
right_hand与单一table实体绑定提升为由 task/motion metadata 解析的active_hand与active_support语义角色。执行前源码审计进一步冻结: tracking/critic 仍使用 GRAIL 同序 14-body semantic subset;PHC-X 153D body/hand partition按名字做非连续 gather/scatter;support stage按物理时间而非源帧号 解析;normalized action只经过一次 PHC PD affine。reward/termination 数学、 权重和阈值不变。v5 根据独立代码 review 修正两项 embodiment-conversion 预注册:contact label/center 改为复现 GRAIL postprocess 的双手5 cm几何判定;45D hand primitive 改为从 source SMPL-Xpose_hand确定性提取, 不再使用额外 hand-only IK。finger action仍由 task role选择,inactive hand恒开。 v6 又根据实现审计冻结四项容易产生静默漂移的合同:Isaac Lab 运行时 body/joint 树遍历顺序必须按名字生成 PHC↔runtime 双向置换,禁止 identity 假设;hand action/contact label使用同一物理时间最近邻索引;BPS缺失、全零、 非有限或维度漂移时 fail-fast;PHC-X checkpoint、RMS、PD affine、eval状态、 gradient和optimizer隔离在初始化及每次 optimizer step 后审计。 v7 把所有E0/runtime gate绑定到当前config audit、PHC-X checkpoint、action affine、robot USD与reference contract的SHA-256;P1还绑定E1/P0,S0绑定 E1/P0/P1。三个E0 gate schema也改为强制校验。S0/T0命令通过shell&&与preflight硬串联,任一gate非零退出时训练进程不会启动。 v8 进一步要求config/reference exact artifact key sets及source hashes,并把 config audit中的runtime paths与checkpoint、action affine、USD和reference逐项 交叉绑定。S0/T0在preflight后生成grail_minimal_runtime_config_gate_v1;训练入口在创建accelerator/environment前 重算实际Hydra config hash并复核preflight hash。静态审计A、实际训练配置B的 混用因此fail-fast。 v9 再把当前runtime config与E0冻结的resolved_config_adapted.yaml做语义 hash比较;只剔除预注册的seed、env数、headless、输出路径、wandb、gate路径、 iteration与rollout长度字段,而后两项仍由phase exact-value gate限制。GRAIL-Min 漏传runtime gate直接退出。reference contract也新增所有task-support USD的 内容hash,config中的support路径必须逐项同序匹配。 v10 使用项目实际GRAIL运行环境.envs/sonic重新转换并加载主SMPL-X USD; converter显式移除MJCF importer附加在非刚体wrapper上的多余articulation root, 只保留刚体Pelvisroot。Isaac Lab运行时审计观测到exact 52 bodies/153 revolute joints,名称集合、唯一性和canonical/runtime permutation round-trip 全部通过。E0 fail-closed preflight现为passed=true;下一门槛是E1 replay与 P0 tensor/PD parity,尚未授权或运行正式实验。 v11 根据独立review补上stage artifact的fail-closed metric schema。E1/P0/P1 不再只凭顶层schema/passed/hash被preflight接受;每个gate必须包含下文 exact required keys、预注册threshold、逐项check和raw trace hash。P0必须读取 ActionManager最终processed target与robot target,禁止只比较adapter自己的pd_target。E1显式写入frame 0,禁止直接用先increment后apply的step_replay()漏掉首帧。P1主MPJPE冻结为22个非finger SMPL-X bodies的 world-space、无root alignment误差;同时冻结frame sampling、safe-NaN/reset、 joint-limit和持续self-collision判据。 v13 根据用户确认收敛为唯一实验条件GRAIL-Min。E0/E1/P0/P1/S0只是同一个 GRAIL-Min条件进入训练前的顺序验证gate,不是额外模型或实验组。P1只在 GRAIL-Min原生200/50 Hzruntime中以zero residual验证frozen PHC-X, 使用预注册绝对tracking门槛,不再依赖第二rollout。 v14进一步固定实验单位:最终结果表只能有一行GRAIL-Min;E0/E1/P0/P1/S0 只形成这行结果的内部证据链,T0/T1只是在完全相同条件下运行不同seed。 stage/preflight/runtime-config新增当前关键源码的exact SHA-256映射,旧gate在 adaptation、runner、validator或训练入口变化后必须失效。 v15把“一个条件”进一步落实到执行和报告:gate名仅表示同一GRAIL-Min实例的 资格检查,不保留任何已废弃control的执行合同。对抗审查证明早期raw trace可被 同源复制或全合成数据绕过,因此正式runner前新增独立canonical 50 Hz reference、 checkpoint/RMS/PD affine绑定、USD hard-limit绑定、逐sensor contact时间戳以及 P1真实closed-loop transition证据;无法由runtime直接证明的检查一律fail closed。 - Supersedes:
grail_pulsex_adaptation_plan_20260724.md的 PULSE-X/B3-G 设计 - Primary Upstream:
submodules/GRAIL/imports/SONIC/gear_sonic/config/exp/manager/universal_token/hoi/pnp_table.yamlsubmodules/PHC/output/HumanoidIm/phc_x_pnn/Humanoid.pthsubmodules/PHC/output/HumanoidIm/phc_x_pnn/.hydra/config.yamlsubmodules/Omnigrasp/phc/data/assets/mjcf/smplx_humanoid.xml
UNVERIFIED 表示本文仍不是完成报告。minimal adaptation、reference converter
和 CPU contract tests 已实现;60项定向测试和 composed-config allowlist audit
已经通过。Isaac replay、PHC-X parity、closed-loop gate、smoke和训练效果仍需
按本文门槛实际测量。v5/v6 的 contact/primitive/mapping 修订发生
在任何训练或 outcome inspection 前,原因是与一手 GRAIL postprocess 和 source
SMPL-X 数据合同对齐,不是基于结果调参。
当前静态执行状态(2026-07-24):
- config auditor枚举两份 composed config 的全部97个 leaf differences; 97/97均命中显式 allowlist,unexpected diff为0;新增的1项只是null runtime-config gate path,不改变policy或环境语义;
- PHC canonical action partition、任意 Isaac runtime permutation round-trip、 task roles、reference conversion、统一重采样、frozen adapter和fail-closed preflight/runtime-config hash chain共60项测试通过;
- 真实
phc_x_pnn/Humanoid.pth已在CPU加载:真实RMS/primitive-0 PNN完成2×2026 → 2×153,normalized action与PD target均finite、trainable parameter count为0;结果见e0/phcx_checkpoint_static_gate.json。这仍不是P0 tensor parity; - reference/object/BPS/primitive/scene/task-role artifacts已生成; 两个实际加载的task-support USD也已进入reference SHA-256 contract;
- 主
robot_motion_humanoid.usd已由修正后的converter重新生成:临时MJCF删除 world geom/light、要求唯一Pelvisroot、把超出±180°的关节范围钳到 官方PHC USD行为,并删除importer在非刚体wrapper上生成的多余articulation root; .envs/sonic中的Isaac LabArticulation已实际加载该USD:exact 52 bodies/153 revolute joints,body/joint exact-set、unique和permutation round-trip六项均通过;USD SHA-256为8cabafb45f29aeac5299b18bccd2a21e267bdb01b0a047418d4b5005f495cf6f;- 先前的fail-closed
e0/preflight.json已把config/checkpoint/USD/reference 四者联结并通过;由于v15继续修改critical source并新增canonical reference与 USD hard-limit证据,该旧E0 artifact按设计已经失效。完成本轮实现后必须重新生成 reference/USD audit并重跑E0;旧的passed=true不得继续使用。 T0前必须使用--phase train并分别提供--e1-audit/--p0-audit/--p1-audit/--s0-audit。当前工具只已实现 exact key/threshold/type、上游hash、关键源码hash和阶段prerequisite hash联结; 第一版raw trace validator虽然能复算shape、threshold和内部一致性,但独立 adversarial review已构造出不启动Isaac/PHC、仅靠同源复制的全合成E1/P0/P1 伪阳性。v15 hardening及专用runner因此仍是E1前的阻断工程项;review复验通过前 不得把任何gate记为GO,也不得进入S0/T0。 - S0/T0 Hydra override已做compose-only核验,并已实现训练入口内的hash复核:
S0解析为
2 envs / 1 iteration / 24 steps / wandb=false;T0解析为4096 envs / 20000 iterations / 24 steps / wandb=true,两者均选择pnp_table_smplx_phcx_minimal、phcxaction transform和65D meta action。
1. 决策摘要
本轮只实现一个实验条件:
GRAIL-Min-SMPLX = 以原版 GRAIL
pnp_table为算法母配置,把 G1 embodiment 换成 SMPL-X、把 frozen SONIC controller 换成 frozen PHC-X,并把 release config 中固定的right_hand/table实体绑定改成 task-drivenactive_hand/active_support语义角色。除 checkpoint/embodiment 接口和 task-entity binding 外,observation、reward、termination、PPO 与训练日程保持不变。
必须保留:
- GRAIL 的 Isaac Lab manager runtime;
- GRAIL policy observation 的 term、顺序、坐标系、future horizon 和 corruption 开关;
- GRAIL critic observation;
- GRAIL reward 函数、term 组合、weight、kernel、threshold 和同时生效方式;
- GRAIL termination;
- GRAIL PPO、actor/critic MLP、rollout horizon、训练迭代、保存和 motion-resample 日程;
- GRAIL 的
2D左/右手 primitive、use_motion_hand_actions=true和 body/hand action 拼装方式; - GRAIL 的 target-object、support-object、mass、无 domain randomization 和初始帧采样逻辑;
- GRAIL 的 filtered
target-object↔active-hand、task-supports↔active-handcontact 语义。
本轮明确不做:
- 不使用 OmniGrasp/Strict OmniGrasp observation、reward、termination 或 PPO 配置;
- 不使用 PULSE-X、48D VAE latent、2456D observation 或 B3-G;
- 不加入 C-PAIR、point-cloud reward、额外 lift reward、curriculum、domain randomization;
- 不重新设计 GRAIL reward,不调 weight,不做新的 reward shaping;
- 不把
left/right、具体 scene object id 或具体 support id 写死在 reward、 observation、termination 或 sensor 函数中; - 不做 GRAIL 原理抽取后重写到另一套 runtime;
- 不直接比较 G1 与 SMPL-X 的绝对 reward 数值来宣称某个 embodiment 更强。
因此,本文中的“minimal”不是“只改两行路径”,而是:
- 只允许 embodiment、frozen checkpoint 接口和 task-entity role binding 所迫使的变化;
- 每个变化必须进入 allowlist;
- 任何不在 allowlist 的 resolved-config diff 都阻断训练。
2. 研究问题、假设与可声明范围
2.1 主问题
在保持 GRAIL pnp_table 的 policy/critic observation contract、
reward/termination 数学、PPO 和训练日程不变时:
把 G1/SONIC 替换为 SMPL-X/PHC-X,并把 release 中固定的
right_hand/table解析为 reference 指定的active_hand/active_support后,是否能得到一个可训练、可完成当前左手跨-support pick-and-place reference 的 GRAIL minimal adaptation?
2.2 假设
- H1 — frozen-base compatibility:PHC-X 在 GRAIL Isaac Lab runtime 中、零 residual 条件下,能先通过完整 human tracking parity gate。
- H2 — minimal residual sufficiency:在 frozen PHC-X body action 上增加 GRAIL 同尺度
0.1 × residual,足以学习 object/contact correction,而不需要改变 actor observation 或 task reward。 - H3 — semantic-role preservation:把 G1 的 anchor、ankle、active wrist/palm、thumb/index/middle 和 table-support roles 映射到 SMPL-X 与 task entities 后,原 reward/termination 数学仍具有相同语义, 且 left/right mirror case 只改变实体选择、不改变数值公式。
- H4 — config invariance:除 allowlist 外不改变 GRAIL resolved config,能把实验结果归因于 embodiment/checkpoint replacement,而不是新的 task formulation。
2.3 零假设
- PHC-X 在 GRAIL 的
200 Hz physics / 50 Hz controltime base 下无法稳定闭环; - 直接 action-space residual 不能替代 GRAIL 的 SONIC pre-quantization latent residual;
- 固定
2Dhand primitive 在 45-DOF/hand 的 SMPL-X 上不足以形成 GRAIL 所需的 8-role contact; - 相同 reward 公式作用于 52-body SMPL-X 后不能产生可用的优化尺度。
2.4 可声明范围
首轮只在当前预注册的 SMPL-X 左手、床头柜到书桌的 pick-carry-place sequence
上做 overfit/compatibility 验证。该 case 保持不变;不得为了匹配 release 中的
right_hand 常量而换成右手或单桌面数据。通过只能声明:
“GRAIL minimal-style adaptation 在该 sequence 上可执行并通过预注册 gate。”
不能声明 cross-object、cross-motion、cross-shape 或方法整体优于 GRAIL。
3. 一手证据账本
3.1 GRAIL release contract
| 源码事实 | 证据 | 状态 |
|---|---|---|
Release mother config 是 pnp_table.yaml |
GRAIL experiment config | VERIFIED_FROM_CODE |
policy observation 为 grab_43dof_policy_mf_delta_bps |
pnp_table.yaml defaults |
VERIFIED_FROM_CODE |
critic observation 为 grab_43dof_critic_mf_delta |
pnp_table.yaml defaults |
VERIFIED_FROM_CODE |
reward 为 grab_rewards_no_lift_ucw,所有 terms 同时生效 |
reward composition YAML | VERIFIED_FROM_CODE |
actor 输出 64D residual + 2D hand primitive |
meta_action_dim=66, tokenizer_action_dim=64, hand_action_dim=2 |
VERIFIED_FROM_CODE |
residual 在 action-transform 内以 pre_quantization、scale 0.1 注入 |
config 与 ManagerEnvWrapper.step |
VERIFIED_FROM_CODE |
use_motion_hand_actions=true 会用 motion 的 hand_action_left/right 覆盖 policy 的最后 2D |
ManagerEnvWrapper.step |
VERIFIED_FROM_CODE |
| hand primitive 再被转换为固定 finger joint targets,最后与 body action 按 joint indices 拼装 | ManagerEnvWrapper._convert_primitive_to_finger_actions 与 step |
VERIFIED_FROM_CODE |
release pnp_table 把 contact sensor links、grasp hand、finger-direction links 和 approach wrist 固定为右手 |
pnp_table.yaml 与 rewards.py |
VERIFIED_FROM_CODE |
reward_grasp 的数学是 clamp(contact_count / min_contacts, 1),再乘指定 hand 的 reference contact label |
rewards.py::reward_grasp |
VERIFIED_FROM_CODE |
reward_grasp_finger_direction 同时依赖指定 hand 的 contact label、contact center 和 thumb/index/middle links |
rewards.py::reward_grasp_finger_direction |
VERIFIED_FROM_CODE |
actor/critic MLP 均为 [512,256,128]、SiLU、无 RNN |
hoi_staged_mlp_aux.yaml |
VERIFIED_FROM_CODE |
latent L2 为 mean(residual ** 2) |
LatentL2Loss |
VERIFIED_FROM_CODE |
physics dt=0.005、decimation 4,即 200 Hz / 50 Hz |
manager_env/base_env.yaml |
VERIFIED_FROM_CODE |
PPO 为 horizon 24、4096 env、20000 iterations |
ppo_im_phc.yaml 与 pnp_table.yaml |
VERIFIED_FROM_CODE |
| 无 observation corruption、无 motion/object pose randomization | pnp_table.yaml |
VERIFIED_FROM_CODE |
3.2 PHC-X checkpoint contract
| 源码事实 | 证据 | 状态 |
|---|---|---|
checkpoint path 为 submodules/PHC/output/HumanoidIm/phc_x_pnn/Humanoid.pth |
本地 artifact | VERIFIED_LOCAL |
checkpoint size 580969013 bytes |
filesystem stat | VERIFIED_LOCAL |
checkpoint SHA-256 3a9f7c410e79df28f66308e4226086adeab7be56dd17fff5ab4ef39b0565b03d |
local hash | VERIFIED_LOCAL |
frozen input 为 2026D = 778D self + 1248D imitation |
已有 PHC-X loader contract 与 PHC observation functions | VERIFIED_FROM_CODE |
checkpoint normalizer 后执行 [-5,5] clamp |
FrozenPHCXBackbone.forward |
VERIFIED_FROM_CODE |
PNN 输出 153D normalized action,并 clamp 到 [-1,1] |
checkpoint loader | VERIFIED_FROM_CODE |
checkpoint 为 num_prim=3, primitive index=0, has_lateral=false, activation silu |
PHC-X saved Hydra config | VERIFIED_FROM_CODE |
native PHC-X 使用 60 Hz physics / 30 Hz control |
saved Hydra config controlFrequencyInv=2 |
VERIFIED_FROM_CODE |
checkpoint 没有暴露 SONIC 的 64D pre-quant latent + decoder 接口 |
checkpoint loader/API audit | VERIFIED_FROM_CODE |
| PHC 已有 Isaac Lab evaluation prototype,可构造 PHC observation、加载 PNN 并施加 PD target | submodules/PHC/scripts/eval_in_isaaclab.py |
VERIFIED_FROM_CODE |
3.3 SMPL-X embodiment contract
| 源码事实 | 证据 | 状态 |
|---|---|---|
| asset 有 52 bodies、51 个 3-axis joints、153 action axes | smplx_humanoid.xml |
VERIFIED_FROM_CODE |
非手部为 21 joints × 3 = 63D |
body-name inventory | VERIFIED_FROM_CODE |
双手为 30 finger joints × 3 = 90D |
body-name inventory | VERIFIED_FROM_CODE |
PHC-X canonical body/joint ordering可由 SMPLH_MUJOCO_NAMES 与 x/y/z 轴生成 |
PHC Isaac Lab evaluation script | VERIFIED_FROM_CODE |
PHC-X normalized action 必须使用 PHC _build_pd_action_offset_scale 语义转换为 PD target |
PHC humanoid task | VERIFIED_FROM_CODE |
3.4 当前 task/reference contract
| 源码事实 | 证据 | 状态 |
|---|---|---|
| 当前任务为左手 cup pick-and-place | task_plan_left.json |
VERIFIED_LOCAL |
target object 为 room_e8121c03_cupnightstanda_5578c869;其 layout place_id 把 source support 解析为 room_e8121c03_nightstand_022f8481,place step/expected contact 把 destination support 解析为 room_e8121c03_desk_aadfdf70 |
task plan 与 layout | VERIFIED_LOCAL |
motion.npz 有 597 帧、22-body motion、90D hand pose 和 object trajectory |
NPZ schema audit | VERIFIED_LOCAL |
motion.npz 本身没有 GRAIL 所需的 hand_action_left/right、object_in_contact_left/right、contact-center、BPS 和 active-support arrays |
NPZ schema audit | VERIFIED_LOCAL |
task plan/manifest 有 active_hands、pick/carry/place 语义和 expected-contact intervals,可作为确定性转换输入;这些字段不是原始物理 contact labels |
task plan 与 pipeline manifest | VERIFIED_LOCAL |
3.5 复现 hashes
| Artifact | SHA-256 |
|---|---|
GRAIL pnp_table.yaml |
902a784298381eed3c559e0f59b8603dd15c64c48811540483f853aa664b0362 |
GRAIL manager_env_wrapper.py |
5d1122a49a7a151d11433f2d77bd393e5ba3ffce3748f690b46dc8fb3afa52c0 |
GRAIL rewards.py |
b1d8929251c893c15e57b23b990f2caab48a476044e8f820dea3c4139ce364d5 |
GRAIL observations.py |
d117043878ede58a4d606ff34b9d2c73acccfb0756cdb55889d0f56d1a5704b7 |
| GRAIL policy observation YAML | c2cb69cd5c0d06d4bd113bb692630c4cad6a6582ddaf352609f04261411e3416 |
| GRAIL critic observation YAML | 04a91dd154151f9b82fd22a488c8232135de8fec52934263e7a7ff4060339db7 |
| PHC-X checkpoint | 3a9f7c410e79df28f66308e4226086adeab7be56dd17fff5ab4ef39b0565b03d |
| PHC-X saved Hydra config | 9e2ae4fcfe623129d5b1930d07094f05364e80b040772fa3fbc3f152b3f53578 |
| PHC authoritative SMPL-X MJCF | fc0d15deacaa32d3dfd4de33f503f8d2fed51b83984f88c45fdcd8620eb0576c |
| PHC Isaac Lab SMPL-X USD | 199c15de7809b470eec124680f963ef18770131243dccf8cfbb842a80141511a |
| PHC SMPL-X PD affine | f238c759e68ae77cc92b0b6baed8d77fd53ee740d9913e61bedb45802c7a5635 |
| OmniGrasp SMPL-X MJCF(仅差异审计,不作为运行资产) | 961eb97f7b0e41028f504c5ac75e97b3a48edde132167c148e2ac8b669db08a9 |
| v20 source motion | 98b5f079eb54e6c404453992650e6f2b67d4d59c1d1ac5925aa9dedcad1cc622 |
| task plan | a7e3c2a8765bf9b180f996297122360cd72948beef9fa9c230223c8f7362c74b |
| layout JSON | 24c2c28c5bdb64523a42c5cb93ddd80fde8e92fffdcb27f804f55977352d7b1a |
GRAIL submodule 当前不能从内部 HEAD 可靠取得 revision;执行时必须同时记录父仓库 gitlink、工作树 diff 和上述文件 hashes,不能只写一个未经验证的 commit id。
4. 不变量与差异白名单
4.1 必须 bit-for-bit/值相等的 resolved config
以下项目相对原 pnp_table.yaml 必须保持一致:
num_envs=4096env_spacing=10.0replicate_physics=falseobject_is_dynamic=trueobject_mass=0.1- plane、scene pose convention 和 support collision material语义
sim_dt=0.005decimation=4- actor/critic history length
10 num_future_frames=10dt_future_ref_frames=0.1sample_before_contact=truesample_from_n_initial_frames=30use_paired_motions=true- pose、velocity、joint、object randomization 均为零/false
- policy/critic observation term 名、顺序、noise enable 状态
- reward term 集合、函数、weight、std、threshold
- termination term 集合与 threshold
- PPO、actor/critic network、optimizer 和 schedule
- save frequency
500 - motion resample frequency
250
4.2 唯一允许变化
| 类别 | GRAIL 原值 | GRAIL-Min-SMPLX | 理由 |
|---|---|---|---|
| robot asset | G1 43DOF | SMPL-X 153DOF | 用户指定 embodiment |
| reference body/joint names | G1 names | SMPL-X names | index/semantic mapping |
| body action dimension | 29 | 63 | SMPL-X 非手部轴数 |
| hand target dimension | 14 | 90 | SMPL-X 手部轴数 |
| residual dimension | 64 latent | 63 normalized body action | PHC-X 无 SONIC latent API |
| total meta action | 66 | 65 = 63 + 2 | residual dimension change,2D primitive 保留 |
| frozen checkpoint | SONIC ATM | PHC-X PNN | 用户指定 checkpoint |
| frozen checkpoint input | tokenizer + proprio history | PHC-X 2026D checkpoint observation | checkpoint 必需接口;不进入 actor policy obs |
| residual insertion | SONIC pre-quant latent | PHC-X normalized body action | checkpoint 必需接口 |
| full-latent buffer | SONIC decoder input 64D | final normalized PHC-X body control 63D | 最接近的 controller-input 对应物 |
| motion body DOF | 29 | 63 | SMPL-X non-hand reference |
| hand default/primitive target | 14 | 90 | SMPL-X hand |
| active-hand binding | release 常量 right_hand |
active_hand[motion_id],当前 case 解析为 left_hand |
消除 task-side hardcode;reward 数学不变 |
| table/support binding | release 单一 table actor |
task metadata 驱动的 active_support[frame];当前 case 为床头柜→书桌 |
保持单一9D support observation channel,不写死 scene id |
| support collision scope | 单一 table | task 声明的 source/destination support set | 把原 table 碰撞语义等价推广到当前跨-support task |
| contact/body/EE link names | G1 links | 固定 SMPL-X role map | reward/termination index 映射 |
| robot PD/limits/order | G1 controller | PHC-X SMPL-X controller contract | checkpoint 稳定性所需 |
4.3 禁止变化
下列任一差异出现即停止:
- actor policy 改看 PHC-X 2026D observation;
- 删除 GRAIL BPS、object/table delta、future command 或 force observations;
- 把当前 case 替换成右手或单桌面 sequence 来规避实体绑定实现;
- 在 reward/observation/termination 中写死
left_hand、right_hand、床头柜、 书桌或任一 layout object id; - 加入 point cloud、target-attributed contact、lift/hold reward;
- 改 contact threshold
0.1 N、min_contacts=8; - 改 object termination
0.1 m; - 改 residual scale
0.1或加入tanh; - 改为 30 Hz 主训练;
- 改 reward weight、PPO budget、network width、activation;
- 启用 noise/domain randomization/curriculum;
- 用 OmniGrasp/ResMimic observation 或 reward;
- 把 failed parity 当成理由直接继续 PPO。
5. G1→SMPL-X 语义映射
5.1 Task role resolver
新增一个窄的、无 reward 数学的 semantic-role layer。它只从 motion/task metadata 返回当前 env/frame 的实体选择:
target_object_id[env]
active_hand_id[env] # 0=left, 1=right;本轮每条 motion 内保持稳定
active_support_id[env, t] # 当前交互 support
task_support_ids[env] # source + destination support set
当前主 case 的 source-time 冻结解析如下。converter 必须显式传入并哈希化
source_fps=30,因为源 NPZ 本身没有 fps 字段:
active_hand = left
target_object = room_e8121c03_cupnightstanda_5578c869
reach+pick [0.0 s, 5.0 s):
active_support = room_e8121c03_nightstand_022f8481
carry+place [5.0 s, 19.9 s):
active_support = room_e8121c03_desk_aadfdf70
约束:
active_hand必须来自 task/motion metadata,不从文件名、object位置或 reward结果猜测;- source support 必须由 target object 的 layout
place_id解析; - destination support 必须由 place step
target_id与expected_contacts[channel=object_support].support_id交叉核对,两者不一致即失败; - 本轮只支持每条 motion 一个稳定的
left或rightactive hand;both、中途换手或缺失 hand metadata 必须 fail fast,留给后续独立 adaptation; active_support的唯一切换点来自预注册 stage boundary 的绝对秒数,不根据 simulator contact或policy行为改变;- 运行时在 50 Hz 由秒数解析,因此本 case 切换 step 是 250,不得把 source frame 150 直接硬编码到 runtime;
- 当前 support 切换规则和 source/destination ids 写入
task_role_contract.json; - role resolver 不得读取 reward、termination、训练 epoch 或 policy output。
5.2 Joint partition
SMPL-X joint order必须从 PHC canonical body order生成,不能依赖 USD 偶然枚举顺序:
phcx_joint_order =
[f"{body}_{axis}"
for body in SMPLH_MUJOCO_NAMES[1:]
for axis in ("x", "y", "z")]
非手部 63D bodies:
L_Hip, L_Knee, L_Ankle, L_Toe,
R_Hip, R_Knee, R_Ankle, R_Toe,
Torso, Spine, Chest, Neck, Head,
L_Thorax, L_Shoulder, L_Elbow, L_Wrist,
R_Thorax, R_Shoulder, R_Elbow, R_Wrist
手部 90D bodies:左右手各自的
启动时必须断言:
- body indices 数量
63; - hand indices 数量
90; - union 数量
153; - intersection 为空;
- PHC canonical→Isaac Lab 和 Isaac Lab→PHC canonical 均为双射;
- action、joint state、reference 使用同一份保存下来的 ordered-name artifact。
不能把上面的 canonical顺序直接当作 Isaac Lab array顺序。USD被Isaac Articulation加载后,body/joint通常按树的广度优先顺序暴露。运行时必须由精确 名称生成:
canonical_to_runtime = [runtime_names.index(name) for name in canonical_names]
runtime_from_canonical = [canonical_names.index(name) for name in runtime_names]
motion library先用 runtime_from_canonical 把 canonical reference排成
simulator顺序;PHC-X observation/action再用 canonical_to_runtime gather/scatter。
两组置换都必须逐项 round-trip,任何缺失、重复、extra name均 fail-fast。
静态 range(153) / range(52) identity mapping只表示 canonical self-map,
不得用于实际 articulation。
5.3 Body/reward role map
GRAIL release 的 tracking reward、termination reference 与 critic body terms 并不对 52 bodies 求均值,而是使用以下同序 14-body semantic subset。SMPL-X 必须保持数量、顺序和 reduction denominator 不变:
Pelvis,
L_Hip, L_Knee, L_Ankle,
R_Hip, R_Knee, R_Ankle,
Torso,
L_Shoulder, L_Elbow, L_Wrist,
R_Shoulder, R_Elbow, R_Wrist
因此 critic 的 body_pos 仍为 14×3=42D,body_ori 仍为
14×6=84D。52 bodies 只用于 PHC-X checkpoint 的 2026D internal
observation,不进入 GRAIL tracking reduction。
| GRAIL role | G1 | SMPL-X |
|---|---|---|
| anchor/root | pelvis |
Pelvis |
| left ankle | left_ankle_roll_link |
L_Ankle |
| right ankle | right_ankle_roll_link |
R_Ankle |
| left wrist EE | left_wrist_yaw_link |
L_Wrist |
| right wrist EE | right_wrist_yaw_link |
R_Wrist |
| upright torso | torso_link |
Torso |
| active palm proxy | right_hand_palm_link |
select(L_Wrist, R_Wrist, active_hand_id) |
| active thumb distal | right_hand_thumb_2_link |
select(L_Thumb3, R_Thumb3, active_hand_id) |
| active index distal | right_hand_index_1_link |
select(L_Index2, R_Index2, active_hand_id) |
| active middle distal | right_hand_middle_1_link |
select(L_Middle2, R_Middle2, active_hand_id) |
| table/support | table |
active_support_id[env, t] |
Wrist 作为 palm proxy 是 SMPL-X 没有独立 palm rigid body 时的明确近似,必须进入 metadata;不能静默声称它与 G1 palm 几何等价。
左右两套 object_to_hand_frame_links 都固定为
Thumb3/Index2/Middle2;运行时按 active_hand_id 做 per-env select,保持 GRAIL
用三点定义 hand-object transform 的方式和9D输出不变。
5.4 Exact active-hand 8-role contact map
原 GRAIL pnp_table 使用8个右手 sensor links并设置 min_contacts=8。这里把
“右手”提升为“active hand”,但不改变8个槽、槽顺序、force vector或
min_contacts:
| Slot | G1 release role | SMPL-X canonical active-hand body |
|---|---|---|
| 0 | palm | Wrist |
| 1 | thumb proximal | Thumb1 |
| 2 | thumb middle | Thumb2 |
| 3 | thumb distal | Thumb3 |
| 4 | index proximal | Index1 |
| 5 | index distal | Index2 |
| 6 | middle proximal | Middle1 |
| 7 | middle distal | Middle2 |
必须同时实例化左右两套固定槽:
left: L_Wrist, L_Thumb1, L_Thumb2, L_Thumb3,
L_Index1, L_Index2, L_Middle1, L_Middle2
right: R_Wrist, R_Thumb1, R_Thumb2, R_Thumb3,
R_Index1, R_Index2, R_Middle1, R_Middle2
必须保持 filtered pair-force 语义:
object_to_left_hand_contact_sensor与object_to_right_hand_contact_sensor分别跟踪 target object ↔ 对应8 bodies;- observation/reward按
active_hand_id选择一套,flatten后仍为24D; supports_to_left_hand_contact_sensor与supports_to_right_hand_contact_sensor跟踪 task-declared source/destination supports ↔ broad hand collision bodies;table_pos_b/table_ori_b只读取active_support_id;support penalty/termination 对task_support_ids中任一 support 的 active-hand接触生效;- G1 的三个串联 wrist links 和 palm 在 SMPL-X 中合并为唯一
Wristproxy, 不通过重复 filter path伪造 slots; - 不得用 aggregate net force 替代;
- 不得把 support/table contact 计入 object grasp reward。
support-collision 与 object-grasp 是两套不同 link contract。GRAIL release 的
support sensor 是 11 个 broad links,不能错误复用上面的 8 grasp slots。
SMPL-X 没有独立 palm 及三段 wrist rigid bodies,因此使用每侧
Wrist + 15 finger bodies 的完整 physical-hand broad set,并把
11→16 记为 embodiment 必需、可审计的近似;reduction、clamp 与 threshold
仍逐字保留。不得用 aggregate net force 代替 filtered pair force。
5.5 Hand primitive
保留 GRAIL 两个 scalar:
并保留:
SMPL-X 每只手需要固定的 normalized open_45d 和 closed_45d:
- 从 source SMPL-X
pose_hand[:,90]读取双手 axis-angle,禁止另做 IK 或 用训练 reward反推 pose; q_open_90d为 source 前min(30,T)帧逐维 median;- 在 active-hand GRAIL-style geometric-contact frames 内,选与
q_open_activeaxis-angle L2 距离最大的 source frame作为q_closed_active_45d; - 当前 single-active-hand motion没有独立 inactive-hand closed demonstration,
因此以 axis-angle
[x,y,z]→[x,-y,-z]镜像 active closed pose生成 inactive closed pose;这是必须披露且后续可被真实双手数据替代的 embodiment-conversion fallback,不影响 inactive hand在本 case恒开; - 用 PHC-X PD affine把
q_open/q_closed转成 normalized 90D primitive, 并验证 shape、joint name/order、finite、[-1,1]和 round-trip; - 两组 normalized向量写入
primitive_open_closed.json,记录 source frame、 derivation、input/output hashes; - E1 replay必须检查 joint limits、自碰撞、open/closed fingertip geometry以及 active primitive不会造成即刻非任务碰撞;任一失败即停止,不以调 reward修复。
本轮不增加第三个 primitive,不改成 continuous hand policy,不让 PHC-X 的 90D finger action绕过 GRAIL primitive。
hand_action_left/right 都必须存在;双手几何 contact arrays均保留,但 finger
action只由 task_roles.active_hand 对应的几何 contact timeline驱动,inactive
hand固定为 open。这样既不在 wrapper 中写死当前 case 为左手,也不会让非任务手
偶然进入 5 cm 阈值时错误闭合。
6. Observation contract
6.1 Actor policy observation
term 顺序严格保留:
commandmotion_anchor_pos_bmotion_anchor_ori_bbase_lin_velbase_ang_veljoint_posjoint_velactionstarget_object_poshand_object_transform_6dfinger_tips_forceobject_pos_bobject_ori_b_6dtable_pos_btable_ori_bobject_pos_delta_multi_futureobject_ori_delta_multi_future_6dcommand_multi_futuremotion_anchor_ori_b_mfobject_bps
只允许下列 shape 变化:
command: G1 body29 pos + 29 vel→ SMPL-X body63 pos + 63 vel;joint_pos/joint_vel/actions:43D→153D;hand_object_transform_6d: 左右各按对应三点计算,再由active_hand_idper-env选择,输出仍为9D;finger_tips_force: 左右各计算8-role × 3-axis filtered pair force,再由active_hand_idper-env选择,输出仍为24D;table_pos_b/table_ori_b: 从固定tableactor改读active_support_id[env,t],输出仍为3D+6D;- body/future command 中的 joint/body维度按 SMPL-X 扩展。
以下内容不变:
- term 顺序;
- local/world/body frame 定义;
- quaternion/6D rotation representation;
- target-object/support term公式与维数;
- future count
10; - object future
dt=0.1; - BPS
10D; enable_corruption=false。
6.2 Critic observation
critic 保持 actor 对应 terms,并保留 GRAIL privileged:
body_posbody_origrab_contact_flag,但读取 active hand 的 reference label
tracked body 数量保持 14,只把 joint/action 数量改为 153;不加入 PHC-X critic state。
6.3 Frozen checkpoint observation
PHC-X 的 2026D observation 是 action-transform 内部输入,不是 GRAIL actor observation。
数据流必须为:
GRAIL actor obs (SMPL-X-shaped) ──► residual actor ──► 63D residual + 2D primitive
SMPL-X sim state + human reference
──► PHC-X self/imitation builder
──► checkpoint RMS
──► clip [-5, 5]
──► frozen PHC-X PNN
──► 153D normalized base action
禁止把 2026D 拼到 GRAIL actor observation 中。
6.4 Schema gate
每次启动保存:
policy_observation_schema.jsoncritic_observation_schema.jsonphcx_observation_schema.json
每个 schema 至少含:
- ordered term names;
- per-term shape;
- flattened offsets;
- dtype;
- frame/representation 标签;
- source function;
- semantic role source(
target_object/active_hand/active_support); - resolved config hash。
schema 与预注册 snapshot 不一致时必须 fail fast。
7. Action-transform contract
7.1 唯一可执行定义
因为 PHC-X 没有 SONIC 64D latent encoder/decoder,不能伪造“只换 checkpoint 路径”。本轮采用最接近 GRAIL action flow 的接口:
a_phcx_153 = FrozenPHCX(obs_phcx_2026)
a_base_63 = gather_non_hand(a_phcx_153)
delta_63 = policy_output[:63]
a_body_63 = clip(a_base_63 + 0.1 * delta_63, -1, 1)
h_left, h_right = motion hand actions # override policy last 2D, same as GRAIL
a_hand_90 = finger_primitive(h_left, h_right)
a_env_153 = scatter(a_body_63, a_hand_90)
ActionManager(a_env_153):
q_target_153 = phcx_pd_offset + phcx_pd_scale * a_env_153
约束:
- residual scale 精确为
0.1; - 不加入
tanh; - PHC-X parameters、RMS 全部 frozen 且
eval(); - primitive index 固定
0; - base action先按 PHC canonical order生成,再显式 gather/scatter 到 Isaac Lab order;
- normalized action clip
[-1,1]; - PD offset/scale严格复现 PHC
_build_pd_action_offset_scale,包含 knee scale 特例; - wrapper/adapter只输出 normalized
a_env_153;siblingJointPositionActionCfg负责唯一一次 PHC PD affine,严禁 adapter 先生成q_target后又经过 GRAIL action scale/default offset; - hand primitive输出为 normalized hand target,再与 body action一起经过同一 PHC-X PD affine;不使用 PHC-X 的 90D hand base action。
7.2 保留 GRAIL regularization
| GRAIL term | SMPL-X translation | 数值设置 |
|---|---|---|
actor aux latent_l2 |
mean(delta_63²),仍作用于 policy residual |
coefficient 0.1 |
meta_action_rate_l2 |
原函数作用于 65D = 63 residual + 2 primitive raw policy output |
weight -0.1 |
full_latent_rate_l2 |
原函数作用于 a_body_63,即 frozen base + scaled residual 的最终 normalized controller input |
weight -0.01 |
第三项不再是 FSQ latent;它是 checkpoint-interface replacement 中不可避免的语义对应。函数、L2-squared reduction 和 weight 保持不变,但报告必须称为“full controller-input rate”,不能误称 PHC-X latent rate。
7.3 Frozen gate
训练时每个 optimizer step 后断言:
- PHC-X parameter grad 全为
None; - checkpoint parameter hash抽样不变;
- RMS 不更新;
- PNN 保持 eval mode;
- optimizer parameter groups 不含 PHC-X parameter。
8. Reward 与 termination contract
8.1 Reward 不变表
| Term | Function | Resolved weight | 关键参数 |
|---|---|---|---|
| anchor position | tracking_anchor_pos_error |
0.5 |
std 0.3 |
| anchor orientation | tracking_anchor_ori_error |
2.5 |
std 0.4 |
| relative body position | tracking_relative_body_pos_error |
1.0 |
std 0.3 |
| relative body orientation | tracking_relative_body_ori_error |
5.0 |
std 0.4 |
| body linear velocity | tracking_body_linvel_error |
1.0 |
std 1.0 |
| body angular velocity | tracking_body_angvel_error |
1.0 |
std 3.14 |
| undesired contacts | undesired_contacts |
-0.1 |
threshold 1.0 N |
| active-hand/support contact | reward_hand_table_contact_penalty 的 role-aware binding |
-1.0 |
task-support filtered pair force |
| active-hand grasp | reward_grasp 的 role-aware binding |
5.0 |
threshold 0.1 N, min 8, contact-label gated |
| active-hand finger direction | reward_grasp_finger_direction 的 role-aware binding |
10.0 |
active contact center enabled |
| finger primitive limit | 原函数 | 0.0 |
discrete |
| meta action rate | meta_action_rate_l2 |
-0.1 |
unchanged reduction |
| full controller input rate | full_latent_rate_l2 |
-0.01 |
unchanged reduction |
| termination | Isaac Lab is_terminated |
-10.0 |
unchanged |
| object tracking | object_tracking_reward |
0.0 |
保留但不参与总 reward |
| active-wrist approach velocity | reward_approach_velocity_penalty 的 role-aware binding |
-15.0 |
sigma 0.25, threshold 0.1, min contacts 8, disable-after-contact false |
| upright | upright_penalty |
0.0 |
Pelvis, Torso |
所有 body tracking 函数仍对当前 tracked-body集合求 mean;SMPL-X 的 tracked-body集合保持第 5.3 节同序 14 bodies。不得改成 canonical 52 bodies, 也不得再乘任何 action/body-count 修正系数。
8.2 只做 name/index/role conversion
role-aware reward必须实现成先选择实体、再执行原公式:
active_force = where(active_hand_id == left, force_left_8x3, force_right_8x3)
active_label = where(active_hand_id == left, label_left, label_right)
contact_count = sum(norm(active_force, axis=-1) > 0.1)
grasp_reward = clamp(contact_count / 8, max=1) * active_label
support_force = filtered_pair_force(task_support_ids, active_hand_id)
support_contact_penalty = clamp(
sum(norm(support_force, axis=-1), over=support_and_hand_slots),
max=1.0,
)
support_contact_termination = (
sum(norm(support_force, axis=-1), over=support_and_hand_slots) > 1.0
)
不得为左右手分别设置不同 reward、weight、threshold 或 normalization。支持 left/right motions 同 batch 时,选择必须逐 env 执行,不能用一个全局 config 字符串替代。
上述 support 推广在单 support 时必须退化为 release 的逐项范数求和、clamp(1.0)
和 >1.0 N 原公式;多 support 时只扩展 filtered-pair 的实体集合,不改变
reduction、clamp或 threshold。为保持 config diff 最小,公开 term/function 名
仍保留 table_pos_b、table_ori_b、reward_hand_table_contact_penalty 和
hand_table_contact_termination;其中 table 仅作为兼容名称,运行时实体不得
从名称推断,必须由 role contract 解析。
- anchor:
pelvis → Pelvis - undesired-contact allowlist:两侧 ankles + 双手 30 个 finger bodies +
双侧
Wristpalm proxy。GRAIL 在 G1 上能区分 palm 与三段 wrist,而 SMPL-X 将它们合并;为了让 active side 能把 Wrist 用作 palm,左右必须静态同规则, 不得让 inactive wrist采用另一套 reward; - grasp hand:release
right_hand常量 → per-envactive_hand_id; - hand-object transform:左右
Thumb3/Index2/Middle2都计算,再选择 active side; - finger direction:左右
Thumb3/Index2/Middle2都可用,再选择 active side; - approach wrist:左右
Wrist速度都可用,再选择 active side; - contact center与 in-contact label按 active side选择;
table_pos_b/table_ori_b按active_support_id[env,t]选择;- support contact penalty对
task_support_ids集合中任一 support生效; - 8-role contact sensor按第 5.4 节;
- upright body
pelvis/torso_link → Pelvis/Torso,weight仍为零。
left/right mirror unit test在镜像 state、相同 contact count/label下必须产生相同
grasp、finger-direction和approach reward(浮点 tolerance 1e-6)。inactive-hand
接触不得计入 active grasp。
8.3 Termination 不变
| Term | 原阈值 | SMPL-X conversion |
|---|---|---|
| anchor position | 0.25 m, down 0.5 m |
anchor Pelvis |
| anchor orientation | 1 rad |
anchor Pelvis |
| EE position | 0.25 m, down 0.5 m |
L/R_Ankle, L/R_Wrist |
| motion timeout | reference end | 不变 |
| object position deviation | 0.1 m |
不变 |
| hand-support termination(保留 release term 名) | 1.0 N |
active SMPL-X hand ↔ 任一 task support filtered links |
不得使用当前 PhysHSI 其他实验中的 0.5 m object ET。
8.4 PPO/network lock
| Setting | Value |
|---|---|
| actor/critic hidden dims | [512,256,128] |
| activation | SiLU |
| PPO learning epochs | 5 |
| mini batches | 4 |
| clip | 0.2 |
| gamma / lambda | 0.99 / 0.95 |
| value loss coefficient | 1.0 |
| entropy coefficient | 0.01 |
| actor / critic learning rate | 2e-5 / 1e-3 |
| max grad norm | 0.1 |
| desired KL | 0.01 |
| adaptive LR bounds | [1e-5,2e-4] |
| initial action noise std | 0.05 |
| learned std clamp | [0.001,0.5] |
| actor residual L2 coefficient | 0.1 |
不得因 SMPL-X action维度变大而改 hidden width、learning rate、entropy或 minibatch规则;若资源不足,只能减少并行 env 做 smoke,正式结果仍使用 release budget。
9. Reference conversion
9.1 Canonical input
首轮输入三件套固定为:
output/auto_experiments/20260723_cup_left_hand_object_interaction_v20/motion.npz
output/auto_experiments/20260705_hsi_generation_task_inputs/task_plan_left.json
data/selected_SAGE10k/e2e_test_scenes/2cdc81db/layout_2cdc81db.json
其冻结事实为:
- size
67511033bytes; - SHA-256
98b5f079eb54e6c404453992650e6f2b67d4d59c1d1ac5925aa9dedcad1cc622; 597source frames;- stages
[0,150) reach+pick、[150,597) carry+place; - active side
left; - dynamic object id
room_e8121c03_cupnightstanda_5578c869; - layout
data/selected_SAGE10k/e2e_test_scenes/2cdc81db/layout_2cdc81db.json。
转换器不优化 motion,并保留完整 source time span。它区分“source已有字段”和
“从 task/reference 确定性派生字段”,不得假装后者已存在于 motion.npz。
直接转换:
- SMPL-X root pose;
- canonical 52-body position/orientation;
- body joint position/velocity
63D; - optional hand joint pose
90D,用于 replay/parity,不替代 primitive control; - object position/orientation/velocity;
- fps、length、object identity和单位。
确定性派生并单独记录 provenance:
active_hand=left:来自 task plan 的active_hands/primary_hand,不是代码常量;active_support_id[t]:[0,150)为 layoutplace_id解析出的room_e8121c03_nightstand_022f8481,[150,597)为 place step/expected contact 共同解析出的room_e8121c03_desk_aadfdf70;task_support_ids:source/destination support ids;object_contact_points_left/right:复现 GRAILgrail/postprocessing/postprocess.py的语义,对每帧、每只手分别找与 SMPL-X hand mesh距离<0.05 m的 object-mesh vertices,并存为 object-local points;object vertices上限保持10000。若超过上限,为保证 conversion可复现,使用 deterministic index selection并记录 selection/hash; 当前 cup未触发 downsample,因此与 release selection无数值差异;object_in_contact_left/right:各手当帧 geometric-contact point集合非空时为1,否则为0;task expected-contact interval只用于 role/provenance consistency,不作为 physics/contact label;hand_action_left/right:task_roles.active_hand对应侧按上述 geometric label取+1/-1,inactive side始终-1;不得根据当前 case手侧写常量;object_contact_center_left/right:沿用 GRAIL runtime的 contact-point集合 求 mean;无点帧保持无 contact,不得退化到 object CoM;- object BPS
10D:使用冻结的 GRAIL basis和同一编码定义从 layout object geometry离线计算;basis hash必须记录,缺失时不得返回零向量继续训练; - active support position/orientation:从 layout geometry与上述 stage mapping读取。
以上派生输出写入 reference_contract.json,至少包含 source field、derivation
method、frame interval、hand/support ids、0.05 m threshold、10000 vertex
上限、selection policy、basis hash和输出 hash。expected-contact interval是
task-semantic evidence,不得在报告中称为真实 physics contact;reference
geometric contact也只能称为离线 label,真实接触仍由 simulator filtered pair
force评估。
source 中的 vertices/faces 仅可用于离线 FK/contact-center validation,不进入
GRAIL canonical motion artifact;object/support geometry由
layout_json + semantic entity ids 在 simulator consumer boundary加载。
9.2 GRAIL motion settings
motion_lib_num_dof: 63
hand_default_positions: 90D canonical open hand
num_future_frames: 10
dt_future_ref_frames: 0.1
smpl_num_future_frames: 10
smpl_dt_future_ref_frames: 0.02
use_paired_motions: true
start_from_first_frame: false
sample_before_contact: true
sample_from_n_initial_frames: 30
encoder_sample_probs 和 SONIC tokenizer encoder 选择不再参与 PHC-X action transform;不得把其数值变化解释成 policy observation 改动。
9.3 Conversion gates
- source frame count/fps必须记录;若 motion lib重采样,target frame count必须等于按声明 fps推导的值,首尾 time span误差不超过半个 target frame;
- quaternion全部单位化,约定明确;
- root/body FK position max error
< 1e-4 m; - body orientation max geodesic error
< 1e-4 rad; - joint round-trip max error
< 1e-5 rad; - object pose round-trip max error
< 1e-5 m/rad; - contact points在 object local/world frame round-trip
< 1e-5 m; - binary hand action只含
-1/+1; - 每条 motion 的
active_hand恰为一个left/right值,且与 task plan一致; - active-support transition恰好发生在声明的 stage boundary,无未声明切换;
object_in_contact_left/right精确等价于对应侧 object-local contact-point集合 非空;双侧 arrays均保留;- active-side hand action与 active-side geometric label一致,inactive-side hand action全开,即使 inactive-side geometric label偶然为1也不得闭合;
- contact-labelled frame全部有 finite object-local contact points/center,不允许 CoM fallback;
- BPS shape精确为10且不是全零,basis hash与预注册值一致;
- active-hand contact interval非空;
- object、motion、USD stem一一对应。
10. 工程修改计划
10.1 新增文件
建议以原 GRAIL config 为母本增加 sibling files,不原地改 release baseline:
submodules/GRAIL/imports/SONIC/gear_sonic/
config/exp/manager/universal_token/hoi/
pnp_table_smplx_phcx_minimal.yaml
config/manager_env/observations/policy/hoi_manip/
grab_smplx_phcx_policy_mf_delta_bps.yaml
config/manager_env/observations/critic/hoi_manip/
grab_smplx_phcx_critic_mf_delta.yaml
config/actor_critic/
hoi_staged_mlp_aux_phcx.yaml
envs/manager_env/robots/
smplx.py
envs/manager_env/
task_roles.py
envs/wrapper/
phcx_action_adapter.py
tools/
convert_smplx_motion_to_grail.py
convert_grail_smplx_mjcf_to_usd.py
audit_grail_smplx_usd.py
audit_grail_phcx_checkpoint.py
audit_grail_minimal_config.py
audit_grail_minimal_preflight.py
audit_grail_minimal_runtime_config.py
utils/tracking_adapters/grail/
reference.py
新 policy/critic YAML 只允许复制 term 列表并改说明/shape contract;不得改变 term 顺序或覆盖数值。
10.2 定点修改
| 文件 | 修改 |
|---|---|
modular_tracking_env_cfg.py |
注册 smplx_phcx robot、左右8-role object sensors、左右 task-support sensors和scene support entities |
joint_utils.py |
增加显式 SMPL-X 63/90 ordered-name partitions;保留 G1路径 |
manager_env_wrapper.py |
支持 PHC-X checkpoint format/transform initialization;其 step 的 residual、motion-hand override、primitive和scatter流程尽量不改 |
| PHC-X observation builder | 从 Isaac Lab SMPL-X state生成与 PHC native一致的 778+1248 tensor |
task_roles.py |
从 motion ids、绝对时间和冻结 metadata返回 target object、active hand、active support和support set;不包含 reward公式 |
observations.py |
hand_object_transform_6d、finger_tips_force和table terms改为逐env role selection,term名/shape/order不变 |
rewards.py |
grasp、finger direction、approach和support-contact函数先做 active-role selection,再执行原公式/weight/threshold |
terminations.py |
hand-support termination按 active hand和task support set选择,阈值仍为1N |
| motion converter | 生成 GRAIL motion-lib字段、task-role contract、contact labels/centers、hand actions和BPS |
| tests | schema、mapping、reward parity、frozen gate、smoke tests |
phcx_action_adapter.py 实现当前 action-transform 所需的窄接口,不把
OmniGrasp task引入GRAIL。它只负责:
load checkpoint
build/normalize PHC-X observation
infer 153D base action
select 63D body action
add 0.1 residual and clip
expose final 63D controller-input buffer
已实现的最小修改还包括:
commands.py在 SMPL-X 路径根据实际 articulation names构建 motion-lib 双向置换,并从active-hand contact label推导first-contact;motion_lib_base.py对 hand action与contact label使用统一最近物理时间索引, 且 adapted path强制有效非零10D BPS;ppo_trainer.py仅增加条件式 frozen audit hook;未改变 PPO更新公式或日程;manager_env_wrapper.py在PHC-X路径补 env-origin world frame、next-reference terminal clamp、一次PD affine和exact action scatter;SONIC路径保持原样。
10.3 不得复用的现有代码语义
submodules/Omnigrasp/phc/learning/resmimic_strict_phcx.py 可以作为 checkpoint loader事实参考,但 GRAIL-Min 不得复用:
2033DResMimic actor observation;- 153D full-action residual;
- point-cloud object reward;
- OmniGrasp task/termination;
- Strict target-contact extensions。
10.4 Config diff auditor
tools/audit_grail_minimal_config.py 输入:
- 原
pnp_tableresolved config; - SMPL-X/PHC-X resolved config;
- allowlist JSON。
输出:
resolved_config_base.yamlresolved_config_adapted.yamlconfig_diff.jsonunexpected_diff.jsonpassed
只要 unexpected_diff.json 非空,smoke和训练 command必须拒绝执行。
allowlist只能接受 right_hand/table concrete binding → semantic-role resolver、
SMPL-X names/shapes和PHC-X checkpoint接口;reward公式、weight、threshold、
reduction和term启用状态仍必须精确相等。
当前实现还输出 observation_schema.json、phcx_observation_schema.json 和
config_audit.json。2026-07-24审计结果为97个leaf differences、97个allowlisted、
0个unexpected;这只通过E0的config子门槛,不替代USD/runtime子门槛。
audit_grail_minimal_preflight.py 必须同时核对主USD runtime audit的input path
与sha256以及reference contract内每个runtime artifact的path/sha256;
config/checkpoint/USD三个E0 gate也必须匹配各自冻结schema,checkpoint与action
affine必须匹配当前文件hash。--phase train 强制接收并校验E1/P0/P1/S0四个
专用schema、当前五项upstream hashes与阶段依赖hash,任一缺失、schema错误、
hash不一致或 passed!=true均非零退出。
tools/audit_grail_minimal_runtime_config.py 在passed smoke/train preflight之后
重新compose精确S0/T0 Hydra config,并与E0冻结的
resolved_config_adapted.yaml比较semantic hash;只移除预注册的phase/run
overrides,reward、observation、network、environment和checkpoint paths仍参与
比较。工具写出exact config、semantic config、preflight、config-audit与frozen
resolved-config hashes。训练入口要求GRAIL-Min必须提供
grail_runtime_config_gate,并在任何accelerator、simulator或optimizer创建前
复核上述文件和实际config;不一致立即退出。该hook只做完整性检查,不进入
observation、reward、action、PPO或优化器语义。
11. 实验工作流与门槛
内部资格门 E0 — Static contract
执行:
- config resolve;
- joint/body/contact role解析;
- per-motion active hand与per-frame active support解析;
- observation schema dump;
- reward/termination resolved table dump;
- checkpoint/asset hash;
- frozen parameter audit。
通过门槛:
- unexpected config diff =
0; - joint partition
63+90=153; - exact body ids=
0..50 + 96..107、hand ids=51..95 + 108..152,禁止连续切片; - GRAIL tracked-body role map长度/顺序精确为14;
- contact slots =
8; - 当前 main case的 active hand逐env解析为left,但代码和resolved role contract 中没有硬编码 scene-specific left/right分支;
- active support只有预注册的一次 source→destination transition;
- policy/critic term顺序精确匹配母配置;
- reward/termination term、公式与数值精确匹配;
- left/right mirror reward parity max abs diff
≤1e-6。
失败:修实现,不进入 simulator。
当前结果:E0 GO。config/CPU contract子门槛通过(51 tests;97/97 config
leaf differences allowlisted);修正后的主USD由Isaac Lab实际加载,52-body、
153-joint exact-set/unique/permutation checks全部通过;e0/preflight.json
对config、checkpoint、USD、reference及主USD内容hash的联结校验为
passed=true。下一步只进入E1/P0,不得跳到P1或训练。
内部资格门 E1 — Reference replay
在无 policy 控制条件下把 converted reference 写入 SMPL-X:
- 对比 root/joint/body/object replay;
- 检查 active-hand primitive;
- 检查 object↔left/right hand 与 task-supports↔left/right hand filtered sensor pairs;
- 检查 active-hand/contact-label和active-support逐帧选择;
- 输出一条完整 sequence trace和视频。
通过门槛:
- 第 9.3 节全部成立;
- 8 个 contact slots 顺序正确;
- contact label开启区间与 reference一致;
- inactive-hand contact observation/reward不泄漏到active channel;
- support role只在声明的stage boundary切换;
- 无 NaN/Inf。
内部资格门 P0 — PHC-X tensor parity
在相同静态 state/reference batch 上,分别用:
- PHC native observation functions;
- GRAIL Isaac Lab PHC-X observation builder;
构造 checkpoint input。
通过门槛:
- pre-normalization observation max abs diff
≤ 1e-4; - normalized/clipped observation max abs diff
≤ 1e-4; - PNN action max abs diff
≤ 1e-6; - PD target max abs diff
≤ 1e-5 rad; - 比较的是 ActionManager 最终 applied joint target,确保不存在 double affine;
- ordering mismatch为零。
内部资格门 P1 — Frozen zero-residual closed loop
条件:
主 gate 使用 GRAIL 原 time base:
P1记录994个reference state之间的993个control transition。Isaac Lab先计算
termination、后推进command cursor,所以到达terminal state的第993个transition
上原版tracking_time_out仍为false;它只会在额外terminal-hold action上触发。
P1不执行该额外transition,也不修改原termination。
这是唯一GRAIL-Min条件内部的pre-training gate,不是第二个实验组。为隔离human controller,此阶段不启用object-deviation termination;其他human termination 保留。
通过门槛:
- sequence completion
100%; - 非 object human termination
0; - 22-body world-space MPJPE mean
≤0.10 m; - 22-body world-space MPJPE p95
≤0.20 m; - root position p95
< 0.25 m; - 无 NaN/Inf、joint limit explosion或持续 self-collision。
P1失败时只报告GRAIL-Min frozen-tracker gate失败并停止;不得增加另一time-base rollout来绕过,也不得靠PPO、reward shaping或curriculum掩盖controller/runtime 接口问题。
Stage artifact exact schemas
所有stage gate都必须包含以下公共exact keys,不得接受缺字段或额外的未注册字段:
schema, stage, passed, command, started_at, completed_at,
upstream_hashes, code_hashes, prerequisite_gate_hashes,
runtime, thresholds, metrics, checks, artifacts, errors
其中:
upstream_hashes必须与当前E0 preflight五项同名同值;code_hashes必须与当前E0的critical-source exact map同名同值,并在 preflight、runtime-config auditor和训练入口逐文件重算;- E1/P0的
prerequisite_gate_hashes={};P1必须精确绑定当前E1与P0 artifacts; thresholds必须等于本节冻结值,runner不能从CLI覆盖;checks必须是preflight按exact key set复算的逐项bool,passed必须等于errors=[] and all(checks.values());artifacts每项必须为{path,sha256},preflight重新计算内容hash;raw trace 不得只写在日志或wandb中。
E1 grail_minimal_e1_reference_replay_v1 的exact nested keys:
runtime:
python, torch, isa_sim, isaaclab, device,
physics_hz, control_hz, motion_key,
source_fps, source_frames, target_fps, expected_frames, audited_frames
thresholds:
root_position_max_m=1e-4
root_orientation_max_rad=1e-4
joint_position_max_rad=1e-5
body_position_max_m=1e-4
body_orientation_max_rad=1e-4
object_position_max_m=1e-5
object_orientation_max_rad=1e-5
metrics:
root_position_max_m, root_orientation_max_rad, joint_position_max_rad,
body_position_max_m, body_orientation_max_rad,
object_position_max_m, object_orientation_max_rad,
nonfinite_count, support_transition_count,
active_contact_frame_count, contact_slot_count_per_side,
replayed_frame_indices_sha256, expected_duration_s,
replayed_duration_s, duration_error_s,
sensor_timestamp_advance_count, inactive_channel_leakage_max
checks:
frame_zero_audited, full_sequence_audited, state_tolerances,
object_tolerances, finite, contact_slot_order_exact,
hand_label_interval_exact, inactive_hand_open,
active_hand_routing_exact, active_support_routing_exact,
support_transition_exact, sensor_pair_contract_exact,
sensor_timestamp_advanced, no_inactive_channel_leakage
artifacts:
reference_replay_trace, role_trace, mapping, replay_video
E1的frame index trace必须精确等于 0..T-1 且每帧只出现一次,source/target
duration差不超过半个target frame。当前reference依照MotionLib的
duration=(597-1)/30 与exclusive-end arange(0,duration,1/50) 精确得到
T=994,不是995;converted contact对应target frames 130..960(831帧),
support切换发生在frame 250。E1不能以
setup_replay_motion(...); step_replay() 作为首帧路径,因为
step_replay() 先increment再apply。runner必须在setup后显式把
_replay_time_steps=0 并调用一次frame apply/audit,再从frame 1继续。真实physics
contact force与离线5 cm geometric label分别记录;每帧teleport后必须显式刷新
physics/contact sensor,并证明sensor timestamp前进,不能把一次
sim.forward() 当作force buffer已更新的证据。hand_label_interval_exact
只比较converted label/primitive/routing,不把离线label冒充simulator force。
P0 grail_minimal_p0_phcx_tensor_parity_v1 的exact nested keys:
runtime:
python, torch, isa_sim, isaaclab, device,
sampled_frames, observation_shape, normalized_action_shape, pd_target_shape,
native_observation_function, wrapper_observation_function,
action_term_name
thresholds:
pre_normalization_max_abs=1e-4
normalized_observation_max_abs=1e-4
pnn_action_max_abs=1e-6
pd_target_max_abs_rad=1e-5
metrics:
pre_normalization_max_abs, normalized_observation_max_abs,
pnn_action_max_abs, action_manager_pd_target_max_abs_rad,
robot_joint_target_max_abs_rad, ordering_mismatch_count,
nonfinite_count
checks:
sampled_frames_exact, native_path_independent,
observation_shape_exact, normalized_shape_exact,
pre_normalization_parity, normalized_observation_parity,
pnn_action_parity, action_manager_pd_target_parity,
robot_joint_target_parity, ordering_exact, finite, frozen_digest_unchanged
artifacts:
tensor_parity_trace
sampled_frames 固定为排序去重后的
[0, contact_onset-1, contact_onset, contact_onset+1,
support_boundary-1, support_boundary, support_boundary+1, T-1],越界项先clip到
[0,T-1];当前reference的exact值为
[0,129,130,131,249,250,251,993]。native path必须直接调用PHC
observation函数与checkpoint RMS/PNN;不得调用wrapper builder生成“native”
一侧。PD比较必须同时读取
action_manager.get_term("joint_pos").processed_actions 和
robot.data.joint_pos_target,并按runtime→PHC名字置换;只比较
PHCXActionAdapter.pd_target 属于同源自检,不能通过P0。
P1 grail_minimal_p1_zero_residual_v1 的exact nested keys:
runtime:
python, torch, isa_sim, isaaclab, device,
physics_hz=200, control_hz=50, motion_key, expected_frames, completed_frames
thresholds:
mpjpe_mean_max_m=0.10
mpjpe_p95_max_m=0.20
root_position_p95_max_m=0.25
joint_limit_tolerance_rad=0.001
severe_self_collision_force_n=200
persistent_self_collision_frames=5
metrics:
mpjpe_mean_m, mpjpe_p95_m, root_position_p95_m,
nonfinite_count, human_termination_count, reset_count,
invalid_env_reset_count, joint_limit_violation_count,
joint_limit_violation_max_rad, max_abs_joint_velocity_rad_s,
persistent_self_collision_count
checks:
full_sequence_complete, no_human_termination,
mean_mpjpe_within_limit, p95_mpjpe_within_limit,
root_position_within_limit, finite, no_joint_limit_explosion,
no_persistent_self_collision, no_reset, no_invalid_recovery,
zero_body_residual,
motion_hand_primitive_enabled, frozen_digest_unchanged
artifacts:
grail_zero_residual_trace, termination_reasons
主MPJPE body set精确为:
Pelvis,
L/R_Hip, L/R_Knee, L/R_Ankle, L/R_Toe,
Torso, Spine, Chest, Neck, Head,
L/R_Thorax, L/R_Shoulder, L/R_Elbow, L/R_Wrist
共22 bodies;逐body world-space Euclidean distance,不做root alignment,
先对body求mean再对frame统计mean/p95。14-body GRAIL subset、full-52和finger
tips只作secondary metrics。P1必须禁用diagnostic harness中的safe-NaN自动恢复,
并要求 reset_count=invalid_env_reset_count=0;object-deviation termination是
唯一排除项,其他termination逐项写入 termination_reasons。
joint-limit violation定义为超出runtime hard limit超过 0.001 rad;持续严重
self-collision定义为非相邻body pair filtered force >200 N 连续至少5个control
frames。两者计数必须为0,且raw maxima进入trace,不能只写bool。
内部资格门 S0 — Two-env smoke
设置:
num_envs=2num_learning_iterations=1num_steps_per_env=24- seed
0
这只是工程 smoke,不是实验结果。检查:
- reset/step/backward/save/load;
- actor action
65D; - body/hand/env action
63/90/153D; - 两个 env 分别注入 left-active 与 right-active 的镜像 role contract,验证 per-env active-hand select,不要求当前训练集真实包含右手 sequence;
- 在 rollout 中跨过一次 source→destination boundary,验证 active-support 逐帧切换且 observation shape/order 不变;
- inactive-hand 与非 task-support 的人工 contact 不进入 active reward/termination channel;
- reward每项有限;
- PHC-X无梯度;
- checkpoint resume一致;
- evaluation callback可读取 trace。
S0 grail_minimal_s0_smoke_v1 也使用上面的公共exact top-level keys,并冻结:
runtime:
python, torch, isa_sim, isaaclab, device,
num_envs=2, num_iterations=1, num_steps_per_env=24,
actor_action_dim=65, body_action_dim=63,
hand_action_dim=90, env_action_dim=153
thresholds:
nonfinite_count_max=0
optimizer_overlap_count_max=0
checkpoint_roundtrip_max_abs=0
metrics:
nonfinite_count, optimizer_overlap_count,
checkpoint_roundtrip_max_abs, reward_term_count,
left_active_env_count, right_active_env_count,
support_transition_count, backward_grad_norm,
save_load_parameter_count
checks:
runtime_shape_exact, reset_step, backward_finite,
reward_terms_finite, left_right_roles, support_transition,
inactive_isolation, frozen_no_grad, optimizer_isolated,
save_load_exact, eval_trace_readable
artifacts:
smoke_trace, checkpoint, resume_comparison
S0的 prerequisite_gate_hashes 精确绑定E1/P0/P1;它仍然只是唯一
GRAIL-Min条件的一步工程检查。
Stage T0 — 单 sequence 开发训练
仅 seed 0,完全恢复 GRAIL budget:
num_envs: 4096
num_steps_per_env: 24
num_learning_iterations: 20000
save_frequency: 500
motion_resample_frequency: 250
训练期间每 500 iterations固定评估一次。不得根据中途结果改 reward、residual scale或 observation。
早停只允许:
- NaN/Inf;
- frozen gate失败;
- action/observation schema漂移;
- 连续 3 个 eval checkpoint出现相同 catastrophic human termination,且回溯确认不是 evaluator bug。
Stage T1 — 预注册重复
T0首次通过后,按完全相同 resolved config训练 seeds:
不得只报告最好 seed。每个 seed 使用相同 budget和 evaluation frames。
12. 唯一实验条件
本轮只有一个训练条件:
| ID | Runtime/robot | Frozen controller | policy output | 训练 |
|---|---|---|---|---|
| GRAIL-Min | GRAIL/SMPL-X | PHC-X | learned 63D body residual;hand primitive来自motion | 是 |
E0、E1、P0、P1和S0都是这一个条件的顺序验证gate,不是baseline、control或 额外训练。它们只回答“当前GRAIL-Min实现是否有资格进入下一步”,不参与方法间 排名。
不运行任何额外条件:
- OmniGrasp baseline;
- PULSE-X latent baseline;
- 原GRAIL/G1重新训练或zero-residual control;
- PHC native/matched 60/30 rollout;
- reward/contact ablation;
- residual scale sweep;
- observation删减;
- 30 Hz 主结果。
13. Evaluation protocol
13.1 GRAIL primary success
沿用 GRAIL evaluation 语义:
从 GRAIL 允许的 pre-contact start 到 reference 结束前没有任何非-timeout early termination,即 sequence success。
每个 seed固定评估 target-frame start offsets [0,7,14,21,29],都位于原 sample_from_n_initial_frames=30 范围内;不把 start distribution改成 post-contact。另把 start 0 的 trace指定为 canonical full-sequence artifact。
主 gate:
- 五个 start offsets均 sequence success;
- start
0完整 source time span success; - object position deviation从未超过
0.1 m; - active-hand↔任一 task-support termination次数
0; - reference contact interval 内,8-role grasp reward的 contact-count saturation ratio
≥ 0.8; - 所有 reward/action/state均 finite。
三 seed promotion gate:
- 每个 seed都通过上述 gate;
- 不能用 pooled mean掩盖失败 seed。
13.2 Secondary reporting
只用于诊断,不改变训练 reward:
- MPJPE mean/p50/p95/max;
- root position/orientation error;
- per-body position/orientation error;
- object position/orientation error;
- 8-role per-link contact ratio与force;
- grasp reward、finger-direction reward;
- active-hand↔source/destination support force,按 support role 分段;
- inactive-hand contact force及其对 active reward 的贡献(应为零);
- resolved active-hand、active-support time series及 role-transition frame;
- raw residual RMS/p95/max;
0.1 × residualRMS/p95/max;- base/final normalized body action clip rate;
- full controller-input rate;
- termination reason与first-failure frame;
- reference-contact前/中/后分段统计。
13.3 Statistical summary
因为是单 sequence:
- 不做样本独立性不足的显著性检验;
- 报告每 seed、每 rollout原始值;
- 汇总 median、min、max;
- bootstrap 只能对 rollout做描述性区间,并明确不是 motion-level generalization interval。
14. Required artifacts
每次 run目录必须包含:
material_passport.json
command.txt
git_state.json
artifact_hashes.json
resolved_config.yaml
config_diff.json
observation_schema/
policy.json
critic.json
phcx.json
mapping/
bodies.json
joints.json
contact_roles.json
primitive_open_closed.json
checkpoint_contract.json
reference_contract.json
task_role_contract.json
train_metrics.jsonl
eval/
per_rollout_metrics.jsonl
summary.json
termination_reasons.json
trace.npz
video.mp4
git_state.json 至少记录:
- parent repo commit和dirty diff;
- GRAIL gitlink与关键文件 hashes;
- PHC revision;
- PHC-X checkpoint hash;
- SMPL-X asset hash;
- CUDA、driver、PyTorch、Isaac Sim、Isaac Lab版本;
- GPU型号;
- seed和determinism flags。
15. Test plan
15.1 Unit
- PHC canonical↔Isaac Lab joint permutation round-trip;
63/90/153partition;- active-hand 8-role mapping;
- left/right 8-role mapping的镜像槽位和 reward parity;
- per-env active-hand select及 inactive-hand isolation;
- per-frame active-support select和唯一 stage-boundary transition;
- missing/ambiguous hand或support metadata fail-fast;
- primitive
-1/+1conversion; - hand action/contact label共用物理时间最近邻索引且逐帧一致;
- strict BPS缺失、全零、NaN/Inf和维度漂移 fail-fast;
- PHC observation shape
2026D; - RMS/clamp;
- frozen PNN action
153D; - frozen checkpoint/RMS/PD-affine digest、eval、grad和optimizer隔离;
- residual equation无
tanh、scale0.1; - full action gather/scatter;
- PHC PD offset/scale parity;
- policy/critic term order;
- role selection后的 reward/termination resolved values;
- reward数学、weight、threshold在 left/right 与各 support 之间完全相同;
- config allowlist。
15.2 Integration
- reference replay;
- native-vs-IsaacLab observation/action parity;
- zero-residual full sequence;
- filtered object↔left/right 8-role contact与 active-side selection;
- filtered task-supports↔left/right hand contact;
- source→destination support transition前后 observation/reward/termination routing;
- 非 active hand contact不计入 grasp,非声明 support不触发 task-support termination;
- two-env PPO backward;
- save/resume;
- deterministic evaluator artifact。
15.3 Regression
- 原
pnp_table.yamlresolve结果不变; - 原 G1 joint mapping不变;
- 原 SONIC action transform仍可加载;
- 原 GRAIL reward tests不变;
- 新 SMPL-X path不影响未选择该 robot/controller的实验。
16. Stop/go decision table
| Gate | GO | STOP |
|---|---|---|
| Config invariance | unexpected diff 0 |
任一未白名单 diff |
| Role contract | 每 motion一个 active hand;support只在声明边界切换 | 缺失、歧义、猜测或未声明切换 |
| Mapping | 63+90=153,双侧各8 roles且镜像 parity通过 |
缺失、重复、顺序不确定或 inactive-side泄漏 |
| PHC tensor parity | 达到 P0 tolerance | observation/action/PD target不一致 |
| Frozen closed loop | P1全部通过 | human tracker在GRAIL time base失败 |
| Smoke | finite、frozen、可save/resume | NaN、PHC-X更新、shape漂移 |
| Main eval | 每 seed 5/5 success和contact gate |
任一 seed失败 |
任何 STOP 都先报告失败的 contract;不能用改 reward、增加 curriculum或换 OmniGrasp observation来“修复”本实验。
17. 实施顺序
- 冻结 mother config、checkpoint、asset和reference hashes。
- 完成 config diff auditor。
- 注册 SMPL-X robot和
63/90joint partition。 - 完成 reference converter和52-body replay。
- 完成 task-role resolver;冻结当前 sequence 的 left hand、 source→destination support contract,并增加缺失/歧义 metadata fail-fast。
- 完成左右各8-role object/support sensors、active-side selection和镜像 parity tests。
- 完成双侧45D hand primitive转换:active hand按 motion action,inactive hand固定 open。
- 完成 PHC-X 2026D observation tensor parity。
- 完成 frozen PHC-X action transform和PD target parity。
- 运行 E0、E1、P0。
- 运行P1;不通过则停止。
- 运行 S0。
- 运行 T0 seed 0。
- 只有 T0 通过后运行 T1 seeds 1/2。
- 输出逐 seed原始结果、role trace、失败原因和复现 artifacts。
17.1 冻结执行命令
所有命令从 /mnt/data/PhysHSI 开始;正式E1/P0/P1/S0/T0运行前仍须按
experiment-agent规则把精确命令交给用户确认。GRAIL/Isaac Lab实际安装在项目
.envs/sonic,不得改用旧的 isaac-sim conda环境。公共环境:
set -euo pipefail
export OMNI_KIT_ACCEPT_EULA=YES
export MPLCONFIGDIR=/tmp/grail_minimal_mpl
export PYTHONPATH=/mnt/data/PhysHSI:/mnt/data/PhysHSI/submodules/GRAIL/imports/SONIC:/mnt/data/PhysHSI/submodules/PHC
export GRAIL_PYTHON=/mnt/data/PhysHSI/.envs/sonic/bin/python
test -x "$GRAIL_PYTHON"
cd /mnt/data/PhysHSI
E0静态、checkpoint与主USD命令:
"$GRAIL_PYTHON" tools/convert_smplx_motion_to_grail.py \
--motion output/auto_experiments/20260723_cup_left_hand_object_interaction_v20/motion.npz \
--task-plan output/auto_experiments/20260705_hsi_generation_task_inputs/task_plan_left.json \
--layout-json data/selected_SAGE10k/e2e_test_scenes/2cdc81db/layout_2cdc81db.json \
--out-dir output/grail_minimal_smplx_phcx_20260724/reference \
--motion-key cup_left_pick_place_v20 \
--source-fps 30
"$GRAIL_PYTHON" tools/audit_grail_minimal_config.py \
--output-dir output/grail_minimal_smplx_phcx_20260724/e0
"$GRAIL_PYTHON" tools/audit_grail_phcx_checkpoint.py \
--checkpoint submodules/PHC/output/HumanoidIm/phc_x_pnn/Humanoid.pth \
--action-offset submodules/PHC/data/action_offset_smplx.pkl \
--output output/grail_minimal_smplx_phcx_20260724/e0/phcx_checkpoint_static_gate.json \
--device cpu
"$GRAIL_PYTHON" tools/convert_grail_smplx_mjcf_to_usd.py \
--input output/grail_minimal_smplx_phcx_20260724/reference/robot_motion_humanoid.xml \
--output output/grail_minimal_smplx_phcx_20260724/reference/robot_motion_humanoid.usd \
--headless --device cpu
"$GRAIL_PYTHON" tools/audit_grail_smplx_usd.py \
--input output/grail_minimal_smplx_phcx_20260724/reference/robot_motion_humanoid.usd \
--output output/grail_minimal_smplx_phcx_20260724/e0/usd_contract.json \
--headless --device cpu
"$GRAIL_PYTHON" tools/audit_grail_minimal_preflight.py \
--phase e0 \
--config-audit output/grail_minimal_smplx_phcx_20260724/e0/config_audit.json \
--checkpoint-audit output/grail_minimal_smplx_phcx_20260724/e0/phcx_checkpoint_static_gate.json \
--usd-audit output/grail_minimal_smplx_phcx_20260724/e0/usd_contract.json \
--robot-usd output/grail_minimal_smplx_phcx_20260724/reference/robot_motion_humanoid.usd \
--reference-contract output/grail_minimal_smplx_phcx_20260724/reference/reference_contract.json \
--output output/grail_minimal_smplx_phcx_20260724/e0/preflight.json
E1/P0/P1的专用runner及stage-metric preflight validator尚未实现;冻结名称
与输出schema如下,
不得用手写 passed=true 文件代替:
tools/run_grail_minimal_reference_replay.py
-> e1/reference_replay_gate.json
-> schema=grail_minimal_e1_reference_replay_v1
tools/audit_grail_phcx_tensor_parity.py
-> p0/phcx_tensor_parity_gate.json
-> schema=grail_minimal_p0_phcx_tensor_parity_v1
tools/run_grail_phcx_zero_residual.py
-> p1/zero_residual_gate.json
-> schema=grail_minimal_p1_zero_residual_v1
每个runner输出还必须包含与preflight输出同名同值的
upstream_hashes={config_audit,checkpoint_audit,usd_audit,robot_usd,reference_contract}。
P1的 prerequisite_gate_hashes 必须绑定当前E1/P0 artifacts;S0的同名字段必须
绑定当前E1/P0/P1 artifacts。它们是进入S0前的剩余工程项。实现并通过后,
S0 preflight必须只接受E1/P0/P1,并与训练命令用 && 硬串联:
"$GRAIL_PYTHON" tools/audit_grail_minimal_preflight.py \
--phase smoke \
--config-audit output/grail_minimal_smplx_phcx_20260724/e0/config_audit.json \
--checkpoint-audit output/grail_minimal_smplx_phcx_20260724/e0/phcx_checkpoint_static_gate.json \
--usd-audit output/grail_minimal_smplx_phcx_20260724/e0/usd_contract.json \
--robot-usd output/grail_minimal_smplx_phcx_20260724/reference/robot_motion_humanoid.usd \
--reference-contract output/grail_minimal_smplx_phcx_20260724/reference/reference_contract.json \
--e1-audit output/grail_minimal_smplx_phcx_20260724/e1/reference_replay_gate.json \
--p0-audit output/grail_minimal_smplx_phcx_20260724/p0/phcx_tensor_parity_gate.json \
--p1-audit output/grail_minimal_smplx_phcx_20260724/p1/zero_residual_gate.json \
--output output/grail_minimal_smplx_phcx_20260724/s0/preflight.json \
&& "$GRAIL_PYTHON" tools/audit_grail_minimal_runtime_config.py \
--phase smoke \
--preflight output/grail_minimal_smplx_phcx_20260724/s0/preflight.json \
--experiment-dir output/grail_minimal_smplx_phcx_20260724/s0/seed0 \
--seed 0 \
--output output/grail_minimal_smplx_phcx_20260724/s0/runtime_config_gate_seed0.json \
&& cd /mnt/data/PhysHSI/submodules/GRAIL/imports/SONIC \
&& WANDB_MODE=disabled "$GRAIL_PYTHON" gear_sonic/train_agent_trl.py \
+exp=manager/universal_token/hoi/pnp_table_smplx_phcx_minimal \
num_envs=2 headless=True seed=0 \
algo.config.num_learning_iterations=1 \
algo.config.num_steps_per_env=24 \
use_wandb=false \
experiment_dir=/mnt/data/PhysHSI/output/grail_minimal_smplx_phcx_20260724/s0/seed0 \
grail_runtime_config_gate=/mnt/data/PhysHSI/output/grail_minimal_smplx_phcx_20260724/s0/runtime_config_gate_seed0.json
S0 runner必须把 backward/save/load/frozen checks汇总为
s0/smoke_gate.json,schema为 grail_minimal_s0_smoke_v1。T0命令保持母配置
4096 envs / 24 steps / 20000 iterations,不覆盖训练日程:
cd /mnt/data/PhysHSI
"$GRAIL_PYTHON" tools/audit_grail_minimal_preflight.py \
--phase train \
--config-audit output/grail_minimal_smplx_phcx_20260724/e0/config_audit.json \
--checkpoint-audit output/grail_minimal_smplx_phcx_20260724/e0/phcx_checkpoint_static_gate.json \
--usd-audit output/grail_minimal_smplx_phcx_20260724/e0/usd_contract.json \
--robot-usd output/grail_minimal_smplx_phcx_20260724/reference/robot_motion_humanoid.usd \
--reference-contract output/grail_minimal_smplx_phcx_20260724/reference/reference_contract.json \
--e1-audit output/grail_minimal_smplx_phcx_20260724/e1/reference_replay_gate.json \
--p0-audit output/grail_minimal_smplx_phcx_20260724/p0/phcx_tensor_parity_gate.json \
--p1-audit output/grail_minimal_smplx_phcx_20260724/p1/zero_residual_gate.json \
--s0-audit output/grail_minimal_smplx_phcx_20260724/s0/smoke_gate.json \
--output output/grail_minimal_smplx_phcx_20260724/t0/preflight_seed0.json \
&& "$GRAIL_PYTHON" tools/audit_grail_minimal_runtime_config.py \
--phase train \
--preflight output/grail_minimal_smplx_phcx_20260724/t0/preflight_seed0.json \
--experiment-dir output/grail_minimal_smplx_phcx_20260724/t0/seed0 \
--seed 0 \
--output output/grail_minimal_smplx_phcx_20260724/t0/runtime_config_gate_seed0.json \
&& cd /mnt/data/PhysHSI/submodules/GRAIL/imports/SONIC \
&& WANDB_MODE=offline "$GRAIL_PYTHON" gear_sonic/train_agent_trl.py \
+exp=manager/universal_token/hoi/pnp_table_smplx_phcx_minimal \
num_envs=4096 headless=True seed=0 \
use_wandb=true \
experiment_dir=/mnt/data/PhysHSI/output/grail_minimal_smplx_phcx_20260724/t0/seed0 \
grail_runtime_config_gate=/mnt/data/PhysHSI/output/grail_minimal_smplx_phcx_20260724/t0/runtime_config_gate_seed0.json
T1只把 seed=0 与输出路径分别改为1、2;其他 resolved config必须与T0相同。
18. 最终验收定义
只有同时满足以下条件,才能把状态从 UNVERIFIED 改成 VERIFIED:
- 工程实现和测试完成;
- allowlist外 resolved-config diff为零;
- PHC-X tensor/PD parity通过;
- frozen zero-residual human closed loop通过;
- 三 seed主训练使用同一 GRAIL budget;
- 每 seed
5/5full-sequence success; - GRAIL object/active-hand/task-support gates通过;
- 当前左手跨-support sequence通过,且实现没有 current-scene/current-hand hardcode;left/right镜像 reward parity与 inactive-side isolation测试通过;
- PHC-X全程 frozen;
- 所有 required artifacts、hash和命令齐全;
- 报告明确披露 SONIC latent residual→PHC-X action residual这一不可避免的接口变化。
在此之前,最准确的项目状态是:
GRAIL-Min-SMPLX 的 minimal adaptation、reference conversion、composed config allowlist、CPU contract tests和完整E0已通过;当前仍为UNVERIFIED。 必须继续通过E1/P0/P1、simulator smoke和预注册训练,才能声称实验完成。