跳转至

Hand–Object Interaction 领域接口重构与验收计划(2026-07-23)

1. 目标

把当前分散在 grasp.pyconstraint.pyhands.pybinding.py 和临时 backend selector 中的 pick/place hand–object keyframe 数据流收敛为一个 general + simple 的正式领域接口:

task_plan + layout + natural scaffold
统一 contract 下的 phase-specific natural-scaffold preparation
        ├─ accepted pick scaffold rule
        └─ general place scaffold rule
phase-specific internal interaction solve
        ├─ accepted pick rule → InteractionKeyframe(pick)
        └─ general place rule → InteractionKeyframe(place; inherit pick grasp relation)
ordinary KIMODO constraints
official KIMODO once
canonical hand bake
object binding / release
ordinary motion + interaction_quality provenance

正式实现只允许一个跨阶段 dataclass:InteractionKeyframe。质量评估使用普通函数和固定键字典,不增加 InteractionQuality、phase-specific keyframe class 或 solver-result wrapper。

2. 范围与非目标

本轮必须完成:

  1. 新增 utils/hsi_generation/hand_object_interaction.py,成为正式 pick/place interaction keyframe 的唯一公共领域入口。
  2. 用 frozen InteractionKeyframe 在内存中连接 keyframe generation、constraint preparation、hand bake、object binding/release 和 evaluation。
  3. place 严格继承 pick 的 hand_pose 与 hand–object local SE(3),只允许调整 root translation、root heading、body pose 和交互侧 shoulder/elbow/wrist。
  4. 正式实现直接采用 accepted pick rule + general place rule。已验收 pick 生成规则保持完整不变;place 使用独立但通用的生成/优化规则达到相近效果。两个 phase 不要求共用 solver 内部实现,只共用 InteractionKeyframe 数据契约、坐标约定、同一 quality evaluator/metric、一次 KIMODO 与后续 bake/binding/release 接口。不存在运行时路径切换或旧字段兼容。
  5. 两个 interaction keyframe 必须在生成 motion 之前一次性加入同一份 constraints;完整 sequence 只调用一次 KIMODO,禁止 second pass 或生成后 splice keyframe。
  6. 正式 pipeline 固定为 accepted pick rule + general place rule;不再暴露 --grasp-backendpick_grasp_backend 或 backend context selector,正式代码/配置/manifest/测试也不使用临时 backend 名称。
  7. HOI-FHLI、ContactGen 等旧对照实现可以留在独立 baseline 工具中,但不能成为正式 pipeline.py / constraint.py 的运行时分支或状态来源。
  8. 保留已验收的 grasp 前后各 10 帧 C2 root2d bridge。

本轮不做:

  • 不重写官方 KIMODO inference 或 submodule。
  • 不增加对象名称、support 类型、cup 几何或固定 wrist offset 分支;若候选选择需要修正,只允许使用所有对象共享的既有 contact/opposition/penetration/naturalness 指标,并必须用 golden 非退化对照验证。
  • 不修改 ContactGen、HOI-FHLI、InterMimic、OmniGrasp 等 baseline 的官方实现。
  • 不引入对象名称、类别、handle 顶点、cup opening 或 support-specific 分支。
  • 不把 contact timeline、push/pull/kick scene interaction 合并进 hand_object_interaction.py
  • 不用 manifest、临时 .npz 或目录扫描作为正式阶段之间的运行时状态总线。

3. 正式领域对象

@dataclass(frozen=True)
class InteractionKeyframe:
    phase: Literal["pick", "place"]
    frame: int
    active_hand: Literal["left", "right", "both"]

    local_rot_mats: np.ndarray       # (J, 3, 3)
    root_position: np.ndarray        # (3,)
    root_heading: np.ndarray         # (2,), unit XZ heading
    hand_pose: np.ndarray            # (90,), canonical absolute SMPL-X hands

    object_position: np.ndarray      # (3,)
    object_rotation: np.ndarray      # (3, 3)
    hand_object_local_position: np.ndarray  # (3,) for one hand; (2,3) for both
    hand_object_local_rotation: np.ndarray  # (3,3) for one hand; (2,3,3) for both

    quality: dict[str, float | bool]

构造时必须复制为 contiguous、只读的 float32 数组并验证:

  • phaseactive_hand 为封闭集合;frame >= 0
  • 所有 shape 精确匹配;所有数值 finite。
  • rotation matrices 为右手正交矩阵,det≈1
  • root heading 为非零单位向量。
  • quality 精确包含第 4 节必需键;缺键立即失败。
  • dataclass frozen 只禁止字段重新绑定;数组本身也必须设置 writeable=False,防止跨阶段原地修改。

不添加 to_dict()from_dict()、solver adapter 或 artifact path 字段。需要写 provenance 时由边界函数显式提取普通字典;canonical motion 仍只保存 motion/object identity/pose,不保存 object mesh。

4. Quality 普通字典

唯一 evaluator:

def evaluate_interaction_quality(...) -> dict[str, float | bool]:
    return {
        "contact_pass": ...,
        "opposition_pass": ...,
        "penetration_pass": ...,
        "body_naturalness_pass": ...,
        "root_translation_m": ...,
        "hand_object_penetration_m": ...,
        "hand_object_position_error_m": ...,
        "hand_object_rotation_error_deg": ...,
    }

消费者必须用 quality["contact_pass"] 等显式访问必需字段;禁止 .get() 为缺失质量信号提供默认值。quality 只承担 gate 和 provenance,不拥有类型、生命周期或行为。

5. 正式 API 与职责

5.1 generate_pick_keyframe

pick_interaction = generate_pick_keyframe(
    scaffold=pick_scaffold,
    object_geometry=object_geometry,
    active_hand=active_hand,
)

输入只含自然 reach scaffold、实际 object geometry 和 active hand。正式实现内部固定调用已验收的 pick interaction protocol,不读取 backend selector。返回完整、已 gate 的 InteractionKeyframe(phase="pick")

5.2 generate_place_keyframe

place_interaction = generate_place_keyframe(
    scaffold=place_scaffold,
    object_geometry=object_geometry,
    target_object_pose=target_object_pose,
    pick_keyframe=pick_interaction,
)

强制继承:

place.hand_pose                    == pick.hand_pose
place.hand_object_local_position   == pick.hand_object_local_position
place.hand_object_local_rotation   == pick.hand_object_local_rotation

允许改变:root translation、root heading、body pose、交互侧 collar/shoulder/elbow/wrist。禁止重新优化手指或改变 grasp local SE(3)。

generate_pick_keyframe 固定执行已验收 pick 规则;generate_place_keyframe 通过显式 freeze mask 把 pick grasp 作为固定条件,并可使用独立的通用 solver/loss 内部实现。不得改动已验收 pick,也不得引入 object/support 名称分支。两者的输出坐标、InteractionKeyframe 字段、quality evaluator/metric 和 downstream contract 必须保持统一。

5.3 add_constraints

constraints = add_constraints(
    base_constraints,
    keyframes=[pick_interaction, place_interaction],
    bridge_half_window_frames=10,
)

返回同时包含 pick/place 的普通 KIMODO constraint list,不写中间文件。pick interaction root residual 在原 task root path 上使用前后各 10 帧 quintic smootherstep C2 bridge;grasp frame 精确命中,边界精确回原 path。KIMODO loader 所需 JSON 只在外部 solver boundary 一次性写入;该完整 constraint list 只触发一次 KIMODO full-sequence generation。

6. 正式 pipeline 数据流

constraint.prepare() 的内存状态改为:

pick_reach_scaffold_by_step
pick_interaction_by_step:  InteractionKeyframe
place_reach_scaffold_by_step
place_interaction_by_step: InteractionKeyframe

正式返回值应显式包含:

{
    "scaffold": {"constraints_json": ...},
    "hand_object_interactions": {
        "pick": [...],
        "place": [...],
    },
    "scene_interaction": {...},
}

pick/place hand–object keyframe 不再塞进容易与 contact timeline 混淆的通用 interaction 字典。push/pull/kick、contact windows、support windows 与普通 object motion 继续属于 scene_interaction

hands.bake() 和 object binding/release 接收 InteractionKeyframe,不再从 hand_pose_target.npzkeyframe_artifact、manifest 或嵌套 contract 中重新发现 pose。最终 artifact 和 manifest 只记录 provenance,不反向驱动后续 stage。

禁止的数据流:

pick KIMODO → splice/refine place → second KIMODO
KIMODO → overwrite full-body pick/place keyframe
formal pipeline → runtime backend selector / old schema adapter

7. 命名迁移

正式代码、配置、manifest 和测试统一使用:

旧名 正式名
pick_grasp pick_interaction
place_grasp place_interaction
pick_binding(指 keyframe contract 时) pick_interaction
pick_grasp_keyframe pick_interaction_keyframe
place_grasp_keyframe place_interaction_keyframe
pick_grasp_backend / grasp_backend 删除,不提供正式替代 selector
generic interaction(混合 hand-object 与 scene timeline) hand_object_interactions + scene_interaction

允许 baseline 工具和历史文档保留方法名,但正式 pipeline.pyconstraint.py、默认 config、manifest schema 和正式测试不得依赖这些旧名。

8. 实现顺序

P0:冻结 golden evidence

  • Golden motion:output/auto_experiments/20260723_cup_left_map_free_smooth_root2d_10f/motion.npz
  • Golden visualization:同目录 visualizations/grasp_window_frames_60_140_slow.mp4
  • 固定 task plan、layout、seed 41、KIMODO diffusion 50 steps 和 bridge half-window 10。
  • Golden pick 是不可退化基线:新通用路径的 contact、opposition、penetration、hand naturalness 与 10-frame root smooth 必须达到同等级;不得为了形式上的 pick/place 对称而接受更差抓握。

P1:领域对象与纯函数

  • 新增 InteractionKeyframe、严格构造验证、quality evaluator。
  • 新增 keyframe ↔ ordinary solver payload 的私有纯函数;不暴露 path/manifest adapter。
  • 单元测试先行。

P2:Pick 迁移

  • 将已验收 pick interaction generation 收敛到 generate_pick_keyframe
  • constraint.py 保存 pick_interaction 对象,不再保存 backend result dict。
  • add_constraints 直接消费对象;hand bake/object binding 直接消费对象。

P3:Place 迁移

  • generate_place_keyframe 从 pick 对象继承 hand pose 和 local SE(3),但不要求与 pick 共用内部 solver。
  • 已完成的有界 GPU golden gate 已证明统一内部生成/refinement 会降低已验收 pick 的物理质量,因此正式实现完整冻结 accepted pick rule;place 使用独立但仍然 general、无对象/场景硬编码的生成与 refinement 路径。
  • 优先验证 phase-agnostic natural-reach scaffold:只由 target object pose、task root/heading 与 active hand 决定,不使用 PICKUP_WRIST_OFFSET / PLACE_WRIST_OFFSET、support 类型或对象名称分支。
  • 原样保留已验收的完整 pick 生成规则,并改造一个不依赖对象/support 类别的 place 生成规则,使 place 达到同等级的 natural reach + grasp/mesh 质量;不能保留旧 PLACE_WRIST_OFFSET 路径。phase-specific solver 内部实现可以不同,但必须共用 InteractionKeyframe、quality evaluator/metric 与后续一次 KIMODO 数据流。
  • release alignment 仍由普通 task phase 计划决定,不进入 dataclass。

P4:Scene interaction 分离

  • 将 push/pull/kick/contact/support timeline 保留为普通 scene_interaction 字典。
  • hand-object pick/place 不再借用 contact timeline schema。

P5:删除正式 selector 与临时命名

  • CLI 恢复为仅 task_plan + layout_json + out_dir
  • 默认 settings 删除 pick_grasp_backend
  • 正式 pipeline/constraint import graph 不包含 backend selector 或 baseline implementation。
  • baseline 如需选择器,放在独立 tools/ 入口,不被正式 pipeline import。

P6:回归、真实生成、review

  • 跑单元、集成和全量相关测试。
  • GPU 1 重新生成 cup-left 完整 sequence。
  • 数值比较 golden;生成新完整视频和 grasp-window 慢放。
  • 独立 reviewer 检查是否真正删掉复杂度而非移动复杂度。

P7:用新 trajectory 重训最近一版 OmniGrasp cup-left baseline

  • 该阶段必须回到此前使用旧 cup-left motion、并因 hand pose 不合理而触发本轮 grasp-pose 与整体生成流程重构的同一条实验链;不得改选一个更容易通过但训练定义不同的 OmniGrasp run。
  • 在现有实验记录、config、checkpoint 和训练日志中定位最近一次 cup-left OmniGrasp contact-gate 修正版;记录 commit、config、seed、observation/reward/action、table removal、contact attribution、训练预算和 deterministic eval 命令。
  • 复制其配置并做 machine-readable diff,除 motion/reference artifact 及由其决定的 frame metadata 外不得改变训练定义。
  • 将本轮数值验收通过的完整 motion 转为该 baseline 所需 reference 格式,先运行 loader、zero-action/reference 与 contact-label sanity checks。
  • 重新训练并按既有 cadence 持续 deterministic eval;保存 completion、termination reason、human tracking、object position、lift、target-attributed finger contact 和 drop 指标。
  • 若失败,先区分 reference/data、contact labeling、reward gate、exploration和训练预算;不得回头改成 object-name 或 cup-specific rule。

9. 硬性验收标准

A. 结构与静态接口(全部必须通过)

  1. hand_object_interaction.py 中恰好一个领域 dataclass:InteractionKeyframe
  2. 不存在 InteractionQualityPickInteractionKeyframePlaceInteractionKeyframeInteractionSolverResult
  3. pipeline.pyconstraint.py 不 import backend selector 或 baseline pick/place implementation。
  4. 正式 CLI 不包含 --grasp-backend;默认 config 不包含 pick_grasp_backend
  5. 正式 manifest 不再写 pick_grasp_backend,使用 pick_interaction / place_interaction provenance。
  6. required quality keys 的消费者不用 .get()
  7. phase handoff 不通过 manifest、目录扫描或中间 keyframe/hand-pose .npz
  8. rg 确认正式 import graph 无旧 selector;遗留名字只允许出现在 baseline 工具、历史文档或明确 legacy 文件。

B. InteractionKeyframe 单元测试(全部必须通过)

  1. left/right/both、pick/place 合法构造。
  2. 非法 enum、负 frame、错误 shape、NaN/Inf、非 rotation、零 heading、缺 quality key 全部 fail-fast。
  3. frozen field 不能重新绑定;每个 ndarray 不能原地修改。
  4. 输入数组修改不影响已构造对象,证明 defensive copy。
  5. both-hand local SE(3) shape 与单手 shape 严格区分。
  6. quality 输出键集合和 value type 精确一致。

C. Pick/Place 语义(全部必须通过)

  1. pick 输出 phase/frame/active hand 与 task action-template 一致。
  2. pick 使用 actual triangle mesh 和 metric scale,不使用 bbox/category shortcut。
  3. place 的 hand pose 与 pick bitwise equal。
  4. place 的 hand–object local position/rotation 与 pick bitwise equal。
  5. place 优化前后只允许 root、heading、body 与 active interaction-arm joint 改变;inactive arm 和 fingers 不变。
  6. quality 四个 boolean gate 必须显式读取并为真才允许进入 constraints。
  7. pick/place 的 solver/refinement 调用记录必须指向同一个公共 primitive;除 freeze mask、phase scaffold 和 target object pose 外,参数协议一致。

D. Constraint 语义(全部必须通过)

  1. ordinary task root2d → 10-frame bridge → fullbody interaction keyframe → active-hand orientation,顺序固定。
  2. bridge 窗口为 [frame-10, frame+10],受 segment boundary 裁剪;要求 grasp 两侧均至少一帧,否则明确失败。
  3. quintic smootherstep 两端 value/一阶/二阶导为 0;center 权重为 1。
  4. center root 精确等于 InteractionKeyframe.root_position[[0,2]];边界精确等于原 task root path。
  5. heading 沿原 task path;interaction solve 不优化 heading 时不引入 heading jump。
  6. 输入 base constraints 不被隐式共享修改;输出为新的普通 list/dict。

E. Pipeline 集成与命名(全部必须通过)

  1. mock pipeline 数据流严格为 pick_interaction → place_interaction → constraints → KIMODO → hand bake → binding/release
  2. mock/spy 明确证明 pick/place constraints 在 KIMODO 调用前均已存在,且 full-sequence KIMODO call count 严格等于 1
  3. hands.bake 不读取 hand pose artifact;binding 不读取 keyframe artifact。
  4. KIMODO 之后不存在 pick/place full-body splice、second-pass inference 或 constraint regeneration。
  5. scene contact timeline 与 hand_object_interactions 分离,push/pull/kick regression 不变。
  6. 旧 baseline selector 的测试转移到 baseline scope;正式入口测试明确拒绝旧参数。
  7. 全量 HSI generation 相关测试零失败;测试数不得通过删除断言而减少。

F. GPU 真实 sequence 数值 gate(全部必须通过)

使用 cup-left、GPU 1、seed 41 从 task plan 完整重生,不复用 golden motion:

指标 Gate
frame count 597
grasp frame 98
bridge window [88,108]
strict hand-object audit pass
pick contact gate pass
pick opposition gate pass
active hand ratio <5 cm ≥ max(0.85, golden−0.02)
support overlap max depth diagnostic ≤ 3 cm,不作为本轮主要苛刻 gate
object–wrist local position drift, frames 98–500 ≤ 1e-5 m
object–wrist local rotation drift, frames 98–500 ≤ 1e-3 deg
place pose 对 inherited local position 的实际实现误差 ≤ 5 mm(亚毫米级 solver 方差不应拒绝几何上等价的 place;仍远严于允许的厘米级碰撞诊断)
place pose 对 inherited local rotation 的实际实现误差 ≤ 2°
frame 97→98 object position jump ≤ 1 mm

绝对时序阈值不能比已验收结果本身更严格。正式比较使用同一输入、shape、seed、帧窗和 metric 实现;pick 以已验收的 20260723_cup_left_map_free_smooth_root2d_10f 为不可退化基线,place 以该 motion 的连续性统计为上限参考,同时增加新的 hand-pose/local-SE(3) 继承硬门。允许的数值包络是 golden 的约 1.25×,root acceleration 因随机生成方差采用 1.5×;不是为了形式统一而降低 pick 质量。

pick frame 98 与 place frame(由 phase plan 解析,不在实现中 hard code)的中心 ±10 帧必须满足:

Temporal metric Pick gate Place gate
root position max step ≤ 1.00 cm/frame ≤ 3.50 cm/frame
active wrist max step ≤ 1.65 cm/frame ≤ 3.75 cm/frame
object position max step ≤ 1.50 cm/frame ≤ 4.75 cm/frame
local body joint max SO(3) step ≤ 3.20°/frame ≤ 11.75°/frame
root linear acceleration ≤ 4.50 m/s² ≤ 10.20 m/s²
canonical hand-pose L2 step ≤ 0.065 rad/frame ≤ 0.24 rad/frame

同时报告 active wrist acceleration、local body angular acceleration、position/rotation jerk 与相邻 30-frame robust median/MAD 比值。robust ratio 用于定位异常,不能单独否决语义 keyframe:静止→运动或 reach→withdraw 的合法 phase boundary 会令局部 MAD 接近零,并使任意平滑转向产生任意大的比值。时序硬门仍是上表的绝对 step/acceleration,加上数值或视频中实际出现的单帧来回反转;单次预期方向反转不等于 jitter。place keyframe 的 hand_posehand_object_local_positionhand_object_local_rotation 必须与对应 pick bitwise equal,这是独立于碰撞容差的硬门。

任何一项失败都不能通过放宽阈值处理;必须定位是领域转换、constraint、hand bake、binding 还是模型非确定性。

G. 可视化 gate(全部必须人工确认)

必须输出:

  1. 完整 597-frame full-scene opaque video。
  2. frames 60–140、0.5× grasp-window 视频,标注原始 frame。
  3. frames 68/78/88/98/108/118/128 contact sheet。

人工检查:

  • frame 88–108 无水平 root snap、反向弹回或 planted-foot 明显滑移。
  • approach 手/前臂不穿过 support;不在 grasp frame 瞬移到物体另一侧。
  • frame 98 grasp pose 与 accepted golden keyframe 一致,无 finger bake convention 变化。
  • object 在绑定瞬间无位置/旋转跳变;carry 保持固定 hand-local relation。
  • place 不改变抓握手型,不出现 release 前 object teleport。

H. 独立 reviewer gate

reviewer 必须主动检查并给出零阻断结论:

  • 复杂度是否真正删除,而非藏入 adapter/wrapper。
  • 是否仍存在 manifest-as-state、path discovery、旧 schema 或 adapter 残留。
  • 是否意外把 contact timeline 或普通 scene interaction 塞进新模块。
  • 是否存在 .get() 默认掩盖缺失 required field。
  • 是否存在 hidden mutation、array alias、shape ambiguity、left/right/both convention drift。
  • 正式 pipeline 是否仍能触达旧 backend selector。

I. OmniGrasp 重训 gate

  1. 找到的 prior run 必须是使用旧 cup-left motion、因 hand pose 不合理而暂停并直接触发本轮重构的最近一次 target-attributed contact-gate 修正版;用时间、配置路径和训练日志证明,不凭记忆选择。
  2. 新旧训练 config 的结构化 diff 只允许 reference motion/path、frame count/phase metadata 等输入派生项变化;policy observation、reward、PPO、action、contact filter 和 table removal 保持不变。
  3. 新 reference loader 必须保持 597 帧、pick/place frame、active left hand、object identity/scale/pose convention 和统一 SMPL-X shape。
  4. 训练前 deterministic/reference sanity:无 object teleport,pick/place hand pose继承通过,target-attributed contact label落在真实 object↔finger,而不是 support contact。
  5. 训练期间按原实验 cadence 保存 checkpoint 和 deterministic eval;不能只报告训练 reward。
  6. 最终 deterministic eval 必须完整运行既有正式 evaluation clip,不因 human/object tracking early termination 提前结束。
  7. pick/lift/carry 至少满足:形成 target-attributed active-hand contact、完成 lift、carry 期间 object 不掉落;object rotation reference 只作为弱诊断,不因 raw KIMODO reference 小角度偏差单独判失败。
  8. human tracking 不得出现 keyframe jerk 导致的瞬时爆炸;报告全身 mean error、active arm/hand error及其 pick/place window峰值,并与 prior run和新 kinematic reference对照。
  9. 输出训练曲线、最新 checkpoint、deterministic rollout trace、完整视频和 pick/place 慢放。

10. 停止、回退与完成条件

立即停止并修复:结构 gate、place 继承、constraint center/boundary、hand bake convention、object local binding 任一失败。

若新接口结构正确但 GPU motion 未过数值 gate,保留重构分支和失败 artifact,回到最后一个通过的阶段定位;不得恢复正式 backend selector或增加 case-specific rule。

正式 pick 固定使用已验收的完整生成规则;place 独立使用通用规则直到达到同等级效果。solver 内部不要求对称,但 place 仍必须满足相同领域接口、quality metric 和继承协议。不得用更差 pick 换取代码表面对称,也不得退回固定 place offset。

用户离线期间不等待人工视觉确认:先以数值 gate、keyframe render、contact sheet 和自动几何审计持续迭代,直到实现侧不存在已知异常,再生成视频供次日 final review。视频生成本身不代表目标完成。

只有 A–I 全部通过、reviewer 零阻断、OmniGrasp 重训与 deterministic rollout 完成,并输出待人工 review 的最终视频后,才把目标标记 complete。所谓“对实现有 100% 信心”在本计划中严格等价于这些预注册证据全部成立,而不是声称软件不存在任何未知缺陷。

11. 2026-07-23 当前执行结果

统一 scaffold/refiner 曾产生一个通过纯运动学 golden-relative gate 的候选:

output/auto_experiments/20260723_cup_left_hand_object_interaction_final_v14/motion.npz

  • 597 帧;pick/place 分别为 frame 98/568;pick 与 place 的 pose_hand bitwise equal。
  • strict hand-object audit、contact、opposition 均通过;active-hand <5 cm ratio 为 0.87228,高于 golden 0.87021
  • place 实际 inherited hand-object local relation 误差为 1.245 mm / 0.902 deg
  • pick ±10 帧 root/wrist/object 最大 step 为 0.751/1.359/1.105 cm,body SO(3) 为 2.455 deg,root acceleration 为 3.214 m/s²,hand-pose step 为 0.0582
  • place ±10 帧对应值为 2.246/2.809/2.247 cm4.897 deg9.727 m/s²0.0888,全部位于预注册 gate 内。
  • target object 从 place frame 起精确保持目标 world pose;无 release 后 object step。

同定义重复生成的 v17 保持 grasp/contact/relation 质量,但 pick root step/acceleration 为 1.019 cm / 4.652 m/s²,place frame 569 出现 12.171 m/s² 单帧 root acceleration spike,超过预注册 1.00 cm / 4.50 / 10.20 门,因此明确拒绝,不通过放宽阈值掩盖。

随后对 v14 运行了保持 policy/reward/action/contact-filter 不变的 C-PAIR-A Target-Contact OmniGrasp 物理执行门。1024-env fresh PPO 在 epoch 100/200/300/400/500 的 deterministic rollout 始终终止于 frame 114--115;最大 lift 分别约为 0.03/0.46/0.28/0.47/0.03 cm,从未达到 2 cm。实际 target-attributed contact 从始至终只覆盖 L_Thumb1/2/3,没有任何 index/middle/ring/pinky link;epoch 400 还出现约 10.3 kN 的拇指单侧挤压力。该结果证明 v14 的 mesh contact/opposition 指标不能代表 Isaac Gym articulated-link force closure,训练已陷入 one-sided thumb pressing。因此 v14 只保留为 kinematic candidate,不得再称为正式 motion,也不得用来证明统一 pick 规则非退化

由此正式设计固定为非对称内部实现:pick 原样使用 20260723_cup_left_map_free_smooth_root2d_10f 对应的 accepted rule,place 独立使用 general + simple 规则达到相同层级的手型、接触、人体自然度和时序质量。该非对称只存在于内部 solver;InteractionKeyframe、坐标约定、quality evaluator、一次 KIMODO、hand bake 与 object binding/release 合约统一。正式 pipeline 没有运行时 selector、旧字段读取或兼容 adapter。禁止为表面对称降低 pick,也禁止对象/support/cup 分支或固定 PLACE_WRIST_OFFSET

新增 pick hard gate:除 mesh contact/opposition 外,必须在 Isaac Gym target-attributed trace 中形成至少一个 thumb link 与至少一个 non-thumb finger link 的持续目标物接触,并完成 lift/hold;仅拇指接触无论 mesh 指标多高均判失败。该 gate 按交互手的通用解剖分组定义,不依赖对象类别。

结构与测试证据:核心定向回归覆盖 motion schema、scaffold input、pick/place generation、hand bake、binding、pipeline 和 wrist-correction,共 307 passed;扩展到 approach、geometry、root despike、expected-contact、interaction-scaffold 和 SMPL-X/PHC-X hand contract 后共 352 passed。相关模块 py_compilegit diff --check 均通过。静态扫描确认正式模块中不存在 MotionState/MotionInput、旧 hand artifact/path discovery、运行时 backend selector、临时 backend 名称或兼容 adapter,且唯一新增 dataclass 是 InteractionKeyframe。独立 reviewer 在修复 required heading/mode、旧 hand artifacts、exact motion schema 和 producer/consumer 的 hand_pose_schedule 键不一致后重新复核,最终结论为零结构 blocker;其最终定向复核为 35 passed

加入显式 50 cm OmniGrasp curriculum 参数后,当前定向回归把上述 HSI generation、SMPL-X/PHC-X hand contract 与 Strict OmniGrasp runner/monitor 合并重跑,共 381 passed;单独 runner/monitor 契约为 14 passed。这证明 ET 修改没有进入或改变 InteractionKeyframe → constraints → one KIMODO → hand bake → binding 数据流。

v14 的历史可视化产物:

  • full scene:output/auto_experiments/20260723_cup_left_hand_object_interaction_final_v14/human_left_full_scene.mp4
  • 去遮挡 interaction-only:output/auto_experiments/20260723_cup_left_hand_object_interaction_final_v14/human_left_interaction_only.mp4
  • keyframe sheet:output/auto_experiments/20260723_cup_left_hand_object_interaction_final_v14/human_left_interaction_contact_sheet.png

P7 的 v14 bounded run 已在 epoch 500 按停止规则终止;最新 checkpoint 与 trace 位于 output/auto_experiments/20260723_hand_object_interaction_v14_target_contact_omnigrasp_overfit_0_219_2000e。它只作为“统一内部 solver 会降低 pick 物理质量”的反例保留。

按正式的 accepted pick rule + general place rule 重新生成的唯一当前候选为:

output/auto_experiments/20260723_cup_left_hand_object_interaction_v20/motion.npz

  • 从 task plan、layout 和 seed 41 完整生成 597 帧,不读取 golden motion 或旧 manifest 作为运行时输入。
  • pick/place 分别为 frame 98/568;两者的 canonical hand_pose bitwise equal。
  • pick 完整保留已验收生成协议;place 独立求解但继承 pick 的 hand pose 与 hand-object local SE(3)。
  • place 实际 inherited local relation 误差为 1.840 mm / 0.806 deg,通过统一的 5 mm / 2 deg 门。这里的 5 mm 是类别无关的局部关系保真阈值,不是 cup-specific 几何规则;先前 2 mm 会把 solver 的无害数值差异误判成协议失败。
  • pick/place keyframe penetration proxy 为 2.609/2.679 mm;完整 approach 序列的 active forearm/hand 最大 penetration 诊断为 27.08 mm。按本轮约定,约 3 cm 内的序列碰撞只报告、不单独否决。
  • strict hand-object audit、contact、opposition 和 body-naturalness 均通过;active-hand <5 cm ratio 为 0.86059,opposition ratio 为 1.0
  • frame 98–500 的 object–left-wrist local position/rotation 最大 drift 为 2.04e-7 m / 5.16e-6 deg;frame 97→98 object position jump 为 4.55e-7 m,通过 binding 连续性硬门。
  • pick ±10 帧 root/wrist/object 最大 step 为 0.459/1.186/1.114 cm,body SO(3) 为 2.479 deg,root acceleration 为 2.359 m/s²,hand-pose step 为 0.0494
  • place ±10 帧对应值为 2.357/2.915/2.237 cm4.912 deg10.118 m/s²0.0754,全部位于预注册 gate 内。
  • v20 相对 accepted golden 的 frame-98 active wrist 位置差为 5.97 mm,local body rotation mean/max 为 0.229/1.902 deg;因此 pick 未因 place API 重构而退化。

v20 的 Strict OmniGrasp smoke 已验证 pure PPO、2456D actor observation、48D latent action、target-attributed Object-Finger contact 和完整 219 帧 deterministic rollout 的工程契约均可运行。与 v14 的结构化 experiment diff 只有 motion/reference 路径以及输入派生的 geometric-contact frame 84→82;contact-reward/lift/table-removal 仍为 97/106/123,policy、reward、PPO、action 和 contact classifier 未变。smoke 仅训练 2 epochs,其 reward/contact/tracking 数值不用于判断收敛。正式 1024-env bounded fresh overfit 必须从零开始、每 100 epochs deterministic eval,并以真实 thumb + non-thumb target contact、lift/hold 和 human tracking 作最终物理 gate。

11.1 Object-error termination curriculum

v20 fresh overfit 的 epoch-400 checkpoint 在旧 12 cm object-position early termination 下于 frame 161 结束;终止不是 human fall 或 human-tracking IET。对同一 checkpoint 关闭 object ET 的 deterministic 诊断能运行完整 [0,219)219/219、最大 lift 51.24 cm、持续 lift 108 帧,并形成 thumb 与 non-thumb target-attributed contact。因此旧结果至少已经证明 grasp/lift discovery,而 12 cm 会在 long carry 偏差出现时截断后续状态。

当前 single-case curriculum 按用户确认改为显式 50 cm object-position ET。该值同时进入训练和 deterministic eval,不只在评估端修改;observation、reward、PPO、48D latent action、target-attributed contact gate、human IET 和 table removal 均不变。runner/monitor 必须在 CLI 与 provenance 中记录 object_termination_distance_m=0.50。旧 12 cm trace 只作为 strict diagnostic comparator,不再作为当前 overfit 的 rollout-completion gate;no-ET 的 1000 m 只允许作为定位上界,不是正式配置。

50 cm 只是“先获得完整 physics rollout”的 curriculum 阈值,不能被解释成最终 object tracking 已经良好。每次 deterministic eval 仍必须分别报告:

  • 是否完整 219/219
  • 首次超过 12/30/50 cm 的 frame;
  • object position mean/RMSE/p95/max;
  • human body mean/p95 与 pick/carry 分段误差;
  • target thumb/non-thumb contact、lift/hold/drop;
  • 最大 target-attributed force。

50 cm eval 仍提前结束,先根据 no-ET trace 判断是后段 human drift、接触丢失、object drop 还是 reference mismatch,再继续训练;不得继续无依据放宽 ET。最终模型资格仍要求完整 rollout、真实多指接触、lift/hold 以及可接受的人体执行质量,不能只凭放宽阈值通过。

同一旧 12 cm 训练阶段的 checkpoint 在新阈值下得到以下基线:

Checkpoint 50 cm eval frames Max lift Longest lift hold Max target links Human mean 末帧 object error
epoch 400 180/219 56.93 cm 69 5 30.96 cm >50 cm
epoch 500 183/219 55.55 cm 71 8 29.89 cm 50.27 cm
epoch 600 (50 cm train) 184/219 54.36 cm 72 8 30.50 cm >50 cm
epoch 700 (50 cm train) 206/219 54.83 cm 95 7 32.41 cm >50 cm
epoch 800 (50 cm train) 219/219 54.33 cm 107 7 34.33 cm <50 cm

epoch-500 no-ET trace仍可完整 219/219,但后段误差没有自行消失:object p95 1.274 m、human mean/p95 0.391/1.073 m。这与旧训练分布一致:policy 能建立抓握和 lift,但 12 cm training ET 使多数 episode 无法覆盖后段。因此下一步不是继续只改 eval,而是从 epoch 500 checkpoint 在训练端启用 50 cm,每 100 epochs 做一次同阈值 deterministic eval。

第一段 50 cm train(epoch 500→600)使训练 episode mean length 从约 154 提升到约 168,deterministic contact gate ratio 达 0.942、thumb ratio 0.919,但完成帧只从 183 提升到 184。这说明 grasp/contact 已稳定,而 carry 后段仍可能进入平台;按预注册停止规则再续训到 epoch 700。若仍停在 183–185,不再无限增加同配置 epoch,转为只改变一个 human/carry curriculum 变量的对照。

epoch 700 没有停在平台,而是推进到 206/219;longest lift hold 95 帧、contact gate 0.963。因此不启用预注册的 lambda_human ablation,不改变 reward;继续同一 50 cm / lambda_human=0.5 配置到 epoch 800,以保持单变量因果解释。human mean/p95 仍为 0.324/0.750 m,且最大 attributed force 64.7 kN,所以即使下一次达到完整帧数,也只能先称为 rollout-completion milestone,不能直接称为高质量最终 tracker。

epoch 800 首次通过 rollout-completion milestone:219/219、completion 1.0、final object lift 51.12 cm、longest lift hold 107 帧、target-contact gate 0.983,object position mean/RMSE/p95 为 0.100/0.183/0.438 m,均未触发 50 cm ET。该结果证明 accepted-pick + general-place v20 reference 能被当前 pure-PPO OmniGrasp adaptation 学成完整可执行 pick clip。

但完整帧数不等于最终 tracker 通过:human body mean/p95 仍为 0.343/0.795 m,超过 0.15/0.30 m gate;最大 target-attributed force仍为 32.7 kN,且 index contact ratio为 0(non-thumb contact由 middle/ring/pinky 提供)。因此 result.jsonpassed=false 是正确的;epoch 800 只能标作“first complete physics rollout”,后续先做 no-ET 一致性与视频,再按预注册 lambda_human ∈ {0.25,0.5,1.0} 单因素改善 human drift,不能修改 grasp/contact 定义。

同一 epoch-800 checkpoint 的 no-object-ET 对照也完整 219/219:final lift 36.69 cm、hold 107 帧、contact gate 0.959、object p95 0.425 m、human mean/p95 0.338/0.693 m。它与 50-cm trace 不逐数组相同,因为当前 Isaac Gym/PhysX 运行记录明确为 torch_deterministic=False;但两次独立 deterministic-policy rollout 都完整并维持 lift/contact,排除了“恰好被 ET bookkeeping 判成完成”的解释。下一分支从 epoch 800 恢复,只把 outer lambda_human0.5 改为 1.0,其余保持不变。

epoch-800 50-cm physics trace 已用 Isaac Sim 按实际 rigid-body transforms(replay body error严格为 0)渲染完整 219 帧 full-scene 左视角视频:

output/auto_experiments/20260723_hand_object_interaction_v20_target_contact_omnigrasp_et50cm_resume500_1000e/evaluations/epoch_00000800_et50cm/physics_rollout_human_left_full_scene.mp4

最终帧:

output/auto_experiments/20260723_hand_object_interaction_v20_target_contact_omnigrasp_et50cm_resume500_1000e/evaluations/epoch_00000800_et50cm/physics_rollout_human_left_final.png

自动数值与最终帧视觉结论一致:object仍随手保持在空中,但人体上身/四肢已经严重偏离 reference。视频证明 physics completion,也同时否决“人体 tracking 已合格”。

预注册的 lambda_human=1.0 单因素分支从 epoch 800 恢复并训练到 epoch 900,其 50-cm deterministic eval 仍完整 219/219。相对 lambda_human=0.5 epoch 800:

  • human mean/p95 从 0.343/0.795 m 小幅改善到 0.336/0.745 m
  • max attributed force 从 32.7 kN 降到 16.2 kN
  • index contact ratio从 0 提升到 0.190
  • 但 contact gate从 0.983 降到 0.760,max active links从 7 降到 5

因此 lambda_human=1.0 暂时是可行但未充分的 trade-off,不足以解决人体漂移。按有界规则只再续训到 epoch 1000;若 human error 仍远高于 gate,不再继续放大 outer weight或无限加 epochs。

20260718_fullref_intermimic_teacher_v8_phc_warmup human-only checkpoint 也做了只读迁移诊断。它在当前 v20 reference 上虽运行 219/219,human mean/p95 却为 1.399/2.179 m,且无 lift/contact;旧 motion 与 online normalizer 分布不能复用。若后续采用 human-only curriculum,必须在当前 v20/fixed-shape reference 上从头训练,不能用旧 checkpoint 伪装 warm start。

lambda_human=1.0 到 epoch 1000 后仍完整 219/219,object p95 0.403 m、final lift 44.20 cm、contact gate 0.967;但 human mean/p95 为 0.340/0.744 m,没有优于 epoch 900 的 0.336/0.745 m,最大 attributed force反而升到 42.0 kN。因此该 scalar 分支按规则停止:epoch 900 是 human/force trade-off 较好的 checkpoint,epoch 800 是 contact/force更稳定的首个完整 baseline;两者都不通过最终 human gate。下一步不能再调 outer scalar,只能把 current-v20 fresh human-only warm-up 作为新的 curriculum 实验,且必须与 strict combined training 分阶段隔离。

current-v20 fresh human-only warm-up 使用同一 motion.npz、统一 SMPL-X shape、2456D actor observation、48D PULSE-X latent action、frame-0 start 与原生 PHC/PULSE imitation reward;它只把 reward 临时切为 human-only,并启用 human imitation termination。该实验不是新的正式 policy 定义,也不能用前段误差代替完整序列验收。deterministic 结果为:

Checkpoint Eval coverage Human position mean Human position p95
epoch 50 25/219 10.18 cm 18.92 cm
epoch 100 75/219 9.84 cm 16.90 cm
epoch 150 94/219 8.60 cm 15.77 cm
epoch 200 129/219 8.81 cm 16.25 cm
epoch 250 149/219 8.62 cm 16.59 cm
epoch 300 169/219 8.83 cm 17.38 cm
epoch 350 174/219 7.58 cm 16.08 cm
epoch 400 179/219 7.01 cm 14.85 cm

coverage 连续增长、有效区间误差稳定低于 combined policy,说明 fresh warm-up 确实在学习当前 reference,而非靠放宽 object ET 延长 rollout;但 epoch 350→400 只推进 5 帧,coverage 已开始平台。epoch 400 的有效区间 position error 很低,却仍在 179/219 终止,因此停止继续单独 human-only。下一步先在 strict combined task 对 epoch-400 checkpoint 做 zero-step 诊断,再只把 reward 切回正式 original OmniGrasp + 0.5 × PHC/PULSE human、target-attributed contact 与 50 cm object ET,保持 observation、48D latent、PPO、reference 和 frame-0 start 不变,训练到 epoch 500。只有迁移后的 policy 同时通过 full rollout、human、target-contact 与 lift/hold gate,才把该 curriculum 纳入正式训练协议。

epoch-400 checkpoint 的 strict combined zero-step 诊断运行到 131/219,human position mean/p95 保持在 6.77/14.60 cm,证明 actor 与 online normalizer 可兼容迁移;但 target-contact、thumb/index contact 与 lift 全为 0。support 在 frame 123 按正式协议移除后,未被抓取的物体下落并最终触发 object ET。该结果把下一阶段目标明确限定为:在不破坏低 human error 的前提下,让 combined PPO 在 table removal 前发现 target-attributed 承载抓握。已从该 checkpoint 启动 epoch 400→500 fine-tune,其余配置不变。

epoch 500 deterministic eval 仍为 131/219;human mean/p95 为 8.01/16.12 cm,active-hand mean 7.08 cm,但 target-contact、lift 与 active target link 数仍全部为 0。手到物体表面的最小距离约 3.78 cm。对照 v20 from-scratch 分支在自己的 epoch 100 已出现 0.176 target-contact ratio,说明 human warm start 的局部动作分布明显压缩了 grasp exploration。为区分“发现较晚”与“已陷入 human-only 局部最优”,保持相同配置追加最后 500→600 的 100-epoch bounded budget;若 epoch 600 仍无 target contact/lift,则停止该迁移路线,不再无界续训。

epoch 600 不再是零接触:target-contact ratio 为 0.364、thumb ratio 0.394、最近 surface distance 1.73 cm,human mean/p95 仍为 8.84/20.57 cm。但接触最多只覆盖 2 个 active links,index ratio 为 0,最大 lift仅 0.08 cm,rollout仍为 131/219;当前是拇指侧接触发现,不是 force closure。由于它已经跨过“完全不探索”的停止条件,保持 lambda_human=0.5 与全部其他配置不变,允许再续训 600→700,以 non-thumb contact、≥2 cm lift 和 rollout推进作为下一判据。

反向 curriculum 也做了有界对照:从已成功抓取的 epoch-800 policy 切到 human-only 20 epochs,同时保持正式 support removal。human IET 令训练 episode length立即缩到约 6–8 帧;epoch 820 strict eval 只有 130/219、human mean/p95 27.87/48.42 cm、contact gate 0.188,最大 lift仅 0.89 cm。它既破坏了原有承载抓握,也没有把人体拉回最终 gate,因此判负。

另一个并行单变量分支从同一 human epoch-400 checkpoint 出发,只在 grasp-discovery 阶段把 lambda_human0.5 暂降到预注册的 0.25,其余 observation、48D latent、PPO、target contact、table removal、frame-0 start 与 50 cm ET 完全一致。该分支检验当前零接触是否来自接近物体时 human reward损失过强;若能发现 target contact/lift,后续必须恢复正式 0.5 并重新通过 human gate,不能以 0.25 直接冒充最终方案。

12. 2026-07-24 最终接口与 main-pipeline parity 验收

用户已于 2026-07-24 明确确认 v20 的完整时序可视化,故 output/auto_experiments/20260723_cup_left_hand_object_interaction_v20/validation.json 中的 temporal render gate 正式记为 accepted;该确认只作用于既有 v20 artifact, 不允许用来跳过后续接口回归。

独立 reviewer 的第一轮复核发现两个代码收口 blocker:正式 contact -> grasp.py -> grasp_backend 传递图仍间接到达旧 runtime selector; InteractionKeyframe 的 fail-fast 组合虽由实现支持,但没有完整固化成单测。 修复严格限定在接口边界,未修改 v20 motion、grasp 参数、sequence 逻辑或 OmniGrasp checkpoint:

  • 新增纯 scene-contact 领域模块 utils/hsi_generation/scene_contact_hand.py;正式 pipeline -> constraint -> contact/keyframe 依赖图不再 import grasp.pygrasp_backend.py、map-free/ContactGen pick dispatch 或旧 backend selector。
  • keyframe.py 直接持有其所需的 hand-policy 与 place-constraint 领域查询, 不再为四个小函数导入整个 legacy grasp 模块。
  • InteractionKeyframe 单测现覆盖 pick/place × left/right/both 六种合法组合, 并覆盖非法 phase/hand/frame、负数/非整数 frame、NaN/Inf、zero heading、 quality 缺键/多键及 both-hand 使用单手 local-SE(3) shape 的 fail-fast。
  • 正式传递边界的静态测试扩展到 pipeline.py/constraint.py/contact.py/keyframe.py/scene_contact_hand.py/hand_object_interaction.py, 不再只扫描两个顶层文件。

第二轮 reviewer 又发现 enabled pull 的 direct-contact producer 仍返回旧 {"artifact": schedule.json},而 canonical hand consumer 只接受内存 {"frame_indices": ..., "hand_pose": ...};该路径会在 hand bake 前稳定触发 KeyError("frame_indices")。现已删除 schedule JSON/hand-target NPZ 的运行时 handoff,producer 直接返回只读的 explicit-frame (N,) + (N,90) 数组, constraint 原样传递,manifest 只记录 frame range/count provenance。新增测试 用 mock heavy solver 贯通 scene_contact_hand -> _record_contact_object -> _resolve_hand_inputs -> _hand_pose_trajectory, 同时验证 quintic fade-in/hold/fade-out、无 artifact/path 和 active-hand 写入。

当前工作树的 motion/schema、scaffold、interaction、pipeline、hand bake、 binding、contact、SMPL-X/PHC-X、Strict OmniGrasp 与 backend-isolation 综合 回归为 407 passed in 15.22s。六个正式模块 py_compile、定向 git diff --check、旧 selector/import 字符串扫描和 hand_object_interaction.py.get() 审计均通过。

第三轮独立 reviewer 对 enabled-pull 修复做了 fresh-process 复审,结论为 零阻断:内存 schedule 完整贯通 scene_contact_hand -> constraint -> hands,fade/hold 数值正确;正式 import graph 未加载 grasp.pygrasp_backend.py,main pipeline 仍只有 一次 kimodo.generate_scaffold(...),且未发现 manifest-as-state、旧 schema adapter、不必要 wrapper 或 legacy 复杂度重新流入正式依赖图。

为验证接口清理没有只在 mock/test 中成立,使用与 v20 完全相同的 task_plan_left.json、SAGE layout、seed 41 和正式 tools/run_hsi_generation.py -> pipeline.run() 在 GPU 1 重新完整生成:

output/auto_experiments/20260724_cup_left_hand_object_interaction_interface_parity_rerun

该 run 只包含一次顶层 generate_scaffold/KIMODO 调用,输出同样的 32 个 canonical motion fields 和 597 帧;pick/place 仍为 98/568、active hand 仍为 left,pick/place hand pose bitwise equal,且四个 interaction quality gate 全部通过。它不是 bitwise replay:当前 refiner candidate 相对 v20 的 pick/place wrist 位置差为 1.617/1.605 cm,root 位置差为 4.786/4.482 cm,hand-pose RMSE/max 为 0.090/0.267 rad。因此 parity 定义为类别无关的领域/质量等价,而不是冻结某个随机优化 candidate。

新 run 的内部硬指标全部通过:

  • frame 98–500 hand-object carry relation position drift: 2.05e-7 m
  • place inherited relation:0.518 mm / 0.246 deg,优于 v20 的 1.840 mm / 0.806 deg
  • maximum root step/acceleration/joint step: 2.804 cm / 1.462 cm / 0.225 rad
  • active-hand <5 cm ratio:0.85243,opposition ratio 1.0
  • 最大 active forearm/hand penetration:2.778 cm,仍位于用户确认的 约 3 cm 诊断容差内;
  • strict hand-object、grasp semantic、body motion、binding continuity 与 pick/place quality gate 全部通过。

机器可判定 parity 记录为:

output/auto_experiments/20260724_cup_left_hand_object_interaction_interface_parity_rerun/parity_report.json

v20 与新 main-pipeline run 的 pick/place 并排 keyframe 审计图为:

output/auto_experiments/20260724_cup_left_hand_object_interaction_interface_parity_rerun/v20_vs_parity_pick_place.png

OmniGrasp 当前正式物理结论仍使用已经训练完成且用户确认可查看的 v20 epoch-800 rollout:219/219、最大/最终 lift 54.33/51.12 cm、hold 107 帧、target-contact ratio 0.9835。按用户最新决定,当前目标是验证 OmniGrasp object grasp/lift 执行,human tracking error 保留为诊断量而不再 阻断本版 baseline;这不把 OmniGrasp 重新定义为 full-reference human tracker,也不删除历史 human-error 实验记录。