跳转至

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_handactive_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-X pose_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, 只保留刚体 Pelvis root。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 Hz runtime中以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.yaml
  • submodules/PHC/output/HumanoidIm/phc_x_pnn/Humanoid.pth
  • submodules/PHC/output/HumanoidIm/phc_x_pnn/.hydra/config.yaml
  • submodules/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、要求唯一 Pelvis root、把超出 ±180° 的关节范围钳到 官方PHC USD行为,并删除importer在非刚体wrapper上生成的多余articulation root;
  • .envs/sonic 中的Isaac Lab Articulation 已实际加载该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_minimalphcx action 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-driven active_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-handtask-supports↔active-hand contact 语义。

本轮明确不做:

  • 不使用 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”不是“只改两行路径”,而是:

  1. 只允许 embodiment、frozen checkpoint 接口和 task-entity role binding 所迫使的变化;
  2. 每个变化必须进入 allowlist;
  3. 任何不在 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 control time base 下无法稳定闭环;
  • 直接 action-space residual 不能替代 GRAIL 的 SONIC pre-quantization latent residual;
  • 固定 2D hand 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_actionsstep VERIFIED_FROM_CODE
release pnp_table 把 contact sensor links、grasp hand、finger-direction links 和 approach wrist 固定为右手 pnp_table.yamlrewards.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 244096 env、20000 iterations ppo_im_phc.yamlpnp_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_NAMESx/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/rightobject_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=4096
  • env_spacing=10.0
  • replicate_physics=false
  • object_is_dynamic=true
  • object_mass=0.1
  • plane、scene pose convention 和 support collision material语义
  • sim_dt=0.005
  • decimation=4
  • actor/critic history length 10
  • num_future_frames=10
  • dt_future_ref_frames=0.1
  • sample_before_contact=true
  • sample_from_n_initial_frames=30
  • use_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_handright_hand、床头柜、 书桌或任一 layout object id;
  • 加入 point cloud、target-attributed contact、lift/hold reward;
  • 改 contact threshold 0.1 Nmin_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_idexpected_contacts[channel=object_support].support_id 交叉核对,两者不一致即失败;
  • 本轮只支持每条 motion 一个稳定的 leftright active 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:左右手各自的

Index1-3, Middle1-3, Pinky1-3, Ring1-3, Thumb1-3

启动时必须断言:

  • 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=42Dbody_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_sensorobject_to_right_hand_contact_sensor 分别跟踪 target object ↔ 对应8 bodies;
  • observation/reward按 active_hand_id 选择一套,flatten后仍为24D;
  • supports_to_left_hand_contact_sensorsupports_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 中合并为唯一 Wrist proxy, 不通过重复 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:

hand_action_left, hand_action_right ∈ {-1, +1}
-1 = open
+1 = closed

并保留:

use_motion_hand_actions: true
use_finger_primitive: true

SMPL-X 每只手需要固定的 normalized open_45dclosed_45d

  1. 从 source SMPL-X pose_hand[:,90] 读取双手 axis-angle,禁止另做 IK 或 用训练 reward反推 pose;
  2. q_open_90d 为 source 前 min(30,T) 帧逐维 median;
  3. 在 active-hand GRAIL-style geometric-contact frames 内,选与 q_open_active axis-angle L2 距离最大的 source frame作为 q_closed_active_45d
  4. 当前 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恒开;
  5. 用 PHC-X PD affine把 q_open/q_closed 转成 normalized 90D primitive, 并验证 shape、joint name/order、finite、[-1,1] 和 round-trip;
  6. 两组 normalized向量写入 primitive_open_closed.json,记录 source frame、 derivation、input/output hashes;
  7. 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 顺序严格保留:

  1. command
  2. motion_anchor_pos_b
  3. motion_anchor_ori_b
  4. base_lin_vel
  5. base_ang_vel
  6. joint_pos
  7. joint_vel
  8. actions
  9. target_object_pos
  10. hand_object_transform_6d
  11. finger_tips_force
  12. object_pos_b
  13. object_ori_b_6d
  14. table_pos_b
  15. table_ori_b
  16. object_pos_delta_multi_future
  17. object_ori_delta_multi_future_6d
  18. command_multi_future
  19. motion_anchor_ori_b_mf
  20. object_bps

只允许下列 shape 变化:

  • command: G1 body 29 pos + 29 vel → SMPL-X body 63 pos + 63 vel
  • joint_pos/joint_vel/actions: 43D153D
  • hand_object_transform_6d: 左右各按对应三点计算,再由 active_hand_id per-env选择,输出仍为9D;
  • finger_tips_force: 左右各计算8-role × 3-axis filtered pair force,再由 active_hand_id per-env选择,输出仍为24D;
  • table_pos_b/table_ori_b: 从固定 table actor改读 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_pos
  • body_ori
  • grab_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.json
  • critic_observation_schema.json
  • phcx_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;sibling JointPositionActionCfg 负责唯一一次 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_btable_ori_breward_hand_table_contact_penaltyhand_table_contact_termination;其中 table 仅作为兼容名称,运行时实体不得 从名称推断,必须由 role contract 解析。

  • anchor:pelvis → Pelvis
  • undesired-contact allowlist:两侧 ankles + 双手 30 个 finger bodies + 双侧 Wrist palm proxy。GRAIL 在 G1 上能区分 palm 与三段 wrist,而 SMPL-X 将它们合并;为了让 active side 能把 Wrist 用作 palm,左右必须静态同规则, 不得让 inactive wrist采用另一套 reward;
  • grasp hand:release right_hand 常量 → per-env active_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_bactive_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 67511033 bytes;
  • SHA-256 98b5f079eb54e6c404453992650e6f2b67d4d59c1d1ac5925aa9dedcad1cc622
  • 597 source 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) 为 layout place_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:复现 GRAIL grail/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/righttask_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_6dfinger_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 不得复用:

  • 2033D ResMimic 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_table resolved config;
  • SMPL-X/PHC-X resolved config;
  • allowlist JSON。

输出:

  • resolved_config_base.yaml
  • resolved_config_adapted.yaml
  • config_diff.json
  • unexpected_diff.json
  • passed

只要 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.jsonphcx_observation_schema.jsonconfig_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 上,分别用:

  1. PHC native observation functions;
  2. 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

条件:

delta_63 = 0
hand primitive仍由 motion labels驱动
不训练 PPO

主 gate 使用 GRAIL 原 time base:

physics = 200 Hz
control = 50 Hz

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_actionsrobot.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=2
  • num_learning_iterations=1
  • num_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:

0, 1, 2

不得只报告最好 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 × residual RMS/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/153 partition;
  • 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/+1 conversion;
  • 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、scale 0.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.yaml resolve结果不变;
  • 原 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. 实施顺序

  1. 冻结 mother config、checkpoint、asset和reference hashes。
  2. 完成 config diff auditor。
  3. 注册 SMPL-X robot和 63/90 joint partition。
  4. 完成 reference converter和52-body replay。
  5. 完成 task-role resolver;冻结当前 sequence 的 left hand、 source→destination support contract,并增加缺失/歧义 metadata fail-fast。
  6. 完成左右各8-role object/support sensors、active-side selection和镜像 parity tests。
  7. 完成双侧45D hand primitive转换:active hand按 motion action,inactive hand固定 open。
  8. 完成 PHC-X 2026D observation tensor parity。
  9. 完成 frozen PHC-X action transform和PD target parity。
  10. 运行 E0、E1、P0。
  11. 运行P1;不通过则停止。
  12. 运行 S0。
  13. 运行 T0 seed 0。
  14. 只有 T0 通过后运行 T1 seeds 1/2。
  15. 输出逐 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/5 full-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和预注册训练,才能声称实验完成。