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>
This commit is contained in:
liyang
2026-09-17 11:27:46 +08:00
parent 7e4ef6f98b
commit ae28d55f81
761 changed files with 55598 additions and 59 deletions
+29
View File
@@ -0,0 +1,29 @@
"""Build a SPIDER task directory from a kinematic reference directory and apply the validated physics settings.
Env: SPIDER_SRC (reference dir with datasets/.../boxes, reference_video_rate.npz, config.json), SPIDER_TASK_OUT (target).
Settings follow output/spider_dynamics_fix_20260915/physics_parameters.json (simulation assumptions, not hardware)."""
import os, json, shutil, xml.etree.ElementTree as E
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]; SRC = Path(os.environ['SPIDER_SRC']); OUT = Path(os.environ['SPIDER_TASK_OUT'])
T = OUT / 'datasets/processed/current/l20/bimanual/boxes'; (T / '0').mkdir(parents=True, exist_ok=True)
for rel in ['datasets/processed/current/l20/bimanual/boxes/scene_act.xml', 'datasets/processed/current/l20/bimanual/boxes/task_info.json', 'datasets/processed/current/l20/bimanual/boxes/0/trajectory_kinematic_act.npz', 'reference_video_rate.npz']:
shutil.copy2(SRC / rel, OUT / rel)
cfg = json.loads((SRC / 'config.json').read_text()); cfg['dataset_dir'] = str(OUT / 'datasets'); cfg.update(json.loads(os.environ.get('SPIDER_CONFIG_OVERRIDES', '{}'))); (OUT / 'config.json').write_text(json.dumps(cfg, indent=2))
for name in ['collision_v2', 'hand_collision']:
if not (OUT / name).exists(): os.symlink(os.path.relpath(ROOT / 'output/collision_fix_20260915' / name, OUT), OUT / name)
p = T / 'scene_act.xml'; tree = E.parse(p); r = tree.getroot()
r.find('option').set('iterations', '80'); r.find('option').set('ls_iterations', '50')
for g in r.findall('.//geom'):
g.set('solimp', '.9 .95 .001 .5 2'); g.set('solref', '.02 1')
if g.get('contype') in ['1', '2', '4']: g.set('margin', '.004'); g.set('gap', '.002')
for a in r.findall('actuator/position'):
n = a.get('name')
if '_object_' in n: continue
if '_hand_pos_' in n: kp, kv, limit = 500, 30, 20
elif '_hand_rot_' in n: kp, kv, limit = 15, 2, 2
else: kp, kv, limit = float(os.environ.get('HF_FINGER_KP', '4')), float(os.environ.get('HF_FINGER_KV', '.15')), float(os.environ.get('HF_FINGER_TORQUE', '.1'))
a.attrib.update(kp=str(kp), kv=str(kv), forcerange=f'{-limit} {limit}')
tree.write(p)
settings = {'solver_iterations': 80, 'ls_iterations': 50, 'wrist_position_kp': 500, 'wrist_position_kv': 30, 'wrist_force_cap_N': 20, 'wrist_rotation_kp': 15, 'wrist_rotation_kv': 2, 'wrist_torque_cap_Nm': 2, 'finger_kp': float(os.environ.get('HF_FINGER_KP', '4')), 'finger_kv': float(os.environ.get('HF_FINGER_KV', '.15')), 'finger_torque_cap_Nm': float(os.environ.get('HF_FINGER_TORQUE', '.1')),
'contact_solimp': [.9, .95, .001, .5, 2], 'contact_solref': [.02, 1], 'contact_activation_distance_m': .002, 'table_collides_with_hands': True,
'note': 'Same contact regularization and 2 mm activation as spider_dynamics_fix_20260915 (selected by GPU/CPU short replay); table now a hand collider. Simulation parameters, not measured hardware.', 'source_reference': str(SRC)}
(OUT / 'physics_parameters.json').write_text(json.dumps(settings, indent=2)); print('configured', OUT)