"""Sweep variants with the real-proxy check; compact table. python design_variants2.py s u px cle (lists comma separated)""" import os, sys, json, subprocess, itertools from concurrent.futures import ThreadPoolExecutor HERE = os.path.dirname(os.path.abspath(__file__)); ROOT = os.path.dirname(HERE) BL = r"E:\Steam\steamapps\common\Blender\blender.exe"; PY = r"E:\Tools\Programs\Python\python.exe" CTX = os.path.join(ROOT, "source", "ship_context_2026-10-16.blend") step = os.environ.get("DRA_STEP", "4") lists = [a.split(",") for a in sys.argv[1:5]] vers = os.environ.get("DRA_VERS", "A,B").split(",") os.makedirs(os.path.join(HERE, "var"), exist_ok=True) def run(combo): s, u, px, cle = combo tag = "_".join(combo) dj = os.path.join(HERE, "var", "d_%s.json" % tag) env = dict(os.environ, DRA_S=s, DRA_U=u, DRA_PX=px, DRA_CLE=cle, DRA_OUT=dj) subprocess.run([PY, os.path.join(HERE, "design_make_json.py")], env=env, capture_output=True) res = [] for dk in os.environ.get("DRA_DOORS", "AFT").split(","): for ver in vers: out = os.path.join(HERE, "var", "c_%s_%s_%s.json" % (tag, dk, ver)) subprocess.run([BL, "-b", "--factory-startup", CTX, "--python", os.path.join(HERE, "design_ik_check.py"), "--", dk, ver, out, step, "0.05"], env=env, capture_output=True) try: res.append((dk + " " + ver, json.load(open(out)))) except Exception as e: res.append((dk + " " + ver, {"fail": str(e)})) return combo, res combos = list(itertools.product(*lists)) with ThreadPoolExecutor(max_workers=4) as ex: for combo, res in ex.map(run, combos): for ver, r in res: if "joints" not in r or r.get("fail"): print(",".join(combo), ver, "FAIL", r.get("fail")) continue j = r["joints"] c = r["clear_sorted"][0]; sf = r["self_sorted"][0] print("%s %s | elb %4.0f..%4.0f |q5| %3.0f..%3.0f J1r %3.0f J2 %4.0f..%4.0f J3 %4.0f..%4.0f rod %.2f..%.2f | ctx %+.3f %s f%d | self %+.3f %s f%d" % ( ",".join(combo), ver, r["elbow_inner_deg"][0], r["elbow_inner_deg"][1], r["min_abs_q5_deg"], max(abs(j["J5"][0]), abs(j["J5"][1])), j["J1"][1] - j["J1"][0], j["J2"][0], j["J2"][1], j["J3"][0], j["J3"][1], r["rod"]["length"][0], r["rod"]["length"][1], c[1], c[0][:48], c[2], sf[1], sf[0][:60], sf[2])) if os.environ.get("DRA_DETAIL"): for k in r["clear_sorted"][:8]: print(" ctx %+.3f f%3d %s" % (k[1], k[2], k[0])) for k in r["self_sorted"][:8]: print(" self %+.3f f%3d %s" % (k[1], k[2], k[0])) print(" pose err mm %.5f deg %.5f | max step deg %s | wc axis min %.2f | reach %s | rod %s" % (r["pose_err_mm"], r["pose_err_deg"], r["max_step_deg"], r["wc_from_J1_axis_min"], r["reach_ratio"], r["rod"]))