"""[feetech_calib] Verify the 180deg saddle: seats@q0, keys (rejects off-zero), lifts off +Z."""
import numpy as np, trimesh
sad   = trimesh.load("servo_zero_fixture.stl", force="mesh")
servo = trimesh.load("st3215.stl", force="mesh")

def yoke_at(deg):
    y = trimesh.load("yoke_fillet.stl", force="mesh")
    if deg:
        R = trimesh.transformations.rotation_matrix(np.radians(deg), [0,1,0], [-25.5,0,0])
        y.apply_transform(R)
    return y

def ivol(a, b):
    try:
        m = trimesh.boolean.intersection([a, b], engine="manifold")
        return 0.0 if m.is_empty else m.volume/1000.0
    except Exception: return -1.0

print(f"SEAT  servo∩saddle={ivol(sad,servo):.3f}  yoke∩saddle={ivol(sad,yoke_at(0)):.3f} cm3 (expect ~0)")
for d in (+6,-6,+12,-12):
    print(f"KEY   yoke@{d:+3d}° ∩saddle={ivol(sad,yoke_at(d)):.3f} cm3 (expect LARGE=rejected)")
for dz in (5,10,20):
    up = sad.copy(); up.apply_translation([0,0,dz])
    print(f"LIFT  saddle+{dz}mm: servo∩={ivol(up,servo):.3f}  yoke∩={ivol(up,yoke_at(0)):.3f} cm3 (expect ->0=removable)")
