单文件约束取消后,Python 侧没必要再靠 16 处 sys.path.insert 维持扁平模块互认。
现在按职责分包:
arm/paths.py 路径唯一来源(含新增 CACHE、TPL)
arm/constants.py 实测接口数值(原 armcore 的 M/C/CLR/FIT/MOTOR_TOL 段)
arm/cad/{helpers,arm_build,part_tools,parts/} 几何与装配
arm/kinematics.py(原 human_layout.py,唯一运动学事实源)
arm/analysis/{sweep_v2,strength_check,torque_balance,finalize_travel,ws_sweep,gen_env_mesh}
arm/dataio/{screw_mesh,draw_sheet} arm/viewer/{build_viewer,shot}
arm/build_model.py(原 arm_model.py)
顺带修掉的既有缺陷(都是实测撞出来的,不是预防性改动):
- arm_model 第二次 sys.path 跳到 gitignore 的 scratch/ 去 import 构建必需的包络脚本:
ws_sweep/gen_env_mesh 提升进 arm/analysis/,缓存挪到 data/cache/(gitignore,可重生成)。
- finalize_travel / draw_sheet 顶层就是"算完写文件",一次 importlib 冒烟测试就把
docs/travel.json 重写了一遍;现在被 import 直接抛错。
- strength_check 用 OUT.replace("/out","/web") 靠字符串形状推路径,改成直接用 WEB。
- build_viewer 里 WORKSPACE 使用点漏改导致 NameError —— 已由构建关卡抓到并修掉。
os._exit 的处置与计划里的假设相反:实测光是 `python -c "import arm.cad.helpers"`
就会在解释器退出时段错误(exit 139,OCC 静态析构),全流程跑完也一样。所以入口
脚本尾部保留 flush + os._exit,并把原因写进注释;被 import 时不生效。
关卡(tests/):
- verify.py 一条命令跑三层:产物 md5、IK 数值 exact 段、截图。
- 截图基线重做并分级:同一构建连跑两轮实测 102 张逐字节可复现(要求 md5 相同),
3 张线束 x-ray 不可复现(mean<=0.0017、无像素差>8)改为与参考像素比容差;
这 3 张不再入库,免得每次跑关卡都脏 git。
- 新增 ?view=sheet / ?sheet=N / ?theme / ?guide=N 四个 URL 参数:工程图与装配向导
占了约一半 CSS 和 700 行 JS,原先没有任何截图覆盖,拆它们等于没有关卡。
- 关卡灵敏度已验:改坏 IK 基线一个数 -> FAIL;换旧版求解器 -> 5 处 exact 差异。
实测:python -m arm.build_model 退出码 0,全部产物 md5 与基线一致,
105 视图截图全过,IK exact 段逐字节一致。
59 lines
3.0 KiB
Python
59 lines
3.0 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""实测接口数值:电机模组、端面齿联轴器、配合公差与电机轴向公差。
|
||
|
||
全部 MEASURED 自 G:/Robot_v2/Model/Solidworks/电机.STEP 与配件(见 docs/interfaces.md)。
|
||
改之前先确认量的是同一个基准面。"""
|
||
|
||
# 注:本段由 armcore.py 原样搬来,行内容与注释未作改动。
|
||
|
||
# ---------------- MEASURED: motor module (local frame: origin = PCBA rear face centre, +Z = output) ----
|
||
M = dict(
|
||
pcba_w=63.6, # square PCBA across flats
|
||
pcba_t=9.0, # z 0 -> 9.0
|
||
rearplate_d=60.0, # z 5.5 -> 10.5
|
||
hous_d=60.0, # housing OD, z 10.5 -> 52.5
|
||
hous_len=42.0,
|
||
cover_d=60.30, # top cover OD (R30.15), z 52.5 -> 56.0
|
||
cover_z=56.0, # cover front face = module total length
|
||
flange_z=54.942, # 2nd-stage output flange face
|
||
neck_d=36.0, # female neck bore in the cover
|
||
neck_depth=1.0,
|
||
centre_d=6.5, # centre bore in the flange
|
||
centre_depth=4.0,
|
||
m2_bcd=29.0,
|
||
m2_clock=(8.05, 128.07, 248.06),
|
||
m2_tap_d=1.85, # M2 pilot for self-tapping in printed material
|
||
m2_depth=6.0,
|
||
m2_clear_d=2.75,
|
||
m2_cb_d=5.2,
|
||
)
|
||
# ---------------- MEASURED: face-spline coupling (existing, printed by the user) ------------------------
|
||
C = dict(
|
||
n_teeth=12, tooth_r0=19.0, tooth_r1=24.5, tooth_s=2.5,
|
||
flange_t=4.50, part_z=5.560, # mirrored stack
|
||
hub_r=27.0,
|
||
gap=9.00, # cover-face to cover-face when closed
|
||
clamp_od_r=30.0, clamp_len=7.80,
|
||
lug_r1=37.0, lug_t=4.50,
|
||
bolt_r=32.50, bolt_d=3.80,
|
||
z0=1.66, z1=9.46, # clamp envelope in the flange frame (motor cover face = 1.060)
|
||
)
|
||
# axial stations, motor local frame:
|
||
COVER_Z = M["cover_z"] # 56.0
|
||
HUB_FACE_Z = COVER_Z + C["gap"] # 65.0 = mating face of the driven hub
|
||
CLAMP_R = C["clamp_od_r"] + 0.6 # radial keep-out around the joint axis
|
||
LUG_R = C["lug_r1"] + 1.0 # radial keep-out where the bolt lugs are
|
||
# ---------------- clearances / print rules -------------------------------------------------------------
|
||
CLR = dict(bore_slip=0.20, pilot=0.10, hole_3=3.4, hole_27=2.8, wall_min=2.0)
|
||
FIT = dict(motor_bore_d=M["hous_d"] + 2 * 0.15, cover_cb_d=M["cover_d"] + 2 * 0.35)
|
||
|
||
# 电机【轴向长度】公差(用户 2026-10-07 要求:余量偏大稍微减去 1mm,由 2mm 改为 1mm)。
|
||
# 这条链是"后端板螺钉 + 前端压盖螺钉"两个刚性夹持面,螺钉头一旦坐死在沉孔台阶上
|
||
# 就再也不能进给,所以公差没法靠"拧紧"消化,只能靠两件事吃掉(见 arm_build.Joint.pocket
|
||
# 与 motor_front_clamp):
|
||
# 长出来的 0~+1mm -> 后端板 4xM3 螺钉头下垫 0~1mm 垫片圈(螺钉被垫高 -> 电机被拉回)
|
||
# 短下去的 0~-1mm -> 电机尾端面与后端板承压面之间垫 0~1mm 垫片(承压面已按 MOTOR_TOL
|
||
# 让空,见 Joint.pocket 的 REAR_SEAT)
|
||
# 两边都不动压盖/凸台的几何,关节轴向长度不变。
|
||
MOTOR_TOL = 1.0
|