"""[feetech_calib] Build a portable MuJoCo bundle for the UMI gripper (v3 handle).
Injects placeholder inertia (kinematic viz only) so MuJoCo compiles, copies meshes,
verifies load from a foreign cwd (proves mesh paths resolve relative to the URDF)."""
import re, os, shutil
SRC = "umi_gripper_v3_handle.urdf"
OUT = "gripper_bundle"
os.makedirs(OUT, exist_ok=True)
x = open(SRC).read()
INERT = ('<inertial><origin xyz="0 0 0" rpy="0 0 0"/><mass value="0.02"/>'
         '<inertia ixx="1e-5" ixy="0" ixz="0" iyy="1e-5" iyz="0" izz="1e-5"/></inertial>')
def add_inertia(m):
    link = m.group(0)
    if "<inertial" in link:
        return link
    return re.sub(r'(<link name="[^"]+">)', r"\1" + INERT, link, count=1)
x2 = re.sub(r'<link name="[^"]+">.*?</link>', add_inertia, x, flags=re.S)
open(os.path.join(OUT, "gripper.urdf"), "w").write(x2)
meshes = sorted(set(re.findall(r'filename="([^"]+)"', x2)))
for f in meshes:
    shutil.copy(f, os.path.join(OUT, os.path.basename(f)))
print(f"bundle: gripper.urdf + {len(meshes)} meshes -> {OUT}/")

import mujoco
here = os.getcwd()
os.chdir("/tmp")  # foreign cwd: proves mesh paths resolve relative to the URDF file
model = mujoco.MjModel.from_xml_path(os.path.join(here, OUT, "gripper.urdf"))
jid = mujoco.mj_name2id(model, mujoco.mjtObj.mjOBJ_JOINT, "jaw")
print(f"LOADED nq={model.nq} jaw qposadr={int(model.jnt_qposadr[jid])} range={model.jnt_range[jid]}")
