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
+4 -1
View File
@@ -118,7 +118,10 @@ def _assert_object_actuator_gains_zero(
if biasprm.ndim == 3:
biasprm = biasprm[0]
kp = gainprm[actuator_ids, 0]
kd = -biasprm[actuator_ids, 1]
kd = -biasprm[actuator_ids, 2]
assert np.allclose(biasprm[actuator_ids], 0.0, atol=atol), (
f"Object actuator affine bias not zero at {stage}"
)
assert np.allclose(kp, 0.0, atol=atol), (
f"Object actuator Kp not near zero at {stage}: max={np.max(np.abs(kp))}"
)
+3 -1
View File
@@ -172,7 +172,9 @@ def make_rollout_fn(
copy_sample_state(config, env, good_indices, bad_indices)
# Replace bad samples control with good samples (for initial control and current timestep only)
ctrls[bad_indices, :t] = ctrls[good_indices, :t]
# State has already advanced through t; its causal prefix must
# include this control too, otherwise replay is inconsistent.
ctrls[bad_indices, : t + 1] = ctrls[good_indices, : t + 1]
# Replace bad samples cumulative reward with good samples reward
cum_rew[bad_indices] = cum_rew[good_indices]
+16 -5
View File
@@ -172,13 +172,14 @@ def setup_env(config: Config, ref_data: tuple[torch.Tensor, ...]) -> MJWPEnv:
def _weight_diff_qpos(config: Config) -> torch.Tensor:
w = torch.ones(config.nv, device=config.device)
if config.embodiment_type == "bimanual":
half_dof = int(config.nu // 2)
# The state includes passive joints, unlike the actuator vector.
half_dof = int((config.nv - 12) // 2)
w[:3] = config.base_pos_rew_scale
w[3:6] = config.base_rot_rew_scale
w[6:half_dof] = config.joint_rew_scale
w[half_dof : half_dof + 3] = config.base_pos_rew_scale
w[half_dof + 3 : half_dof + 6] = config.base_rot_rew_scale
w[half_dof + 6 : config.nu] = config.joint_rew_scale
w[half_dof + 6 : -12] = config.joint_rew_scale
# object: weights live in nv-space (6-dim per freejoint), regardless of nq_obj
w[-12:-9] = config.pos_rew_scale
w[-9:-6] = config.rot_rew_scale
@@ -648,7 +649,7 @@ def get_reward(
contact_pos = site_xpos_torch[:, config.contact_site_ids]
contact_dist = torch.norm(contact_pos - contact_pos_ref, p=2, dim=-1)
contact_dist_masked = contact_dist * contact_ref.unsqueeze(0)
contact_rew = -contact_dist_masked.sum(dim=1)
contact_rew = -config.contact_rew_scale * contact_dist_masked.sum(dim=1)
else:
contact_rew = 0.0
@@ -990,7 +991,12 @@ def save_env_params(config: Config, env: MJWPEnv):
# convert it to torch would lead to OOM
pair_margin = 0.0
xy_offset = 0.0
return {"pair_margin": pair_margin, "xy_offset": xy_offset}
params = {"pair_margin": pair_margin, "xy_offset": xy_offset}
if config.object_actuator_ids:
ids = config.object_actuator_ids
params["kp"] = env.model_cpu.actuator_gainprm[ids, 0].copy()
params["kd"] = -env.model_cpu.actuator_biasprm[ids, 2].copy()
return params
def load_env_params(config: Config, env: MJWPEnv, env_param: dict):
@@ -1071,7 +1077,9 @@ def load_env_params(config: Config, env: MJWPEnv, env_param: dict):
# Update CPU model (used for viewer and as source of truth)
env.model_cpu.actuator_gainprm[actuator_ids, 0] = kp_np
env.model_cpu.actuator_biasprm[actuator_ids, 1] = -kd_np
# Affine servo force: kp * ctrl - kp * length - kd * velocity.
env.model_cpu.actuator_biasprm[actuator_ids, 1] = -kp_np
env.model_cpu.actuator_biasprm[actuator_ids, 2] = -kd_np
# Propagate to MJWarp model if available
if hasattr(env.model_wp, "actuator_gainprm") and hasattr(
@@ -1132,6 +1140,9 @@ def _broadcast_state(data_wp, num_worlds: int):
# Additional core state variables
qacc0 = wp.to_torch(data_wp.qacc)[:1]
wp.copy(data_wp.qacc, wp.from_torch(qacc0.repeat(num_worlds, 1)))
# A new MPC batch must not inherit warmstarts from failed candidate worlds.
warmstart0 = wp.to_torch(data_wp.qacc_warmstart)[:1]
wp.copy(data_wp.qacc_warmstart, wp.from_torch(warmstart0.repeat(num_worlds, 1)))
act0 = wp.to_torch(data_wp.act)[:1]
wp.copy(data_wp.act, wp.from_torch(act0.repeat(num_worlds, 1)))