Hand–Object Interaction 领域接口重构与验收计划(2026-07-23)
1. 目标
把当前分散在 grasp.py、constraint.py、hands.py、binding.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. 范围与非目标
本轮必须完成:
- 新增
utils/hsi_generation/hand_object_interaction.py,成为正式 pick/place interaction keyframe 的唯一公共领域入口。 - 用 frozen
InteractionKeyframe在内存中连接 keyframe generation、constraint preparation、hand bake、object binding/release 和 evaluation。 - place 严格继承 pick 的
hand_pose与 hand–object local SE(3),只允许调整 root translation、root heading、body pose 和交互侧 shoulder/elbow/wrist。 - 正式实现直接采用
accepted pick rule + general place rule。已验收 pick 生成规则保持完整不变;place 使用独立但通用的生成/优化规则达到相近效果。两个 phase 不要求共用 solver 内部实现,只共用InteractionKeyframe数据契约、坐标约定、同一 quality evaluator/metric、一次 KIMODO 与后续 bake/binding/release 接口。不存在运行时路径切换或旧字段兼容。 - 两个 interaction keyframe 必须在生成 motion 之前一次性加入同一份 constraints;完整 sequence 只调用一次 KIMODO,禁止 second pass 或生成后 splice keyframe。
- 正式 pipeline 固定为 accepted pick rule + general place rule;不再暴露
--grasp-backend、pick_grasp_backend或 backend context selector,正式代码/配置/manifest/测试也不使用临时 backend 名称。 - HOI-FHLI、ContactGen 等旧对照实现可以留在独立 baseline 工具中,但不能成为正式
pipeline.py/constraint.py的运行时分支或状态来源。 - 保留已验收的 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 数组并验证:
phase、active_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.npz、keyframe_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.py、constraint.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. 结构与静态接口(全部必须通过)
hand_object_interaction.py中恰好一个领域 dataclass:InteractionKeyframe。- 不存在
InteractionQuality、PickInteractionKeyframe、PlaceInteractionKeyframe、InteractionSolverResult。 pipeline.py、constraint.py不 import backend selector 或 baseline pick/place implementation。- 正式 CLI 不包含
--grasp-backend;默认 config 不包含pick_grasp_backend。 - 正式 manifest 不再写
pick_grasp_backend,使用pick_interaction/place_interactionprovenance。 - required quality keys 的消费者不用
.get()。 - phase handoff 不通过 manifest、目录扫描或中间 keyframe/hand-pose
.npz。 rg确认正式 import graph 无旧 selector;遗留名字只允许出现在 baseline 工具、历史文档或明确 legacy 文件。
B. InteractionKeyframe 单元测试(全部必须通过)
- left/right/both、pick/place 合法构造。
- 非法 enum、负 frame、错误 shape、NaN/Inf、非 rotation、零 heading、缺 quality key 全部 fail-fast。
- frozen field 不能重新绑定;每个 ndarray 不能原地修改。
- 输入数组修改不影响已构造对象,证明 defensive copy。
- both-hand local SE(3) shape 与单手 shape 严格区分。
- quality 输出键集合和 value type 精确一致。
C. Pick/Place 语义(全部必须通过)
- pick 输出 phase/frame/active hand 与 task action-template 一致。
- pick 使用 actual triangle mesh 和 metric scale,不使用 bbox/category shortcut。
- place 的 hand pose 与 pick bitwise equal。
- place 的 hand–object local position/rotation 与 pick bitwise equal。
- place 优化前后只允许 root、heading、body 与 active interaction-arm joint 改变;inactive arm 和 fingers 不变。
- quality 四个 boolean gate 必须显式读取并为真才允许进入 constraints。
- pick/place 的 solver/refinement 调用记录必须指向同一个公共 primitive;除 freeze mask、phase scaffold 和 target object pose 外,参数协议一致。
D. Constraint 语义(全部必须通过)
- ordinary task root2d → 10-frame bridge → fullbody interaction keyframe → active-hand orientation,顺序固定。
- bridge 窗口为
[frame-10, frame+10],受 segment boundary 裁剪;要求 grasp 两侧均至少一帧,否则明确失败。 - quintic smootherstep 两端 value/一阶/二阶导为 0;center 权重为 1。
- center root 精确等于
InteractionKeyframe.root_position[[0,2]];边界精确等于原 task root path。 - heading 沿原 task path;interaction solve 不优化 heading 时不引入 heading jump。
- 输入 base constraints 不被隐式共享修改;输出为新的普通 list/dict。
E. Pipeline 集成与命名(全部必须通过)
- mock pipeline 数据流严格为
pick_interaction → place_interaction → constraints → KIMODO → hand bake → binding/release。 - mock/spy 明确证明 pick/place constraints 在 KIMODO 调用前均已存在,且 full-sequence KIMODO call count 严格等于
1。 hands.bake不读取 hand pose artifact;binding 不读取 keyframe artifact。- KIMODO 之后不存在 pick/place full-body splice、second-pass inference 或 constraint regeneration。
- scene contact timeline 与
hand_object_interactions分离,push/pull/kick regression 不变。 - 旧 baseline selector 的测试转移到 baseline scope;正式入口测试明确拒绝旧参数。
- 全量 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_pose、hand_object_local_position、hand_object_local_rotation 必须与对应 pick bitwise equal,这是独立于碰撞容差的硬门。
任何一项失败都不能通过放宽阈值处理;必须定位是领域转换、constraint、hand bake、binding 还是模型非确定性。
G. 可视化 gate(全部必须人工确认)
必须输出:
- 完整 597-frame full-scene opaque video。
- frames 60–140、0.5× grasp-window 视频,标注原始 frame。
- 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
- 找到的 prior run 必须是使用旧 cup-left motion、因 hand pose 不合理而暂停并直接触发本轮重构的最近一次 target-attributed contact-gate 修正版;用时间、配置路径和训练日志证明,不凭记忆选择。
- 新旧训练 config 的结构化 diff 只允许 reference motion/path、frame count/phase metadata 等输入派生项变化;policy observation、reward、PPO、action、contact filter 和 table removal 保持不变。
- 新 reference loader 必须保持
597帧、pick/place frame、active left hand、object identity/scale/pose convention 和统一 SMPL-X shape。 - 训练前 deterministic/reference sanity:无 object teleport,pick/place hand pose继承通过,target-attributed contact label落在真实 object↔finger,而不是 support contact。
- 训练期间按原实验 cadence 保存 checkpoint 和 deterministic eval;不能只报告训练 reward。
- 最终 deterministic eval 必须完整运行既有正式 evaluation clip,不因 human/object tracking early termination 提前结束。
- pick/lift/carry 至少满足:形成 target-attributed active-hand contact、完成 lift、carry 期间 object 不掉落;object rotation reference 只作为弱诊断,不因 raw KIMODO reference 小角度偏差单独判失败。
- human tracking 不得出现 keyframe jerk 导致的瞬时爆炸;报告全身 mean error、active arm/hand error及其 pick/place window峰值,并与 prior run和新 kinematic reference对照。
- 输出训练曲线、最新 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_handbitwise equal。 - strict hand-object audit、contact、opposition 均通过;active-hand
<5 cmratio 为0.87228,高于 golden0.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 cm、4.897 deg、9.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_compile 与 git 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;两者的 canonicalhand_posebitwise 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 cmratio 为0.86059,opposition ratio 为1.0。 - frame
98–500的 object–left-wrist local position/rotation 最大 drift 为2.04e-7 m / 5.16e-6 deg;frame97→98object 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 cm、4.912 deg、10.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.json 的 passed=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_human 从 0.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_human 从 0.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依赖图不再 importgrasp.py、grasp_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.py 或 grasp_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–500hand-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 cmratio:0.85243,opposition ratio1.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 实验记录。