# -*- coding: utf-8 -*- """从 travel_detail.json 的单关节硬限位重新生成 docs/travel.json。 滑块范围 = 单关节硬限位(任意单关节推满零干涉,含 1° 安全余量); 组合折叠约束保留在 travel_detail.json 的 combos 字段里,供报告引用。 注意 note 的措辞:单轴整周无干涉 **不等于** 任意组合姿态无干涉。sweep_v2 的组合扫描 已经在 J1/J3/J6 上找到了真实卡死(工具法兰 P09 撞固定立柱 P01_A),例如 J3≈±162°。 所以连续轴的 note 必须写明"单轴"并指向 combos,否则这份文件会误导人——查看器运行期 另有胶囊碰撞模型按姿态夹取(ik-glue.js 的 dynLimit),但静态滑块范围按设计不压缩。 """ import json import math import os import sys from arm.analysis.sweep_v2 import CHAIN from arm.paths import DOCS # 这两个脚本的顶层就是"算完并写文件",被 import 时会静默重写 travel/mesh 派生产物 # (实测:一次 importlib 冒烟测试就把 docs/travel.json 重写了一遍)。这里改成直接炸。 if __name__ != "__main__": raise RuntimeError( "finalize_travel 是脚本:顶层代码一执行就重写产物,不能 import。" "要用就跑 python -m arm.analysis.finalize_travel。") d = json.load(open(DOCS + "/travel_detail.json", encoding="utf-8")) # 组合扫描中,每个被扫轴真实出现卡死的最小绝对角 combo_warn = {} for c in d.get("combos", []): if not c.get("jams"): continue ax = c["swept"] for a in c["jams"]: try: v = abs(float(a)) except (TypeError, ValueError): continue combo_warn[ax] = min(combo_warn.get(ax, 1e9), v) out = [] for t in CHAIN[1:]: s = d["singles"][t] lo, hi = s["lo"], s["hi"] warn = combo_warn.get(t) warn_txt = (";组合折叠姿态下(其余关节同时处于各自极限)约 ±%.0f° 起与躯干占位" "(台架 P01 立柱)干涉,见 travel_detail.combos," "运行期由查看器碰撞模型按姿态夹取" % warn) if warn is not None else "" if lo <= -179.9 and hi >= 179.9: out.append(dict(axis=t, lo=-180.0, hi=180.0, continuous=True, zero=0.0, combo_warn_deg=warn, note="单轴整周无干涉(滑块按单轴限位给出)%s" % (warn_txt or ";组合扫描未发现该轴卡死"))) else: lo_out = float(math.ceil(lo + 1.0)) if lo < -0.5 else 0.0 hi_out = float(math.floor(hi - 1.0)) if hi > 0.5 else 0.0 out.append(dict(axis=t, lo=lo_out, hi=hi_out, continuous=False, zero=0.0, combo_warn_deg=warn, note="单轴正向 +%d° / 反向 %d°,总行程 %d°(单关节硬限位,含相邻件与电机)%s" % (hi_out, lo_out, hi_out - lo_out, warn_txt))) print("%-3s %7.1f .. %7.1f -> %s .. %s%s" % (t, lo, hi, out[-1]["lo"], out[-1]["hi"], (" 组合卡死阈值 ±%.0f°" % warn) if warn is not None else "")) json.dump(out, open(DOCS + "/travel.json", "w", encoding="utf-8"), ensure_ascii=False, indent=1) d["final"] = out json.dump(d, open(DOCS + "/travel_detail.json", "w", encoding="utf-8"), ensure_ascii=False, indent=1) print("rewrote docs/travel.json (single-joint hard stops) + updated travel_detail.json")