"""Mako: read-only probe of models/docking-arm/DockArm_Carousel.blend (never saved). Where the clamp head's parts are in the Tender's frame at BOARD (arm 1 let down 5.3 m, the Tender hanging with its origin 1.94 m under the wrist and the clamp axis at (0, -0.09)), claws shut and open: for every head part within 0.9 m of the clamp axis and below z 1.8, its lowest point, its radius range from the axis and its azimuth range (deg from the Tender's +X, port, toward +Y, aft). Tells how small the holder clips can be: the claw pads must find a clip wall behind them, the landing feet a clip top under them. Writes checks/head_parts.json.""" import bpy, os, json, math from mathutils import Vector, Matrix HERE = os.path.dirname(os.path.abspath(__file__)) arm = bpy.data.objects["Arm1"] parts = [o for o in bpy.data.objects if o.type == 'MESH' and o.name.startswith("Arm1_")] dg = bpy.context.evaluated_depsgraph_get() out = {} for claw in (0.0, 1.0): arm["lower_m"] = 5.3 arm["claw_open"] = claw for ob in bpy.data.objects: if ob.name.startswith("Arm1"): ob.update_tag() bpy.context.view_layer.update() dg.update() head = bpy.data.objects["Arm1_Head"].matrix_world o = head.translation - Vector((0, 0, 1.94)) M = Matrix.Translation(o) @ Matrix.Rotation(math.pi / 2, 4, 'Z') @ Matrix.Translation((0, 0.09, 0)) # as clamp_check, nose +x Mi = M.inverted() rows = {} for ob in parts: ev = ob.evaluated_get(dg) me = ev.to_mesh() W = ev.matrix_world pts = [] for v in me.vertices: p = Mi @ (W @ v.co) r = math.hypot(p.x, p.y + 0.09) if r < 0.9 and p.z < 1.8: pts.append((r, math.degrees(math.atan2(p.y + 0.09, p.x)) % 360, p.z)) ev.to_mesh_clear() if not pts: continue zs = [q[2] for q in pts] low = [q for q in pts if q[2] < min(zs) + 0.03] rows[ob.name] = {"n": len(pts), "z_min": round(min(zs), 3), "z_max": round(max(zs), 3), "r_min": round(min(q[0] for q in pts), 3), "r_max": round(max(q[0] for q in pts), 3), "lowest_r": [round(min(q[0] for q in low), 3), round(max(q[0] for q in low), 3)], "lowest_az": sorted({int(q[1] // 5 * 5) for q in low})} out["claws_open" if claw else "claws_shut"] = rows json.dump(out, open(os.path.join(HERE, "checks", "head_parts.json"), "w"), indent=1) for k, rows in out.items(): for nm, r in sorted(rows.items(), key=lambda kv: kv[1]["z_min"]): print("HEAD", k, nm, json.dumps(r))