Files
hand-motion-pipeline/scripts/audit_smooth_table_result.py
T
liyang ae28d55f81 Update to 2026-09-17 pipeline snapshot; add weights, L20 assets and recording via Git LFS
Source: RGB-D -> Dyn-HaMR -> L20 retargeting -> FoundationPose -> reference repair -> SPIDER,
documented in docs/PIPELINE_LATEST.md and docs/SETUP_AND_WEIGHTS.md. Adds FoundationPose and
nvdiffrast upstream snapshots, requirements/pipeline_venv.txt and the FoundationPose weight
manifest/downloader.

Assets (Git LFS): weights/ (WiLoR detector, HandFlow denoiser, UniDepth-L), FoundationPose
checkpoints, HaMeR checkpoint, Dyn-HaMR HMP model and BMC constraints, L20 URDF/meshes, the
20260915_171525 D405 recording and the two box CADs. MANO models are not redistributed
(third_party/hamer/_DATA/data/mano/README.txt). Environments, caches and run outputs excluded.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 11:43:37 +08:00

35 lines
1.9 KiB
Python

"""Audit filtered/projected reference for table and hand-object penetration."""
from pathlib import Path
import json
import numpy as np
import mujoco
ROOT = Path(__file__).resolve().parents[1]
O = ROOT / "output/desktop_smooth_fix_20260915"
z = np.load(O / "reference_video_rate.npz")
m = mujoco.MjModel.from_xml_path(str(O / "scene_act.xml")); d = mujoco.MjData(m)
floor = next(i for i in range(m.ngeom) if "_floor" in (m.geom(i).name or ""))
floor_z = float(m.geom_pos[floor][2])
result = {"frames": len(z["qpos"]), "floor_z_m": floor_z, "max_table_penetration_mm": 0.0,
"max_hand_object_penetration_mm": 0.0, "frames_table_over_0_5mm": 0,
"frames_hand_object_over_0_5mm": 0}
for row in z["qpos"]:
d.qpos[:] = row; mujoco.mj_forward(m, d)
floor_min = {"right": 1.0, "left": 1.0}
for g in range(m.ngeom):
n = m.geom(g).name or ""
if not n.startswith(("right_", "left_")) or m.geom_dataid[g] < 0:
continue
side = n.split("_")[0]; mid = int(m.geom_dataid[g]); a = int(m.mesh_vertadr[mid]); b = a + int(m.mesh_vertnum[mid])
v = m.mesh_vert[a:b: max(1, (b-a)//128)]
world = v @ d.geom_xmat[g].reshape(3,3).T + d.geom_xpos[g]
floor_min[side] = min(floor_min[side], float(world[:,2].min()-floor_z))
tp = max(0.0, -min(floor_min.values())) * 1000
hp = 0.0
for c in d.contact:
a,b = int(c.geom[0]), int(c.geom[1]); ta,tb = int(m.geom_contype[a]),int(m.geom_contype[b])
if {ta,tb} == {1,2}: hp = max(hp, max(0.0,-float(c.dist))*1000)
result["max_table_penetration_mm"] = max(result["max_table_penetration_mm"],tp); result["max_hand_object_penetration_mm"] = max(result["max_hand_object_penetration_mm"],hp)
result["frames_table_over_0_5mm"] += tp > .5; result["frames_hand_object_over_0_5mm"] += hp > .5
(O/"smoothing_table_validation.json").write_text(json.dumps(result,indent=2)); print(json.dumps(result,indent=2))