2026-09-26 18:05:21 +08:00
|
|
|
|
# -*- coding: utf-8 -*-
|
2026-09-27 04:48:49 +08:00
|
|
|
|
"""机器人手臂深度圆角优化版 V2:彻底消除所有棱角
|
|
|
|
|
|
针对用户反馈的三大问题区域进行深度优化:
|
|
|
|
|
|
1. 蓝色零件(P04肩叉)顶部方形突起 → 全圆角处理
|
|
|
|
|
|
2. 绿色/青色零件(P05/P08)底部和侧面棱角 → Loft外轮廓圆角
|
|
|
|
|
|
3. 所有连接处的尖锐过渡 → 大圆角平滑过渡
|
|
|
|
|
|
4. 橙色零件(P06/P07)所有方形边缘 → 完整圆角系统
|
2026-09-26 18:05:21 +08:00
|
|
|
|
"""
|
|
|
|
|
|
import math
|
|
|
|
|
|
import os
|
|
|
|
|
|
import sys
|
2026-09-27 04:48:49 +08:00
|
|
|
|
import time
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
|
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
|
|
import cadquery as cq
|
|
|
|
|
|
import arm_build as AB
|
|
|
|
|
|
from armcore import (M, C, cyl, box, ring, place, trs, bb, bbox_str, solids_of, OUT, WEB, DOCS)
|
|
|
|
|
|
from arm_build import (Joint, add, bx, Ycyl, Ybox, Yplate, prism, dogbone, sector,
|
|
|
|
|
|
FLANGE_Z, COVER_Z, HUB_FACE_Z, CLAMP_SPAN, HUB_M2_CLOCK,
|
|
|
|
|
|
BORE_R, CB_R, PCB_W, D2R, T, R, PARTS)
|
|
|
|
|
|
import human_layout as HL
|
|
|
|
|
|
from OCP.BRepAlgoAPI import BRepAlgoAPI_Common
|
|
|
|
|
|
from human_layout import (HUB, PLATE_T, R_MOT, Z_TIP, Z_WR, Z_EI, Z_SH, Z_RL, Z_R1,
|
|
|
|
|
|
Z_R3, Z_HUB3, Z_EL, Z_R6, Z_HUB6,
|
|
|
|
|
|
Z_R4, Z_CAP, Z_M6, Z_CHEST0, Z_CHEST1, X_J1_HUB, X_ARM, L1,
|
2026-10-02 04:39:12 +08:00
|
|
|
|
X_FORK_GAP, X_BAY_EXT,
|
2026-09-26 18:05:21 +08:00
|
|
|
|
Y_AXIS, Y_HUB, Y_REAR, Y_COVER, Y_H, Y_R_IN, Y_R_OUT,
|
2026-09-27 04:48:49 +08:00
|
|
|
|
Y_M6, Y_CHEST, X_CHEST, FOOT_H)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
VERSION = os.environ.get("ARMVER", "v2")
|
|
|
|
|
|
ITER = int(os.environ.get("ARMITER", "3"))
|
2026-09-26 18:05:21 +08:00
|
|
|
|
AB.VERSION = VERSION
|
|
|
|
|
|
AB.ITER = ITER
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
Y_MID = Y_AXIS
|
|
|
|
|
|
BOSS = COVER_Z + 0.2
|
|
|
|
|
|
DISC_R = 40.0
|
|
|
|
|
|
SLEEVE_R = 35.0
|
|
|
|
|
|
|
|
|
|
|
|
# 深度圆角优化参数
|
|
|
|
|
|
CLEARANCE_GAP = 2.0 # 关节间隙 2.0mm
|
|
|
|
|
|
FILLET_TINY = 1.5 # 微小圆角(螺孔边缘)
|
|
|
|
|
|
FILLET_SMALL = 3.0 # 小圆角(功能面)
|
|
|
|
|
|
FILLET_MEDIUM = 6.0 # 中圆角(结构过渡)
|
|
|
|
|
|
FILLET_LARGE = 10.0 # 大圆角(主要轮廓)
|
|
|
|
|
|
FILLET_XLARGE = 15.0 # 超大圆角(视觉主导区域)
|
|
|
|
|
|
CHAMFER_EDGE = 2.0 # 边缘倒角
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def Xcyl(r, x0, x1, py, pz):
|
|
|
|
|
|
return place(place(cyl(r, 0.0, x1 - x0, 0.0, 0.0), R(90, 0, 1, 0)), T(x0, py, pz))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def Xplate(pts_yz, x0, x1):
|
|
|
|
|
|
prof = [(-p[1], p[0]) for p in pts_yz]
|
|
|
|
|
|
return place(place(prism(prof, 0.0, x1 - x0), R(90, 0, 1, 0)), T(x0, 0.0, 0.0))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def XB(a0, a1, y0, y1, z0, z1):
|
|
|
|
|
|
return bx(X_ARM + a0, X_ARM + a1, y0, y1, z0, z1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def make_direct_hub(shape, j, r_disc=35.0, z_out=74.0):
|
2026-09-27 04:48:49 +08:00
|
|
|
|
"""优化直连法兰:增加导向倒角"""
|
2026-09-26 18:05:21 +08:00
|
|
|
|
disc = cyl(r_disc, 56.5, z_out)
|
|
|
|
|
|
boss = cyl(17.8, 54.942, 56.5)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
chamfer_cone = cyl(18.5, 54.5, 54.942)
|
|
|
|
|
|
shape = shape.fuse(j.L(disc)).fuse(j.L(boss)).cut(j.L(chamfer_cone))
|
2026-09-26 18:05:21 +08:00
|
|
|
|
shape = shape.cut(j.L(cyl(3.5, 54.0, z_out + 30.0)))
|
|
|
|
|
|
for a in AB.HUB_M2_CLOCK:
|
|
|
|
|
|
u = AB.M["m2_bcd"] / 2.0 * math.cos(a * AB.D2R)
|
|
|
|
|
|
v = AB.M["m2_bcd"] / 2.0 * math.sin(a * AB.D2R)
|
|
|
|
|
|
th = cyl(1.4, 54.0, 58.0, u, v)
|
|
|
|
|
|
cb = cyl(2.8, 58.0, z_out + 40.0, u, v)
|
|
|
|
|
|
shape = shape.cut(j.L(th)).cut(j.L(cb))
|
|
|
|
|
|
return shape
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
# ========== 躯干部分 ==========
|
|
|
|
|
|
# ========== 躯干/测试台架部分 (后置防倾翻高刚性机架) ==========
|
|
|
|
|
|
X_COL = -115.0
|
|
|
|
|
|
Y_COL = Y_AXIS # 128.0
|
2026-10-02 04:39:12 +08:00
|
|
|
|
Z_LOCK = 463.0 # 横向防脱锁紧螺钉高度(立柱后壁 → 榫头,M4x16 自攻)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-09-26 18:05:21 +08:00
|
|
|
|
def p_chest():
|
2026-09-27 04:48:49 +08:00
|
|
|
|
"""P01_胸腔支撑立柱 (High-Rigidity Box Mast Tower - 后置台架立柱):
|
2026-09-27 21:08:28 +08:00
|
|
|
|
1. 66x66mm 封闭中空厚壁箱型柱(壁厚 11mm,内腔 44x44),中心在 (-115.0, 128.0),位于手臂正后方;
|
2026-10-02 04:39:12 +08:00
|
|
|
|
2. 顶部接收 P03 43.4x43.4x15mm 定位榫头(44x44 R4 内腔)、4x 竖向安装孔 + 1x 横向防脱锁紧孔
|
|
|
|
|
|
(全部 Ø3.9 直孔:M4x16 从外部直接拧入自攻成型,无过孔/无沉孔/无预埋);
|
2026-09-27 21:08:28 +08:00
|
|
|
|
3. 底部 50x50x12mm 阶梯榫头插入 P02 榫座:环形台肩(66->50)面承载轴向力,槽壁全周承载剪切;
|
2026-09-27 00:28:49 +08:00
|
|
|
|
4. 前向开设两组大圆角走线工艺窗口(Z=60~150mm 与 Z=330~420mm);
|
|
|
|
|
|
5. 外棱角全部采用 R=6mm 圆角。
|
|
|
|
|
|
"""
|
2026-09-27 04:48:49 +08:00
|
|
|
|
z_bot = 22.0
|
2026-09-27 00:28:49 +08:00
|
|
|
|
z_top = Z_CHEST1 # 470.0
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
col = (cq.Workplane("XY", origin=(X_COL, Y_COL, z_bot))
|
2026-09-27 00:28:49 +08:00
|
|
|
|
.rect(66.0, 66.0)
|
|
|
|
|
|
.extrude(z_top - z_bot)
|
|
|
|
|
|
.edges("|Z").fillet(6.0)).val()
|
|
|
|
|
|
s = cq.Shape(col.wrapped)
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
cav = (cq.Workplane("XY", origin=(X_COL, Y_COL, z_bot + 10.0))
|
2026-09-27 21:08:28 +08:00
|
|
|
|
.rect(44.0, 44.0)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
.extrude(z_top - z_bot + 1.0)
|
|
|
|
|
|
.edges("|Z").fillet(4.0)).val()
|
|
|
|
|
|
s = s.cut(cav)
|
2026-09-27 21:08:28 +08:00
|
|
|
|
|
|
|
|
|
|
# 底部阶梯榫头:插入 P02 榫座后环形台肩坐实,轴向力走面压而非 M5 螺纹
|
|
|
|
|
|
tenon = (cq.Workplane("XY", origin=(X_COL, Y_COL, 10.0))
|
|
|
|
|
|
.rect(50.0, 50.0).extrude(z_bot - 10.0)
|
|
|
|
|
|
.edges("|Z").fillet(4.0)).val()
|
|
|
|
|
|
s = s.fuse(tenon)
|
|
|
|
|
|
|
|
|
|
|
|
# 底部 M5 夹紧孔(贯通榫头):X 向非对称 (−20/+16) 与榫座孔位配对防反装/防转 90°
|
|
|
|
|
|
for xx in (X_COL - 20.0, X_COL + 16.0):
|
|
|
|
|
|
for yy in (Y_COL - 18.0, Y_COL + 18.0):
|
|
|
|
|
|
s = s.cut(cyl(2.75, 9.99, z_bot + 15.0, xx, yy))
|
2026-10-02 04:39:12 +08:00
|
|
|
|
# 顶部 4x 安装孔:统一 Ø3.9 直孔(M4x16 直接拧入自攻成型;只打这一个孔,无过孔/无沉孔),深 20mm
|
|
|
|
|
|
# 位于 66x66 顶环 11mm 实体壁内(内腔 22 → 外壁 33),避开 44x44 内腔与 R4 内腔圆角;
|
|
|
|
|
|
for xx in (X_COL - 27.5, X_COL + 27.5):
|
|
|
|
|
|
for yy in (Y_COL - 13.5, Y_COL + 13.5):
|
|
|
|
|
|
s = s.cut(cyl(1.95, z_top - 20.0, z_top + 0.01, xx, yy))
|
|
|
|
|
|
# 横向防脱锁紧孔(后壁 → 榫头):Ø3.9 贯穿 11mm 后壁 + 榫头同径(M4x16 拧入自攻)
|
|
|
|
|
|
s = s.cut(Xcyl(1.95, X_COL - 34.0, X_COL - 20.0, Y_COL, Z_LOCK))
|
2026-09-27 00:28:49 +08:00
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
w_bot = (cq.Workplane("YZ", origin=(X_COL + 33.5, Y_COL, 105.0))
|
2026-09-27 00:28:49 +08:00
|
|
|
|
.rect(34.0, 70.0)
|
|
|
|
|
|
.extrude(-20.0)).val()
|
|
|
|
|
|
s = s.cut(w_bot)
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
w_top = (cq.Workplane("YZ", origin=(X_COL + 33.5, Y_COL, 375.0))
|
2026-09-27 00:28:49 +08:00
|
|
|
|
.rect(34.0, 70.0)
|
|
|
|
|
|
.extrude(-20.0)).val()
|
|
|
|
|
|
s = s.cut(w_top)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-09-27 17:21:50 +08:00
|
|
|
|
def split_p01_poka_yoke(p01):
|
|
|
|
|
|
"""拆分 P01 为 A/B/C 三段(严格适配 200x200mm 打印机,竖直免支撑打印):
|
2026-09-28 01:00:04 +08:00
|
|
|
|
带 16mm 阶梯互锁榫卯(外套筒壁 3.6 + 公榫壁 6.9,内腔收窄 51->44 换取双厚壁,
|
2026-10-02 04:39:12 +08:00
|
|
|
|
单边配合间隙 0.5)、以及统一 Ø3.9 直孔的分段对锁孔(M4x16 从外面直接拧入自攻成型,
|
|
|
|
|
|
母口壁与公榫壁同径,无过孔/沉孔/预埋,前后两面对称各一颗);
|
|
|
|
|
|
孔位相对立柱中心 −16 / +22 非对称(物理防反装防呆);本体 3D 凹刻朝向标识。
|
2026-09-27 17:21:50 +08:00
|
|
|
|
"""
|
|
|
|
|
|
z_bot = 22.0
|
|
|
|
|
|
z_s1 = 172.0
|
|
|
|
|
|
z_s2 = 321.0
|
|
|
|
|
|
z_top = 470.0
|
2026-09-27 00:28:49 +08:00
|
|
|
|
h_lap = 16.0
|
|
|
|
|
|
|
2026-09-27 17:21:50 +08:00
|
|
|
|
# 非对称对锁孔位(相对立柱中心偏心 -16mm 与 +22mm,偏心差 6mm,反装无法穿入螺栓)
|
|
|
|
|
|
xx_bolts = (X_COL - 16.0, X_COL + 22.0)
|
2026-10-02 04:39:12 +08:00
|
|
|
|
|
|
|
|
|
|
# 分段对锁孔:统一 Ø3.9 直孔(M4x16 从外面直接拧入自攻成型;母口壁与公榫壁同径,
|
|
|
|
|
|
# 没有过孔/沉孔等其它孔),前后两面对称;杆尖伸过榫壁的一段在内腔侧留 Ø4.5 让位。
|
|
|
|
|
|
def _seam_holes(part, xx, z):
|
|
|
|
|
|
return (part.cut(Ycyl(1.95, Y_COL - 33.6, Y_COL - 21.4, xx, z))
|
|
|
|
|
|
.cut(Ycyl(1.95, Y_COL + 21.4, Y_COL + 33.6, xx, z))
|
|
|
|
|
|
.cut(Ycyl(2.25, Y_COL - 21.7, Y_COL - 15.5, xx, z))
|
|
|
|
|
|
.cut(Ycyl(2.25, Y_COL + 15.5, Y_COL + 21.7, xx, z)))
|
2026-09-27 00:28:49 +08:00
|
|
|
|
|
2026-09-27 17:21:50 +08:00
|
|
|
|
# --- P01_A (下段) ---
|
|
|
|
|
|
cut_above_s1 = bx(X_COL - 50.0, X_COL + 50.0, Y_COL - 50.0, Y_COL + 50.0, z_s1, z_top + 10.0)
|
|
|
|
|
|
p01_a_base = p01.cut(cut_above_s1)
|
|
|
|
|
|
tongue1_outer = (cq.Workplane("XY", origin=(X_COL, Y_COL, z_s1))
|
2026-09-28 01:00:04 +08:00
|
|
|
|
.rect(57.8, 57.8).extrude(h_lap)
|
2026-09-27 21:08:28 +08:00
|
|
|
|
.edges("|Z").fillet(3.4).edges(">Z").chamfer(1.5)).val()
|
2026-09-27 17:21:50 +08:00
|
|
|
|
tongue1_cav = (cq.Workplane("XY", origin=(X_COL, Y_COL, z_s1 - 1.0))
|
2026-09-27 21:08:28 +08:00
|
|
|
|
.rect(44.0, 44.0).extrude(h_lap + 2.0)).val()
|
2026-09-27 17:21:50 +08:00
|
|
|
|
tongue1 = cq.Shape(tongue1_outer.wrapped).cut(tongue1_cav)
|
|
|
|
|
|
p01_a = p01_a_base.fuse(tongue1)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
|
2026-09-27 17:21:50 +08:00
|
|
|
|
z_bolt1 = z_s1 + h_lap / 2.0 # 180.0
|
|
|
|
|
|
for xx in xx_bolts:
|
2026-10-02 04:39:12 +08:00
|
|
|
|
p01_a = _seam_holes(p01_a, xx, z_bolt1) # A-B 缝对锁孔(Ø3.9,前后两面)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
|
2026-09-27 21:08:28 +08:00
|
|
|
|
# Engrave the front (-Y) flat face, reading VERTICALLY bottom-to-top along
|
|
|
|
|
|
# the column (user request): local +X = world +Z, local +Y = world -X, so
|
|
|
|
|
|
# the trailing "▶" glyph renders pointing world-up (+Z).
|
|
|
|
|
|
front_label_plane_a = cq.Plane(
|
|
|
|
|
|
origin=(X_COL, Y_COL - 33.0, 120.0),
|
|
|
|
|
|
xDir=(0, 0, 1), normal=(0, -1, 0),
|
|
|
|
|
|
)
|
|
|
|
|
|
label_a = (cq.Workplane(front_label_plane_a)
|
|
|
|
|
|
.text("P01-A TOP ▶", 9.0, -0.8)).val()
|
2026-09-27 17:21:50 +08:00
|
|
|
|
p01_a = p01_a.cut(cq.Shape(label_a.wrapped))
|
|
|
|
|
|
|
|
|
|
|
|
# --- P01_B (中段) ---
|
2026-09-27 21:08:28 +08:00
|
|
|
|
cut_below_s1 = bx(X_COL - 50.0, X_COL + 50.0, Y_COL - 50.0, Y_COL + 50.0, z_bot - 14.0, z_s1)
|
2026-09-27 17:21:50 +08:00
|
|
|
|
cut_above_s2 = bx(X_COL - 50.0, X_COL + 50.0, Y_COL - 50.0, Y_COL + 50.0, z_s2, z_top + 10.0)
|
|
|
|
|
|
p01_b_base = p01.cut(cut_below_s1).cut(cut_above_s2)
|
|
|
|
|
|
pocket1 = (cq.Workplane("XY", origin=(X_COL, Y_COL, z_s1 - 0.1))
|
2026-09-28 01:00:04 +08:00
|
|
|
|
.rect(58.8, 58.8).extrude(h_lap + 0.6).edges("|Z").fillet(3.9)).val()
|
2026-09-27 17:21:50 +08:00
|
|
|
|
p01_b_base = p01_b_base.cut(pocket1)
|
|
|
|
|
|
|
|
|
|
|
|
tongue2_outer = (cq.Workplane("XY", origin=(X_COL, Y_COL, z_s2))
|
2026-09-28 01:00:04 +08:00
|
|
|
|
.rect(57.8, 57.8).extrude(h_lap)
|
2026-09-27 21:08:28 +08:00
|
|
|
|
.edges("|Z").fillet(3.4).edges(">Z").chamfer(1.5)).val()
|
2026-09-27 17:21:50 +08:00
|
|
|
|
tongue2_cav = (cq.Workplane("XY", origin=(X_COL, Y_COL, z_s2 - 1.0))
|
2026-09-27 21:08:28 +08:00
|
|
|
|
.rect(44.0, 44.0).extrude(h_lap + 2.0)).val()
|
2026-09-27 17:21:50 +08:00
|
|
|
|
tongue2 = cq.Shape(tongue2_outer.wrapped).cut(tongue2_cav)
|
|
|
|
|
|
p01_b = p01_b_base.fuse(tongue2)
|
|
|
|
|
|
|
|
|
|
|
|
z_bolt2 = z_s2 + h_lap / 2.0 # 329.0
|
|
|
|
|
|
for xx in xx_bolts:
|
2026-10-02 04:39:12 +08:00
|
|
|
|
p01_b = _seam_holes(p01_b, xx, z_bolt1) # A-B 缝对锁孔(Ø3.9,前后两面)
|
|
|
|
|
|
p01_b = _seam_holes(p01_b, xx, z_bolt2) # B-C 缝对锁孔(Ø3.9,前后两面)
|
2026-09-27 17:21:50 +08:00
|
|
|
|
|
2026-09-27 21:08:28 +08:00
|
|
|
|
front_label_plane_b = cq.Plane(
|
|
|
|
|
|
origin=(X_COL, Y_COL - 33.0, 240.0),
|
|
|
|
|
|
xDir=(0, 0, 1), normal=(0, -1, 0),
|
|
|
|
|
|
)
|
|
|
|
|
|
label_b = (cq.Workplane(front_label_plane_b)
|
|
|
|
|
|
.text("P01-B TOP ▶", 9.0, -0.8)).val()
|
2026-09-27 17:21:50 +08:00
|
|
|
|
p01_b = p01_b.cut(cq.Shape(label_b.wrapped))
|
|
|
|
|
|
|
|
|
|
|
|
# --- P01_C (上段) ---
|
2026-09-27 21:08:28 +08:00
|
|
|
|
cut_below_s2 = bx(X_COL - 50.0, X_COL + 50.0, Y_COL - 50.0, Y_COL + 50.0, z_bot - 14.0, z_s2)
|
2026-09-27 17:21:50 +08:00
|
|
|
|
p01_c_base = p01.cut(cut_below_s2)
|
|
|
|
|
|
pocket2 = (cq.Workplane("XY", origin=(X_COL, Y_COL, z_s2 - 0.1))
|
2026-09-28 01:00:04 +08:00
|
|
|
|
.rect(58.8, 58.8).extrude(h_lap + 0.6).edges("|Z").fillet(3.9)).val()
|
2026-09-27 17:21:50 +08:00
|
|
|
|
p01_c = p01_c_base.cut(pocket2)
|
|
|
|
|
|
for xx in xx_bolts:
|
2026-10-02 04:39:12 +08:00
|
|
|
|
p01_c = _seam_holes(p01_c, xx, z_bolt2) # B-C 缝对锁孔(Ø3.9,前后两面)
|
2026-09-27 17:21:50 +08:00
|
|
|
|
|
2026-09-27 21:08:28 +08:00
|
|
|
|
front_label_plane_c = cq.Plane(
|
|
|
|
|
|
origin=(X_COL, Y_COL - 33.0, 390.0),
|
|
|
|
|
|
xDir=(0, 0, 1), normal=(0, -1, 0),
|
|
|
|
|
|
)
|
|
|
|
|
|
label_c = (cq.Workplane(front_label_plane_c)
|
|
|
|
|
|
.text("P01-C TOP ▶", 9.0, -0.8)).val()
|
2026-09-27 17:21:50 +08:00
|
|
|
|
p01_c = p01_c.cut(cq.Shape(label_c.wrapped))
|
|
|
|
|
|
|
|
|
|
|
|
return p01_a, p01_b, p01_c
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def make_p02_poka_yoke():
|
|
|
|
|
|
"""将 P02 拆分为三件模块化组件(均严格 <= 195x190mm,适配 200x200mm 打印床):
|
|
|
|
|
|
1. P02_Center (底座中核心): 195x190x70mm,完整容纳立柱套筒与前后三角斜撑筋,核心应力区无接缝;
|
|
|
|
|
|
2. P02_Front (前向力臂): 145x190x22mm,宽跨距 104mm 双榫头 + 预埋 M5 螺母槽;
|
|
|
|
|
|
3. P02_Rear (后向力臂): 45x190x22mm,窄跨距 80mm 双榫头(跨距差达 24mm 物理防呆,绝不混装)。
|
|
|
|
|
|
"""
|
|
|
|
|
|
z0 = 0.0
|
|
|
|
|
|
z1 = 22.0
|
|
|
|
|
|
y_width = 190.0
|
|
|
|
|
|
|
|
|
|
|
|
f_tenon_w = 44.0
|
|
|
|
|
|
f_tenon_y_span = 52.0
|
|
|
|
|
|
r_tenon_w = 32.0
|
|
|
|
|
|
r_tenon_y_span = 40.0
|
|
|
|
|
|
|
|
|
|
|
|
# 1. P02_Center (X = -195.0 .. 0.0, 195x190mm)
|
|
|
|
|
|
x_c_min = -195.0
|
|
|
|
|
|
x_c_max = 0.0
|
|
|
|
|
|
x_c_len = x_c_max - x_c_min
|
|
|
|
|
|
x_c_mid = (x_c_min + x_c_max) / 2.0
|
|
|
|
|
|
|
|
|
|
|
|
c_plate = (cq.Workplane("XY", origin=(x_c_mid, Y_COL, z0))
|
|
|
|
|
|
.rect(x_c_len, y_width).extrude(z1)
|
|
|
|
|
|
.edges("|Z and <X").fillet(8.0).edges("|Z and >X").fillet(8.0)
|
|
|
|
|
|
.edges(">Z").fillet(2.0)).val()
|
|
|
|
|
|
p02_c = cq.Shape(c_plate.wrapped)
|
|
|
|
|
|
|
|
|
|
|
|
# Socket collar (Z: 22..70mm)
|
|
|
|
|
|
z_collar_top = 70.0
|
|
|
|
|
|
collar_outer = (cq.Workplane("XY", origin=(X_COL, Y_COL, z1))
|
|
|
|
|
|
.rect(80.0, 80.0).extrude(z_collar_top - z1)
|
|
|
|
|
|
.edges("|Z").fillet(8.0).edges(">Z").chamfer(2.0)).val()
|
|
|
|
|
|
p02_c = p02_c.fuse(cq.Shape(collar_outer.wrapped))
|
|
|
|
|
|
|
|
|
|
|
|
# Front & Rear triangular gusset ribs
|
|
|
|
|
|
f_pts = [(-75.0, z1), (-15.0, z1), (-15.0, z1 + 4.0), (-75.0, 68.0)]
|
|
|
|
|
|
f_rib = (cq.Workplane("XZ", origin=(0, Y_COL, 0)).polyline(f_pts).close().extrude(19.0, both=True)).val()
|
|
|
|
|
|
p02_c = p02_c.fuse(cq.Shape(f_rib.wrapped))
|
|
|
|
|
|
|
|
|
|
|
|
r_pts = [(-155.0, z1), (-195.0, z1), (-195.0, z1 + 14.0), (-155.0, 70.0)]
|
|
|
|
|
|
r_rib = (cq.Workplane("XZ", origin=(0, Y_COL, 0)).polyline(r_pts).close().extrude(19.0, both=True)).val()
|
|
|
|
|
|
p02_c = p02_c.fuse(cq.Shape(r_rib.wrapped))
|
|
|
|
|
|
|
|
|
|
|
|
# Front wire guide
|
|
|
|
|
|
wg_pts = [(-75.5, z1 + 1.0), (-14.0, z1 + 1.0), (-14.0, z1 + 4.0), (-75.5, 68.5)]
|
|
|
|
|
|
wire_guide = (cq.Workplane("XZ", origin=(0, Y_COL, 0)).polyline(wg_pts).close().extrude(9.0, both=True)).val()
|
|
|
|
|
|
p02_c = p02_c.cut(wire_guide)
|
|
|
|
|
|
|
2026-09-27 21:08:28 +08:00
|
|
|
|
# Column socket — stepped mortise: upper 66.6 bore for the 66 box walls,
|
|
|
|
|
|
# lower 50.6 recess (floor 0.6 low) for the 50x50 bottom tenon; the recess
|
|
|
|
|
|
# rim at z=22 is the axial seat, so column weight bears on face, not threads.
|
|
|
|
|
|
socket_upper = (cq.Workplane("XY", origin=(X_COL, Y_COL, z1))
|
|
|
|
|
|
.rect(66.6, 66.6).extrude(z_collar_top - z1 + 1.0)
|
|
|
|
|
|
.edges("|Z").fillet(6.3)).val()
|
|
|
|
|
|
p02_c = p02_c.cut(socket_upper)
|
|
|
|
|
|
socket_lower = (cq.Workplane("XY", origin=(X_COL, Y_COL, 9.4))
|
|
|
|
|
|
.rect(50.6, 50.6).extrude(z1 - 9.4)
|
|
|
|
|
|
.edges("|Z").fillet(4.3)).val()
|
|
|
|
|
|
p02_c = p02_c.cut(socket_lower)
|
2026-09-27 17:21:50 +08:00
|
|
|
|
|
2026-09-27 21:08:28 +08:00
|
|
|
|
# Vertical M5 clamp bolts (offsets match the asymmetric column tenon holes:
|
|
|
|
|
|
# X −20/+16 blocks 180° flip, the ±18 Y span blocks 90° rotation).
|
|
|
|
|
|
# Threads engage the tenon 15mm — clamp only, axial load rides on the seat.
|
|
|
|
|
|
for xx in (X_COL - 20.0, X_COL + 16.0):
|
|
|
|
|
|
for yy in (Y_COL - 18.0, Y_COL + 18.0):
|
2026-09-27 17:21:50 +08:00
|
|
|
|
p02_c = p02_c.cut(cyl(2.75, -0.01, 10.5, xx, yy)).cut(cyl(5.0, -0.01, 6.0, xx, yy))
|
|
|
|
|
|
|
|
|
|
|
|
# Center clamp slots
|
|
|
|
|
|
for cy in (Y_COL - 75.0, Y_COL + 75.0):
|
|
|
|
|
|
plane = cq.Plane(origin=(x_c_mid, cy, -0.01), xDir=(0, 1, 0), normal=(0, 0, 1))
|
|
|
|
|
|
slot = cq.Workplane(plane).slot2D(28.0, 7.0).extrude(z1 + 1.0).val()
|
|
|
|
|
|
p02_c = p02_c.cut(slot)
|
|
|
|
|
|
|
|
|
|
|
|
p02_c = p02_c.cut((cq.Workplane("XY", origin=(X_COL, Y_COL - 70.0, -0.01)).rect(28.0, 80.0).extrude(6.0)).val())
|
|
|
|
|
|
|
|
|
|
|
|
# Front mortise pockets
|
|
|
|
|
|
for sign in (-1, 1):
|
|
|
|
|
|
yy = Y_COL + sign * f_tenon_y_span
|
|
|
|
|
|
front_mortise = (cq.Workplane("XY", origin=(-10.0, yy, 4.8))
|
|
|
|
|
|
.rect(21.0, f_tenon_w + 0.8).extrude(12.6).edges("|Z and <X").fillet(3.0)).val()
|
|
|
|
|
|
p02_c = p02_c.cut(front_mortise)
|
|
|
|
|
|
p02_c = p02_c.cut(cyl(2.75, -0.01, z1 + 1.0, -10.0, yy))
|
|
|
|
|
|
p02_c = p02_c.cut(cyl(5.0, z1 - 5.0, z1 + 1.0, -10.0, yy))
|
|
|
|
|
|
|
|
|
|
|
|
# Rear mortise pockets
|
|
|
|
|
|
for sign in (-1, 1):
|
|
|
|
|
|
yy = Y_COL + sign * r_tenon_y_span
|
|
|
|
|
|
rear_mortise = (cq.Workplane("XY", origin=(-185.0, yy, 4.8))
|
|
|
|
|
|
.rect(21.0, r_tenon_w + 0.8).extrude(12.6).edges("|Z and >X").fillet(3.0)).val()
|
|
|
|
|
|
p02_c = p02_c.cut(rear_mortise)
|
|
|
|
|
|
p02_c = p02_c.cut(cyl(2.75, -0.01, z1 + 1.0, -185.0, yy))
|
|
|
|
|
|
p02_c = p02_c.cut(cyl(5.0, z1 - 5.0, z1 + 1.0, -185.0, yy))
|
|
|
|
|
|
|
2026-09-27 21:08:28 +08:00
|
|
|
|
# Debossed text on P02_Center top face. The mid-plate line (y=Y_COL) is
|
|
|
|
|
|
# hidden behind the column collar and the gusset ribs, so both labels sit on
|
|
|
|
|
|
# the flat -Y side strip (y = Y_COL-68) where they stay in full view from the
|
|
|
|
|
|
# label side: REAR on the rear half, FRONT on the front half, clear of the
|
|
|
|
|
|
# clamp slot (x -101..-94) and the M5 screw counterbores.
|
|
|
|
|
|
txt_c_f = (cq.Workplane("XY", origin=(-49.0, Y_COL - 68.0, z1)).text("▲ FRONT (前向) ▲", 9.0, -0.8)).val()
|
|
|
|
|
|
txt_c_r = (cq.Workplane("XY", origin=(-146.0, Y_COL - 68.0, z1)).text("▲ REAR (后向) ▲", 9.0, -0.8)).val()
|
2026-09-27 17:21:50 +08:00
|
|
|
|
p02_c = p02_c.cut(cq.Shape(txt_c_f.wrapped)).cut(cq.Shape(txt_c_r.wrapped))
|
|
|
|
|
|
|
|
|
|
|
|
# 2. P02_Front (X = 0.0 .. 145.0, 145x190mm)
|
|
|
|
|
|
x_f_len = 145.0
|
|
|
|
|
|
x_f_mid = 72.5
|
|
|
|
|
|
f_plate = (cq.Workplane("XY", origin=(x_f_mid, Y_COL, z0))
|
|
|
|
|
|
.rect(x_f_len, y_width).extrude(z1)
|
|
|
|
|
|
.edges("|Z and >X").fillet(16.0).edges(">Z").fillet(2.0)).val()
|
|
|
|
|
|
p02_f = cq.Shape(f_plate.wrapped)
|
|
|
|
|
|
|
|
|
|
|
|
for cy in (Y_COL - 70.0, Y_COL + 70.0):
|
|
|
|
|
|
plane = cq.Plane(origin=(120.0, cy, -0.01), xDir=(0, 1, 0), normal=(0, 0, 1))
|
|
|
|
|
|
slot = cq.Workplane(plane).slot2D(28.0, 7.0).extrude(z1 + 1.0).val()
|
|
|
|
|
|
p02_f = p02_f.cut(slot)
|
|
|
|
|
|
|
|
|
|
|
|
for sign in (-1, 1):
|
|
|
|
|
|
yy = Y_COL + sign * f_tenon_y_span
|
|
|
|
|
|
tongue = (cq.Workplane("XY", origin=(-9.5, yy, 5.25))
|
|
|
|
|
|
.rect(20.0, f_tenon_w - 0.2).extrude(11.5).edges("|Z and <X").fillet(2.5).edges("<X").chamfer(1.5)).val()
|
|
|
|
|
|
p02_f = p02_f.fuse(cq.Shape(tongue.wrapped))
|
|
|
|
|
|
p02_f = p02_f.cut(cyl(2.75, -0.01, z1 + 1.0, -10.0, yy))
|
|
|
|
|
|
nut_pocket = (cq.Workplane("XY", origin=(-10.0, yy, -0.01)).polygon(6, 9.2).extrude(5.0)).val()
|
|
|
|
|
|
p02_f = p02_f.cut(nut_pocket)
|
|
|
|
|
|
|
2026-09-27 21:08:28 +08:00
|
|
|
|
# Top-face engraving rotated 90 deg to run across the plate along +Y (user
|
|
|
|
|
|
# request): letter tops face -X, so it reads upright from the front (+X).
|
|
|
|
|
|
# "▲" points local +Y = world -X, i.e. toward the centre joint.
|
|
|
|
|
|
txt_f = (cq.Workplane(cq.Plane(origin=(x_f_mid, Y_COL, z1), xDir=(0, 1, 0),
|
|
|
|
|
|
normal=(0, 0, 1)))
|
|
|
|
|
|
.text("P02-FRONT ▲ JOIN", 8.0, -0.8)).val()
|
2026-09-27 17:21:50 +08:00
|
|
|
|
p02_f = p02_f.cut(cq.Shape(txt_f.wrapped))
|
|
|
|
|
|
|
|
|
|
|
|
# 3. P02_Rear (X = -240.0 .. -195.0, 45x190mm)
|
|
|
|
|
|
x_r_len = 45.0
|
|
|
|
|
|
x_r_mid = -217.5
|
|
|
|
|
|
r_plate = (cq.Workplane("XY", origin=(x_r_mid, Y_COL, z0))
|
|
|
|
|
|
.rect(x_r_len, y_width).extrude(z1)
|
|
|
|
|
|
.edges("|Z and <X").fillet(16.0).edges(">Z").fillet(2.0)).val()
|
|
|
|
|
|
p02_r = cq.Shape(r_plate.wrapped)
|
|
|
|
|
|
|
|
|
|
|
|
for cy in (Y_COL - 70.0, Y_COL + 70.0):
|
|
|
|
|
|
plane = cq.Plane(origin=(-215.0, cy, -0.01), xDir=(0, 1, 0), normal=(0, 0, 1))
|
|
|
|
|
|
slot = cq.Workplane(plane).slot2D(28.0, 7.0).extrude(z1 + 1.0).val()
|
|
|
|
|
|
p02_r = p02_r.cut(slot)
|
|
|
|
|
|
|
|
|
|
|
|
for sign in (-1, 1):
|
|
|
|
|
|
yy = Y_COL + sign * r_tenon_y_span
|
|
|
|
|
|
tongue = (cq.Workplane("XY", origin=(-185.5, yy, 5.25))
|
|
|
|
|
|
.rect(20.0, r_tenon_w - 0.2).extrude(11.5).edges("|Z and >X").fillet(2.5).edges(">X").chamfer(1.5)).val()
|
|
|
|
|
|
p02_r = p02_r.fuse(cq.Shape(tongue.wrapped))
|
|
|
|
|
|
p02_r = p02_r.cut(cyl(2.75, -0.01, z1 + 1.0, -185.0, yy))
|
|
|
|
|
|
nut_pocket = (cq.Workplane("XY", origin=(-185.0, yy, -0.01)).polygon(6, 9.2).extrude(5.0)).val()
|
|
|
|
|
|
p02_r = p02_r.cut(nut_pocket)
|
|
|
|
|
|
|
2026-09-27 21:08:28 +08:00
|
|
|
|
# Same +Y rotation as the front plate; "▼" points local -Y = world +X,
|
|
|
|
|
|
# i.e. toward the centre joint. Along +Y the ~73 mm text fits the 190 mm
|
|
|
|
|
|
# plate width instead of overhanging its 45 mm X span.
|
|
|
|
|
|
txt_r = (cq.Workplane(cq.Plane(origin=(x_r_mid, Y_COL, z1), xDir=(0, 1, 0),
|
|
|
|
|
|
normal=(0, 0, 1)))
|
|
|
|
|
|
.text("P02-REAR ▼ JOIN", 7.5, -0.8)).val()
|
2026-09-27 17:21:50 +08:00
|
|
|
|
p02_r = p02_r.cut(cq.Shape(txt_r.wrapped))
|
|
|
|
|
|
|
|
|
|
|
|
return p02_c, p02_f, p02_r
|
2026-09-27 00:28:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-09-26 18:05:21 +08:00
|
|
|
|
def p_base_foot():
|
2026-09-27 16:52:27 +08:00
|
|
|
|
"""P02_底脚 (重型防倾翻超长力臂底座 + 双向大截面三角加强斜撑筋):
|
|
|
|
|
|
1. 底盘尺寸大幅扩展为 385x240x22mm (X: -240.0..+145.0, Y: 8.0..248.0);
|
|
|
|
|
|
- 前向延伸至 X = +145.0mm (在手臂垂直投影前方 91.5mm),彻底杜绝手臂前伸与抓握重物时的前倾翻;
|
|
|
|
|
|
- 后向延伸至 X = -240.0mm (在立柱后方 92.0mm),抵御大动态回程后仰力矩;
|
|
|
|
|
|
2. 立柱插接套筒由 12mm 浅槽大幅升级为 48mm 高加固套筒 (Z: 22.0..70.0mm,外壁厚 7mm);
|
|
|
|
|
|
3. 前向大三角加强斜撑筋 (Z: 68.0->22.0mm, X: -75.0->-15.0mm, 宽 38mm),抗弯力臂长达 60mm,留足安全间隙不干涉手臂运动;
|
|
|
|
|
|
4. 后向大三角加强斜撑筋 (Z: 70.0->22.0mm, X: -155.0->-225.0mm, 宽 38mm),抗后仰力臂长达 70mm;
|
|
|
|
|
|
5. 前斜撑表面设 18mm 宽平滑走线导槽,与 P01 下部走线窗口自然贯通;
|
|
|
|
|
|
6. 6 组 M6 工业工作台紧固腰槽 (28x7mm) + 底部隐蔽走线槽;
|
|
|
|
|
|
7. 四周 R=18mm 大圆角过渡与 2.5mm 上边缘倒角。
|
2026-09-27 00:28:49 +08:00
|
|
|
|
"""
|
|
|
|
|
|
z0 = 0.0
|
|
|
|
|
|
z1 = 22.0
|
2026-09-27 16:52:27 +08:00
|
|
|
|
x_rear = -240.0
|
|
|
|
|
|
x_front = 145.0
|
|
|
|
|
|
x_len = x_front - x_rear # 385.0
|
|
|
|
|
|
x_mid = (x_rear + x_front) / 2.0 # -47.5
|
|
|
|
|
|
y_width = 240.0
|
|
|
|
|
|
|
|
|
|
|
|
# 1. 主底盘 (385 x 240 x 22 mm)
|
|
|
|
|
|
base_plate = (cq.Workplane("XY", origin=(x_mid, Y_COL, z0))
|
|
|
|
|
|
.rect(x_len, y_width)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
.extrude(z1)
|
2026-09-27 16:52:27 +08:00
|
|
|
|
.edges("|Z").fillet(18.0)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
.edges(">Z").fillet(2.5)).val()
|
|
|
|
|
|
s = cq.Shape(base_plate.wrapped)
|
|
|
|
|
|
|
2026-09-27 16:52:27 +08:00
|
|
|
|
# 2. 立柱外包加固套筒 (Z: 22.0..70.0 mm, 外廓 80x80mm)
|
|
|
|
|
|
z_collar_top = 70.0
|
|
|
|
|
|
collar_outer = (cq.Workplane("XY", origin=(X_COL, Y_COL, z1))
|
|
|
|
|
|
.rect(80.0, 80.0)
|
|
|
|
|
|
.extrude(z_collar_top - z1)
|
|
|
|
|
|
.edges("|Z").fillet(8.0)
|
|
|
|
|
|
.edges(">Z").chamfer(2.0)).val()
|
|
|
|
|
|
s = s.fuse(cq.Shape(collar_outer.wrapped))
|
|
|
|
|
|
|
|
|
|
|
|
# 3. 前向抗倾翻三角加强斜撑筋 (Front Triangular Gusset Rib)
|
|
|
|
|
|
f_pts = [
|
|
|
|
|
|
(-75.0, z1),
|
|
|
|
|
|
(-15.0, z1),
|
|
|
|
|
|
(-15.0, z1 + 4.0),
|
|
|
|
|
|
(-75.0, 68.0),
|
|
|
|
|
|
]
|
|
|
|
|
|
f_rib = (cq.Workplane("XZ", origin=(0, Y_COL, 0))
|
|
|
|
|
|
.polyline(f_pts).close()
|
|
|
|
|
|
.extrude(19.0, both=True)).val()
|
|
|
|
|
|
s = s.fuse(cq.Shape(f_rib.wrapped))
|
|
|
|
|
|
|
|
|
|
|
|
# 4. 后向抗倾翻三角加强斜撑筋 (Rear Triangular Gusset Rib)
|
|
|
|
|
|
r_pts = [
|
|
|
|
|
|
(-155.0, z1),
|
|
|
|
|
|
(-225.0, z1),
|
|
|
|
|
|
(-225.0, z1 + 4.0),
|
|
|
|
|
|
(-155.0, 70.0),
|
|
|
|
|
|
]
|
|
|
|
|
|
r_rib = (cq.Workplane("XZ", origin=(0, Y_COL, 0))
|
|
|
|
|
|
.polyline(r_pts).close()
|
|
|
|
|
|
.extrude(19.0, both=True)).val()
|
|
|
|
|
|
s = s.fuse(cq.Shape(r_rib.wrapped))
|
|
|
|
|
|
|
|
|
|
|
|
# 5. 前斜撑表面走线导槽 (与 P01 前走线窗 Z=70..140mm 自然顺接)
|
|
|
|
|
|
wire_guide_pts = [
|
|
|
|
|
|
(-75.5, z1 + 1.0),
|
|
|
|
|
|
(-14.0, z1 + 1.0),
|
|
|
|
|
|
(-14.0, z1 + 4.0),
|
|
|
|
|
|
(-75.5, 68.5),
|
|
|
|
|
|
]
|
|
|
|
|
|
wire_guide = (cq.Workplane("XZ", origin=(0, Y_COL, 0))
|
|
|
|
|
|
.polyline(wire_guide_pts).close()
|
|
|
|
|
|
.extrude(9.0, both=True)).val()
|
|
|
|
|
|
s = s.cut(wire_guide)
|
|
|
|
|
|
|
|
|
|
|
|
# 6. 立柱深插槽内腔 (Pocket: 66.6 x 66.6 mm, 留 0.3mm 精密滑配间隙)
|
|
|
|
|
|
socket_box = (cq.Workplane("XY", origin=(X_COL, Y_COL, 10.0))
|
|
|
|
|
|
.rect(66.6, 66.6)
|
|
|
|
|
|
.extrude(z_collar_top - 10.0 + 1.0)
|
|
|
|
|
|
.edges("|Z").fillet(6.3)).val()
|
2026-09-27 00:28:49 +08:00
|
|
|
|
s = s.cut(socket_box)
|
|
|
|
|
|
|
2026-09-27 16:52:27 +08:00
|
|
|
|
# 7. 4x M5 底部垂直紧固螺栓孔与沉孔
|
2026-09-27 04:48:49 +08:00
|
|
|
|
for xx in (X_COL - 21.0, X_COL + 21.0):
|
|
|
|
|
|
for yy in (Y_COL - 21.0, Y_COL + 21.0):
|
2026-09-27 16:52:27 +08:00
|
|
|
|
th = cyl(2.75, -0.01, 10.5, xx, yy)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
cb = cyl(5.0, -0.01, 6.0, xx, yy)
|
|
|
|
|
|
s = s.cut(th).cut(cb)
|
|
|
|
|
|
|
2026-09-27 16:52:27 +08:00
|
|
|
|
# 8. 6 组 M6 工业工作台紧固腰槽 (28 x 7 mm)
|
|
|
|
|
|
slot_positions = [
|
|
|
|
|
|
(-215.0, Y_COL - 85.0), (-215.0, Y_COL + 85.0), # 后部两角
|
|
|
|
|
|
(-47.5, Y_COL - 95.0), (-47.5, Y_COL + 95.0), # 中部两侧
|
|
|
|
|
|
(120.0, Y_COL - 85.0), (120.0, Y_COL + 85.0), # 前部两角
|
|
|
|
|
|
]
|
|
|
|
|
|
for cx, cy in slot_positions:
|
|
|
|
|
|
plane = cq.Plane(origin=(cx, cy, -0.01), xDir=(0, 1, 0), normal=(0, 0, 1))
|
|
|
|
|
|
slot = cq.Workplane(plane).slot2D(28.0, 7.0).extrude(z1 + 1.0).val()
|
|
|
|
|
|
s = s.cut(slot)
|
|
|
|
|
|
|
|
|
|
|
|
# 9. 底部隐蔽走线通槽
|
2026-09-27 04:48:49 +08:00
|
|
|
|
wire_ch = (cq.Workplane("XY", origin=(X_COL, Y_COL - 80.0, -0.01))
|
|
|
|
|
|
.rect(28.0, 100.0)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
.extrude(6.0)).val()
|
|
|
|
|
|
s = s.cut(wire_ch)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_girdle(j1):
|
2026-10-02 04:39:12 +08:00
|
|
|
|
"""P03_肩关节安装悬臂 (轻量化板式桁架版 + 侧开式电机托架):
|
2026-09-27 04:48:49 +08:00
|
|
|
|
1. 10mm 后端重载法兰盘 (X: -61.0..-51.0, 74x74mm);
|
2026-10-02 04:39:12 +08:00
|
|
|
|
2. 主干由 66mm 实心块改为双侧 6mm 桁架竖板 (Y = Y_ARM ± 27..33),外轮廓保持旧版
|
|
|
|
|
|
"主干 ∪ 侧筋"并集不变 —— 只减材料不加体积,零新增干涉风险;实心 728 -> 286 cm³ (-61%);
|
|
|
|
|
|
3. 竖板帐篷形减重窗 (顶/底斜面 ≥52°,自支撑;仅 20mm 平顶可桥接);
|
|
|
|
|
|
4. 底部 9mm 承力鞍座 + 43.4x43.4 定位榫头 (配 P01_C 44x44 内腔,单边 0.3mm 间隙);
|
|
|
|
|
|
鞍座底面 66x66 与立柱顶环带承压面积 2403mm² —— 竖向载荷走面压,螺栓只防上抬/防滑;
|
|
|
|
|
|
5. 4x 安装孔 (X_COL±27.5, Y_COL±13.5):Ø3.9 直孔,M4x16 从上方直接拧入自攻成型
|
|
|
|
|
|
(鞍座与立柱顶环同径,无过孔/沉孔/预埋),可拆装;
|
|
|
|
|
|
6. 下腹中央龙骨筋 (12mm 中位腹板,自鞍座斜拉至法兰下缘) + 顶部横向锁紧环抱筋 (66x9x10mm,
|
|
|
|
|
|
与两侧竖板外面齐平、顶面压在筋板脊线上,仅顶前棱一道 2mm 倒角);
|
|
|
|
|
|
7. 侧开式电机托架 (+Y侧全开, X: -51.0..11.5,前端随 X_BAY_EXT 前延 3mm),
|
|
|
|
|
|
M1 电机可从侧方斜插卡入装配(插槽比电机长 3mm),由后端法兰 4xM3x16 锁死;
|
|
|
|
|
|
电机舱 Ø60.7 从后端直通到前端面(2026-10-02 用户裁定"去掉台阶改成平的":无环形台阶、
|
|
|
|
|
|
无喇叭锥;原前置止脱锁紧法兰 4xM3 随之取消,电机轴向由后端 4xM3x16 约束);
|
|
|
|
|
|
9. 两侧大面积散热舷窗 (34x20mm) + 顶部双斜向对流排热槽 (30x6.5mm),确保散热畅通;
|
|
|
|
|
|
10. Ø26mm 中央走线孔;竖板间为开放腔体(无封闭空腔),M3 螺丝刀通道直接走腔体,拧紧更顺手。
|
2026-09-26 18:05:21 +08:00
|
|
|
|
"""
|
2026-09-27 04:48:49 +08:00
|
|
|
|
X_MOUNT = Z_R1 # -51.0 (Rear face of M1)
|
|
|
|
|
|
T_FLANGE = 10.0 # 10mm thick high-strength mounting flange
|
|
|
|
|
|
X_BACK = X_MOUNT - T_FLANGE # -61.0
|
|
|
|
|
|
Y_ARM = Y_AXIS # 128.0
|
|
|
|
|
|
Z_ARM = Z_RL # 610.0
|
2026-10-02 04:39:12 +08:00
|
|
|
|
Y_P_IN = 27.0 # 桁架竖板内表面 (Y_ARM ± 27)
|
|
|
|
|
|
Y_P_OUT = 33.0 # 桁架竖板外表面 (与旧主干齐平)
|
|
|
|
|
|
T_SADDLE = 9.0 # 底部鞍座厚度
|
|
|
|
|
|
TENON = 43.4 # 定位榫头边长(P01_C 内腔 44x44 R4,单边留 0.3mm)
|
|
|
|
|
|
WIN_R = 4.0 # 竖板减重窗内角圆角(消除内尖角应力集中,Kt 由 ~2.5 降到 ~1.2)
|
|
|
|
|
|
BOLT_DX, BOLT_DY = 27.5, 13.5 # 4x 安装孔相对立柱中心偏移:落在顶环 11mm 实体壁内
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-10-02 04:39:12 +08:00
|
|
|
|
# 1. 主安装法兰盘 (74x74mm, 四角倒圆 R=8mm)
|
|
|
|
|
|
# 背面那圈 2mm 倒角已去掉:板料只伸进法兰 0.1mm,倒角面与板背面相交会在
|
|
|
|
|
|
# Z≈574.9 挤出一批 2mm 短棱,正是这批短棱让整条交接内棱网络倒不出圆角;
|
|
|
|
|
|
# 同时它跨过 R8 角部圆弧,就是角上那道"卷起来"的怪倒角。
|
2026-09-27 04:48:49 +08:00
|
|
|
|
flange = (cq.Workplane("YZ", origin=(X_BACK, Y_ARM, Z_ARM))
|
|
|
|
|
|
.rect(74.0, 74.0)
|
|
|
|
|
|
.extrude(T_FLANGE)
|
2026-10-02 04:39:12 +08:00
|
|
|
|
.edges("|X").fillet(8.0)).val()
|
2026-09-27 04:48:49 +08:00
|
|
|
|
s = cq.Shape(flange.wrapped)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
|
2026-10-02 04:39:12 +08:00
|
|
|
|
# 2. 双侧桁架竖板 (6mm):旧"斜挑支撑主干"与"大三角加强筋"轮廓同段挤出 → 自动并集成单块侧板
|
|
|
|
|
|
# 主干的后缘两点取在加强筋斜边的延长线上,使外轮廓顶部成为一整条直线
|
|
|
|
|
|
# (否则后缘 (-148,550) 处有 5° 折点、留下 5mm 台阶)。
|
|
|
|
|
|
# Z_CREST = 侧筋脊线高度,同时是顶筋 2mm 顶前倒角的下沿:倒角从 (X-71,Z_CREST)
|
|
|
|
|
|
# 斜上到 (X-69,Z_CREST+2) = 顶筋顶面,斜坡面与倒角面几乎相切,顶部读起来是一整张面。
|
|
|
|
|
|
Z_CREST = Z_ARM + 33.0 # 643(初版 642;顶筋整体上移 3mm 让出扳手空间后跟着抬)
|
|
|
|
|
|
|
|
|
|
|
|
RIB_SLOPE = (Z_CREST - 575.0) / ((X_BACK - 10.0) - (X_COL - 15.0))
|
|
|
|
|
|
|
|
|
|
|
|
def rib_line_z(x):
|
|
|
|
|
|
return Z_CREST + RIB_SLOPE * (x - (X_BACK - 10.0))
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
trunk_pts = [
|
|
|
|
|
|
(X_COL - 33.0, Z_CHEST1),
|
|
|
|
|
|
(X_COL + 33.0, Z_CHEST1),
|
|
|
|
|
|
(X_COL + 33.0, 505.0),
|
|
|
|
|
|
(X_BACK + 0.1, 565.0),
|
|
|
|
|
|
(X_BACK + 0.1, Z_ARM - 5.0),
|
2026-10-02 04:39:12 +08:00
|
|
|
|
(X_COL - 10.0, rib_line_z(X_COL - 10.0)),
|
|
|
|
|
|
(X_COL - 33.0, rib_line_z(X_COL - 33.0)),
|
|
|
|
|
|
]
|
|
|
|
|
|
rib_pts = [
|
|
|
|
|
|
(X_COL - 33.0, Z_CHEST1), # 底边两端与主干/鞍座对齐 (±33):原来收进 3mm,
|
|
|
|
|
|
(X_COL + 33.0, Z_CHEST1), # 会在鞍座顶面上留下 0.7/3mm 短棱,卡住整条底棱圆角
|
|
|
|
|
|
(X_BACK + 0.1, 565.0),
|
|
|
|
|
|
(X_BACK + 0.1, Z_CREST),
|
|
|
|
|
|
(X_BACK - 10.0, Z_CREST), # 脊线 (-71,643):正好落在顶筋前面与 2mm 倒角下沿的交点
|
|
|
|
|
|
(X_COL - 15.0, 575.0),
|
|
|
|
|
|
(X_COL - 30.0, 530.0),
|
2026-09-26 18:05:21 +08:00
|
|
|
|
]
|
2026-09-27 04:48:49 +08:00
|
|
|
|
for sign in (-1, 1):
|
2026-10-02 04:39:12 +08:00
|
|
|
|
ya = Y_ARM + sign * Y_P_IN
|
|
|
|
|
|
yb = Y_ARM + sign * Y_P_OUT
|
|
|
|
|
|
y0, y1 = min(ya, yb), max(ya, yb)
|
|
|
|
|
|
for prof in (trunk_pts, rib_pts):
|
|
|
|
|
|
s = s.fuse(cq.Shape(Yplate(prof, y0, y1).wrapped))
|
|
|
|
|
|
|
|
|
|
|
|
# 3. 竖板减重窗 (帐篷形:斜面 ≥52° 自支撑、仅 20mm 平顶可桥接;避开鞍座与 M5 螺母柱)
|
|
|
|
|
|
# 6 个内角全部 R4 圆角:把内尖角应力集中 (Kt≈2.5) 降到 ≈1.2,同时圆角面仍是竖直/自支撑面
|
|
|
|
|
|
win_pts = [
|
|
|
|
|
|
(X_COL - 24.0, 498.0), (X_COL + 23.0, 498.0), (X_COL + 25.0, 522.0),
|
|
|
|
|
|
(X_COL + 10.0, 545.0), (X_COL - 10.0, 545.0), (X_COL - 25.0, 524.0),
|
2026-09-27 04:48:49 +08:00
|
|
|
|
]
|
2026-10-02 04:39:12 +08:00
|
|
|
|
for sign in (-1, 1):
|
|
|
|
|
|
yc = Y_ARM + sign * 0.5 * (Y_P_IN + Y_P_OUT)
|
|
|
|
|
|
tool = (cq.Workplane("XZ", origin=(0, yc, 0)).polyline(win_pts).close()
|
|
|
|
|
|
.extrude(Y_P_OUT - Y_P_IN + 1.0, both=True)
|
|
|
|
|
|
.edges("|Y").fillet(WIN_R).val())
|
|
|
|
|
|
s = s.cut(cq.Shape(tool.wrapped))
|
|
|
|
|
|
|
|
|
|
|
|
# 4. 底部承力鞍座:坐实立柱顶面,把两竖板、龙骨与榫头连成整体
|
|
|
|
|
|
s = s.fuse(bx(X_COL - 33.0, X_COL + 33.0, Y_ARM - Y_P_OUT, Y_ARM + Y_P_OUT,
|
|
|
|
|
|
Z_CHEST1, Z_CHEST1 + T_SADDLE))
|
|
|
|
|
|
|
|
|
|
|
|
# 5. 下腹部纵向抗弯龙骨筋 (12mm 中位腹板,自鞍座斜拉至法兰背面;交接内棱在融合后做真 3D 圆角)
|
|
|
|
|
|
keel_pts = [
|
|
|
|
|
|
(X_COL + 33.0, Z_CHEST1), # (-82, 470)
|
|
|
|
|
|
(X_COL + 33.0, 495.0), # (-82, 495)
|
|
|
|
|
|
(X_BACK + 0.1, 573.0), # (-60.9, 573) 斜拉至法兰背面
|
|
|
|
|
|
(X_BACK + 0.1, 594.4), # (-60.9, 594.4) 顶端贴法兰
|
|
|
|
|
|
(X_COL + 42.1, 585.0), # (-72.9, 585)
|
|
|
|
|
|
(X_COL + 20.0, Z_CHEST1), # (-95, 470) 背面一路斜到底:原来在 (-95,480) 有个折点,
|
|
|
|
|
|
] # 折点离鞍座顶面只 1mm,R2.5 圆角爬不上去 → 龙骨底棱整组倒不出
|
|
|
|
|
|
s = s.fuse(cq.Shape(Yplate(keel_pts, Y_ARM - 6.0, Y_ARM + 6.0).wrapped))
|
2026-09-27 04:48:49 +08:00
|
|
|
|
|
2026-10-02 04:39:12 +08:00
|
|
|
|
# 7. 顶部横向锁紧环抱横筋:Y 向与两竖板外面齐平 (Y_ARM±33)、前面与筋板脊线共面 (X=-71)、
|
|
|
|
|
|
# 顶面 Z=645 压住脊线 (Z=643) 并与 2mm 顶前倒角相切 → 顶筋与两侧脊线合成一整块。
|
|
|
|
|
|
# 整体比初版抬高 3mm (底面 633→636):4x M3 后端沉孔 Ø6.5 跨在 Z 627.2..633.7 上,
|
|
|
|
|
|
# 底面 633 会压住孔口上沿 0.7mm、扳手让位只剩负间隙;抬到 636 后退到孔口上方 2.3mm、
|
|
|
|
|
|
# 离螺钉轴线 5.55mm。顶面 645 不越过法兰 R8 角部圆弧在 Y=95 处的 645.9 上界。
|
|
|
|
|
|
tie_rib = (cq.Workplane("YZ", origin=(X_BACK - 10.0, Y_ARM, Z_ARM + 30.5))
|
|
|
|
|
|
.rect(66.0, 9.0)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
.extrude(10.0)
|
2026-10-02 04:39:12 +08:00
|
|
|
|
.edges(cq.selectors.BoxSelector((X_BACK - 10.5, Y_ARM - 34.0, Z_ARM + 34.5),
|
|
|
|
|
|
(X_BACK - 9.5, Y_ARM + 34.0, Z_ARM + 35.5)))
|
|
|
|
|
|
.chamfer(2.0)).val()
|
2026-09-27 04:48:49 +08:00
|
|
|
|
s = s.fuse(cq.Shape(tie_rib.wrapped))
|
|
|
|
|
|
|
2026-10-02 04:39:12 +08:00
|
|
|
|
# 6.y 体-体交接凹棱:融合完成后对"凹棱"直接做真 3D 圆角。
|
|
|
|
|
|
# 原先这里是手工沿棱 fuse 的 10 条"正方形−四分之一圆"焊珠小体(_cove),已整体删除:
|
|
|
|
|
|
# 焊珠端面是平的、悬在半空,两条互相垂直的焊珠在角上互不搭接 → 圆角"缺一块",
|
|
|
|
|
|
# 并与相邻体的棱互相穿插留 1~3mm² 碎面。真圆角在面边界自然收口、多棱相交处由 OCC
|
|
|
|
|
|
# 生成角部补片。
|
|
|
|
|
|
from cadquery import selectors as _sel
|
|
|
|
|
|
from OCP.BRepAdaptor import BRepAdaptor_Surface
|
|
|
|
|
|
from OCP.GeomAbs import GeomAbs_Plane
|
|
|
|
|
|
from OCP.TopAbs import TopAbs_REVERSED
|
|
|
|
|
|
|
|
|
|
|
|
def _outward(f, sh):
|
|
|
|
|
|
"""平面面的外法向:先按 Orientation 修正,再用"面中心外移 1mm 是否仍在实体内"兜方向。"""
|
|
|
|
|
|
ad = BRepAdaptor_Surface(f.wrapped)
|
|
|
|
|
|
if ad.GetType() != GeomAbs_Plane:
|
|
|
|
|
|
return None
|
|
|
|
|
|
ax = ad.Plane().Axis().Direction()
|
|
|
|
|
|
n = cq.Vector(ax.X(), ax.Y(), ax.Z())
|
|
|
|
|
|
if f.wrapped.Orientation() == TopAbs_REVERSED:
|
|
|
|
|
|
n = n * -1.0
|
|
|
|
|
|
c = f.Center()
|
|
|
|
|
|
if cq.Solid(sh.wrapped).isInside(cq.Vector(c.x + n.x, c.y + n.y, c.z + n.z), 1e-6):
|
|
|
|
|
|
n = n * -1.0
|
|
|
|
|
|
return n
|
|
|
|
|
|
|
|
|
|
|
|
def _fillet_reflex(lo, hi, radii, tag, eps=0.9):
|
|
|
|
|
|
"""倒出 lo~hi 区域内的凹棱(两面夹 270° 材料)。判据:从棱中点沿 (n1-n2) 外探 eps,
|
|
|
|
|
|
落在实体内 = 凹、落在外 = 凸。区域内凹棱先整批一次倒(半径逐级降级,且倒完验拓扑:
|
|
|
|
|
|
OCC 会给出"没抛异常但面已坏"的结果),建不出时按相连棱分组逐组倒。"""
|
|
|
|
|
|
nonlocal s
|
|
|
|
|
|
|
|
|
|
|
|
def _pick(sh):
|
|
|
|
|
|
edges = sh.Edges()
|
|
|
|
|
|
idx = {}
|
|
|
|
|
|
for i, e in enumerate(edges):
|
|
|
|
|
|
idx[e.hashCode()] = i
|
|
|
|
|
|
adj = [[] for _ in edges]
|
|
|
|
|
|
for f in sh.Faces():
|
|
|
|
|
|
for ee in f.Edges():
|
|
|
|
|
|
k = idx.get(ee.hashCode())
|
|
|
|
|
|
if k is not None:
|
|
|
|
|
|
adj[k].append(f)
|
|
|
|
|
|
box = _sel.BoxSelector(lo, hi)
|
|
|
|
|
|
out = []
|
|
|
|
|
|
for i, e in enumerate(edges):
|
|
|
|
|
|
if e.Length() <= 6.0 or len(adj[i]) != 2 or not box.filter([e]):
|
|
|
|
|
|
continue
|
|
|
|
|
|
n1 = _outward(adj[i][0], sh)
|
|
|
|
|
|
n2 = _outward(adj[i][1], sh)
|
|
|
|
|
|
if n1 is None or n2 is None:
|
|
|
|
|
|
continue
|
|
|
|
|
|
dx, dy, dz = n1.x - n2.x, n1.y - n2.y, n1.z - n2.z
|
|
|
|
|
|
ln = math.sqrt(dx * dx + dy * dy + dz * dz)
|
|
|
|
|
|
if ln < 1e-6:
|
|
|
|
|
|
continue
|
|
|
|
|
|
p = e.Center()
|
|
|
|
|
|
if cq.Solid(sh.wrapped).isInside(
|
|
|
|
|
|
cq.Vector(p.x + dx / ln * eps, p.y + dy / ln * eps,
|
|
|
|
|
|
p.z + dz / ln * eps), 1e-6):
|
|
|
|
|
|
out.append(e)
|
|
|
|
|
|
return out
|
|
|
|
|
|
|
|
|
|
|
|
es0 = _pick(s)
|
|
|
|
|
|
if not es0:
|
|
|
|
|
|
print(" [P03 真圆角] %-14s 区域内无凹棱,跳过" % tag, flush=True)
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
def _groups(ee):
|
|
|
|
|
|
"""按共端点把凹棱连成链/网络:一组一次倒,OCC 才能在交汇处生成角部补片;
|
|
|
|
|
|
逐条倒会在交汇处留下断口(看着就像圆角倒一半停了)。"""
|
|
|
|
|
|
pts = [e.Vertices() or [e.Center()] for e in ee]
|
|
|
|
|
|
par = list(range(len(ee)))
|
|
|
|
|
|
|
|
|
|
|
|
def find(a):
|
|
|
|
|
|
while par[a] != a:
|
|
|
|
|
|
par[a] = par[par[a]]
|
|
|
|
|
|
a = par[a]
|
|
|
|
|
|
return a
|
|
|
|
|
|
|
|
|
|
|
|
for i in range(len(ee)):
|
|
|
|
|
|
for j in range(i + 1, len(ee)):
|
|
|
|
|
|
if any(pi.distance(pj) < 0.05 for pi in pts[i] for pj in pts[j]):
|
|
|
|
|
|
par[find(i)] = find(j)
|
|
|
|
|
|
g = {}
|
|
|
|
|
|
for i in range(len(ee)):
|
|
|
|
|
|
g.setdefault(find(i), []).append(ee[i])
|
|
|
|
|
|
return list(g.values())
|
|
|
|
|
|
|
|
|
|
|
|
def _do(edges_, rr):
|
|
|
|
|
|
"""倒完立刻验拓扑:OCC 会给出"没抛异常但面已坏"的结果,必须挡下来。"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
ns = cq.Shape(cq.Solid(s.wrapped).fillet(rr, edges_).wrapped)
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
return None
|
|
|
|
|
|
return ns if cq.Solid(ns.wrapped).isValid() else None
|
|
|
|
|
|
|
|
|
|
|
|
# 先试"区域内全部凹棱一次倒"(探针实测这样能整批成型,且只重建一次,
|
|
|
|
|
|
# 不会像分批那样把同一张面反复重算坏掉);不行再按相连棱分组逐组倒。
|
|
|
|
|
|
for rr in radii:
|
|
|
|
|
|
ns = _do(es0, rr)
|
|
|
|
|
|
if ns is not None:
|
|
|
|
|
|
s = ns
|
|
|
|
|
|
print(" [P03 真圆角] %-14s %d 条凹棱 R%.1f ✓ 整批一次成型"
|
|
|
|
|
|
% (tag, len(es0), rr), flush=True)
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
n_ok, n_grp, left = 0, 0, len(es0)
|
|
|
|
|
|
for _ in range(24):
|
|
|
|
|
|
es = _pick(s)
|
|
|
|
|
|
if not es:
|
|
|
|
|
|
break
|
|
|
|
|
|
got = False
|
|
|
|
|
|
for g in sorted(_groups(es), key=lambda g: -sum(e.Length() for e in g)):
|
|
|
|
|
|
for rr in radii:
|
|
|
|
|
|
ns = _do(g, rr)
|
|
|
|
|
|
if ns is None:
|
|
|
|
|
|
continue
|
|
|
|
|
|
s = ns
|
|
|
|
|
|
n_ok += len(g)
|
|
|
|
|
|
n_grp += 1
|
|
|
|
|
|
print(" [P03 真圆角] %-14s 第%d组 %d 条 R%.1f ✓"
|
|
|
|
|
|
% (tag, n_grp, len(g), rr), flush=True)
|
|
|
|
|
|
got = True
|
|
|
|
|
|
break
|
|
|
|
|
|
if got:
|
|
|
|
|
|
break
|
|
|
|
|
|
if not got:
|
|
|
|
|
|
left = len(es)
|
|
|
|
|
|
break
|
|
|
|
|
|
print(" [P03 真圆角] %-14s 共 %d 组 %d 条凹棱倒圆,剩 %d 条保持尖棱"
|
|
|
|
|
|
% (tag, n_grp, n_ok, left), flush=True)
|
|
|
|
|
|
|
|
|
|
|
|
XR, YC, ZS = X_BACK, Y_ARM, Z_CHEST1 + T_SADDLE # -61, 128, 479
|
|
|
|
|
|
# —— 鞍座顶面 (Z=479) 上的交接内棱:龙骨三条 + 两竖板内侧两条,一次真圆角 ——
|
|
|
|
|
|
# 半径上限 2.0:龙骨侧面 Y=122 与 M5 螺钉头外缘 Y=118.75 只隔 3.25mm,
|
|
|
|
|
|
# 原来的 R3 焊珠会顶到螺帽承压边,R2.0 留 1.25mm。
|
|
|
|
|
|
_fillet_reflex((X_COL - 34.0, Y_ARM - 40.0, ZS - 3.0),
|
|
|
|
|
|
(X_COL + 34.0, Y_ARM + 40.0, ZS + 7.0),
|
|
|
|
|
|
(2.0, 1.5), "鞍座顶面交接")
|
|
|
|
|
|
# —— 法兰背面 (X=-61) 上的交接内棱:只倒竖板/龙骨的竖直棱 ——
|
|
|
|
|
|
# 顶筋底面那条水平棱 (Z=636) 不倒:4x M3 沉孔 Ø6.5 在 Z 627.2..633.7,
|
|
|
|
|
|
# 倒上 R2.5 会把螺钉上方 5.55mm 的扳手让位吃掉 2.5mm。
|
|
|
|
|
|
# 上界取 631:竖板内棱被顶筋底面切成 573..636 / 636..643 两段,只倒下面长的那段
|
|
|
|
|
|
# ——把 636..643 的 7mm 短段并进来,整批就从"一次成型"退化成逐组、且少倒 6 条。
|
|
|
|
|
|
_fillet_reflex((X_BACK - 3.0, Y_ARM - 40.0, 570.0),
|
|
|
|
|
|
(X_BACK + 3.0, Y_ARM + 40.0, 631.0),
|
|
|
|
|
|
(2.5, 2.0, 1.5), "竖板/龙骨↔法兰")
|
|
|
|
|
|
_fillet_reflex((X_BACK - 3.0, Y_ARM - 40.0, Z_ARM + 34.5),
|
|
|
|
|
|
(X_BACK + 3.0, Y_ARM + 40.0, Z_ARM + 35.5),
|
|
|
|
|
|
(1.5, 1.0), "顶筋顶↔法兰")
|
|
|
|
|
|
|
|
|
|
|
|
# 与立柱顶部配合的定位榫头 (43.4x43.4x15mm):配 P01_C 44x44 R4 内腔,单边 0.3mm 滑配
|
2026-09-27 04:48:49 +08:00
|
|
|
|
boss = (cq.Workplane("XY", origin=(X_COL, Y_COL, Z_CHEST1 - 15.0))
|
2026-10-02 04:39:12 +08:00
|
|
|
|
.rect(TENON, TENON)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
.extrude(15.0)
|
2026-10-02 04:39:12 +08:00
|
|
|
|
.edges("|Z").fillet(4.2)).val()
|
2026-09-27 00:28:49 +08:00
|
|
|
|
s = s.fuse(cq.Shape(boss.wrapped))
|
2026-10-02 04:39:12 +08:00
|
|
|
|
|
|
|
|
|
|
# 4x 安装孔:统一 Ø3.9 直孔(M4x16 从腔体正上方拧入自攻成型;鞍座与立柱顶环同径、无沉孔)
|
|
|
|
|
|
# 孔位 (X_COL±27.5, Y_COL±13.5) 同时满足:①在立柱顶环实体壁内(内腔 22 → 外壁 33);
|
|
|
|
|
|
# ②在 P03 两竖板之间、避开中间龙骨,从腔体正上方用扳手可直接拧紧。
|
|
|
|
|
|
for xx in (X_COL - BOLT_DX, X_COL + BOLT_DX):
|
|
|
|
|
|
for yy in (Y_COL - BOLT_DY, Y_COL + BOLT_DY):
|
|
|
|
|
|
s = s.cut(cyl(1.95, Z_CHEST1 - 0.5, Z_CHEST1 + T_SADDLE + 0.5, xx, yy))
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-10-02 04:39:12 +08:00
|
|
|
|
# 1x 横向防脱锁紧:榫头 −X 侧向内 Ø3.9x14 直孔(与立柱后壁 Ø3.9 孔同轴,M4x16 拧入自攻)
|
|
|
|
|
|
s = s.cut(Xcyl(1.95, X_COL - TENON / 2.0 - 1.0, X_COL - TENON / 2.0 + 14.0, Y_COL, Z_LOCK))
|
2026-09-27 04:48:49 +08:00
|
|
|
|
|
2026-10-02 04:39:12 +08:00
|
|
|
|
# 4x M3 连接螺孔(螺丝刀通道直接走两竖板之间的开放腔体,无需再钻 Ø8.5 直通隧道)
|
2026-10-02 12:06:23 +08:00
|
|
|
|
# 孔位 = 电机尾端 4x M3 螺纹径向槽实测位(电机.STEP):BCD55、相位 39.9°+90k。
|
|
|
|
|
|
# 旧 35.1×40.9 矩形孔距与实际槽位差 ~4.7mm(对角两颗螺钉无处咬合),
|
|
|
|
|
|
# 2026-10-02 用户指出"螺钉没有对齐"后按 STEP 实测修正。
|
|
|
|
|
|
for dy, dz in ((21.06, 17.65), (-17.65, 21.06), (-21.06, -17.65), (17.65, -21.06)):
|
|
|
|
|
|
py = Y_ARM + dy
|
|
|
|
|
|
pz = Z_ARM + dz
|
|
|
|
|
|
th = Xcyl(1.7, X_BACK - 0.5, X_MOUNT + 4.0, py, pz)
|
|
|
|
|
|
cb = Xcyl(3.25, X_BACK - 0.5, X_BACK + 4.5, py, pz)
|
|
|
|
|
|
s = s.cut(th).cut(cb)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
|
|
|
|
|
|
# 中央走线孔 (Ø26mm)
|
|
|
|
|
|
wire_hole = Xcyl(13.0, X_COL - 40.0, X_MOUNT + 2.0, Y_ARM, Z_ARM)
|
|
|
|
|
|
s = s.cut(wire_hole)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-10-02 04:39:12 +08:00
|
|
|
|
# 6. 前向电机全包托架 (X: -51.0..8.5+X_BAY_EXT=11.5,Ø60.7 舱孔平直贯通到端面)
|
|
|
|
|
|
# 端面随插槽加长前延 X_BAY_EXT;叉板背面(10.5+X_FORK_GAP=11.5)与端面 0.0 硬贴平
|
|
|
|
|
|
# (用户两次要求"搞成平的";J1 转动摩擦由用户知悉,发涩时可微松 M2)
|
|
|
|
|
|
X_FRONT = 8.5 + X_BAY_EXT
|
2026-09-27 04:48:49 +08:00
|
|
|
|
R_POD = 36.5
|
|
|
|
|
|
R_BORE = 30.35
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
cradle_outer = (cq.Workplane("YZ", origin=(X_MOUNT - 0.1, Y_ARM, Z_ARM))
|
|
|
|
|
|
.circle(R_POD)
|
|
|
|
|
|
.extrude(X_FRONT - X_MOUNT + 0.1)
|
|
|
|
|
|
.edges(">X").chamfer(1.5)).val()
|
|
|
|
|
|
s = s.fuse(cq.Shape(cradle_outer.wrapped))
|
|
|
|
|
|
|
2026-10-02 04:39:12 +08:00
|
|
|
|
# 电机定子配合内腔(最终状态,2026-10-02 用户裁定"去掉台阶改成平的+保留固定电机的面"):
|
|
|
|
|
|
# Ø60.7 圆柱孔壁从前端面平直贯通到舱底(无窄颈、无台阶、无喇叭锥);
|
|
|
|
|
|
# 舱底 = 一个完整的平坦环面(X=5.06+X_BAY_EXT=8.06,与插槽末端墙共面,中开 Ø39 凸台过孔)
|
|
|
|
|
|
# ——即电机前限位面。电机轴向由后端法兰 4xM3x16 约束;
|
|
|
|
|
|
# 前端锁紧由 4 个 Ø10 局部凸台上的 M3 沉头螺钉承担(见下方凸台段)。
|
|
|
|
|
|
motor_pocket = Xcyl(R_BORE, X_MOUNT - 0.2, 5.06 + X_BAY_EXT, Y_ARM, Z_ARM)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
s = s.cut(motor_pocket)
|
2026-10-02 04:39:12 +08:00
|
|
|
|
|
|
|
|
|
|
# 4x 前置 M3 锁紧螺钉凸台(BCD=55mm,17.8°/107.8°/197.8°/287.8°):
|
|
|
|
|
|
# 平直舱孔的沉头座位由 4 个 Ø10 局部凸台承载——凸台位于舱孔前段 8.06..11.5,
|
|
|
|
|
|
# 电机前端面(5.0)之前 3mm,电机斜插路径不经过;M3x10 沉头从凸台端面旋入
|
|
|
|
|
|
# 电机前端面,咬合 3.5mm,兼作电机前端防转定位。
|
2026-09-27 05:02:34 +08:00
|
|
|
|
for deg in (17.8, 107.8, 197.8, 287.8):
|
|
|
|
|
|
rad = math.radians(deg)
|
|
|
|
|
|
fy = Y_ARM + 27.5 * math.cos(rad)
|
|
|
|
|
|
fz = Z_ARM + 27.5 * math.sin(rad)
|
2026-10-02 04:39:12 +08:00
|
|
|
|
s = s.fuse(Xcyl(5.0, 5.06 + X_BAY_EXT, X_FRONT, fy, fz))
|
|
|
|
|
|
th = Xcyl(1.6, 5.06 + X_BAY_EXT, X_FRONT, fy, fz)
|
|
|
|
|
|
cb = Xcyl(3.0, X_FRONT - 2.0, X_FRONT, fy, fz)
|
2026-09-27 05:02:34 +08:00
|
|
|
|
s = s.cut(th).cut(cb)
|
2026-09-27 21:08:28 +08:00
|
|
|
|
|
2026-10-02 04:39:12 +08:00
|
|
|
|
# J1 输出凸台过孔 (Ø39 × 3.44——J1 凸台与 3xM2 输出螺钉的必经孔,非台阶;
|
|
|
|
|
|
# 原 6.7mm 长颈与半圆台肩已随舱底前移一并消除)
|
|
|
|
|
|
hub_clearance = Xcyl(19.5, 4.8, X_FRONT + 0.5, Y_ARM, Z_ARM)
|
|
|
|
|
|
s = s.cut(hub_clearance)
|
|
|
|
|
|
|
2026-09-27 21:08:28 +08:00
|
|
|
|
# 8. 电机托架 +Y 侧全开(侧开式半包,替代原封闭全包筒):
|
|
|
|
|
|
# M1 电机可从 +Y 侧方直线滑入托架完成装配——原封闭筒电机物理上无法装入。
|
2026-10-02 04:39:12 +08:00
|
|
|
|
# 轴向约束:后端法兰 4xM3(电机尾端面)单向锁死(前置止脱法兰随平直舱孔要求取消);
|
|
|
|
|
|
# 径向约束:Ø60.7 精密滑配托架底 + 重力贴底。开口前端至 5.06+X_BAY_EXT=8.06
|
|
|
|
|
|
# (比电机前端面多 3mm 斜插余量,电机可倾斜卡入),止脱法兰环随之前移、环宽保持 3.44mm。
|
|
|
|
|
|
s = s.cut(bx(X_MOUNT, 5.06 + X_BAY_EXT, Y_ARM, Y_ARM + 60.0, Z_ARM - 60.0, Z_ARM + 60.0))
|
2026-09-27 05:02:34 +08:00
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
# 7. 散热系统:双侧大视窗 + 顶部斜向对流排热槽
|
|
|
|
|
|
for sign in (-1, 1):
|
|
|
|
|
|
win_plane = cq.Plane(
|
|
|
|
|
|
origin=(-24.5, Y_ARM + sign * 35.0, Z_ARM),
|
|
|
|
|
|
xDir=(1, 0, 0),
|
|
|
|
|
|
normal=(0, sign, 0)
|
|
|
|
|
|
)
|
|
|
|
|
|
win_cut = cq.Workplane(win_plane).slot2D(34.0, 20.0).extrude(16.0, both=True).val()
|
|
|
|
|
|
s = s.cut(win_cut)
|
|
|
|
|
|
|
|
|
|
|
|
for deg in (45, 135):
|
|
|
|
|
|
rad = math.radians(deg)
|
|
|
|
|
|
slot_plane = cq.Plane(
|
|
|
|
|
|
origin=(-24.5, Y_ARM + 33.0 * math.cos(rad), Z_ARM + 33.0 * math.sin(rad)),
|
2026-09-27 00:28:49 +08:00
|
|
|
|
xDir=(1, 0, 0),
|
|
|
|
|
|
normal=(0, math.cos(rad), math.sin(rad))
|
|
|
|
|
|
)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
slot_cut = cq.Workplane(slot_plane).slot2D(30.0, 6.5).extrude(15.0, both=True).val()
|
|
|
|
|
|
s = s.cut(slot_cut)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
|
2026-09-26 18:05:21 +08:00
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_fork(j1, j2):
|
2026-09-28 03:33:27 +08:00
|
|
|
|
"""P04_肩叉_螺旋体30%_墙5底5_竖打 (Shoulder Fork / L-Bracket) - 加长避让顺滑流线版:
|
2026-10-02 04:39:12 +08:00
|
|
|
|
1. 头部与身子起点自 X=5.5 前移加长至 X=10.5+X_FORK_GAP=11.5,叉板背面与 P03 托架端面
|
|
|
|
|
|
(X=8.5+X_BAY_EXT=11.5) 0.0 硬贴平(2026-10-02 用户两次要求"搞成平的";
|
|
|
|
|
|
P03 侧插槽独立加长 3mm 便于 M1 电机斜插卡入);
|
2026-09-28 00:02:01 +08:00
|
|
|
|
2. J1 从动法兰圆盘已删除(盘面在 column 前缘形成鼓楞):J1 由 boss(Ø35.6)贯通 P03 前盖中心孔直连电机输出盘;column 顶边保持 Z=646.5 与 P03 环齐高,R=18mm 大圆弧顺滑过渡;
|
2026-09-27 05:02:34 +08:00
|
|
|
|
3. 头部转接凸台加长贯通 P03 前盖中心孔 (R=19.5mm),直连 J1 旋转法兰盘;
|
2026-09-28 00:02:01 +08:00
|
|
|
|
4. M2 保留后端安装板(R=35mm, 带 rear_mount_holes 螺钉孔),前端定位环鼓出圆盘已删除(前端定位由 column 端面 pocket 承担),中间镂空散热;
|
2026-10-02 12:06:23 +08:00
|
|
|
|
4b. 【2026-10-02 新增】M2 前端压盖:原方案电机只被后端安装板(S02 4xM3x10)单面锁死,
|
|
|
|
|
|
大扭矩下电机绕 Y 轴在 Ø60.3 座孔里点头/翘起,固定不牢。现在前端盖外端面
|
|
|
|
|
|
(Y=156.0) 再加一枚同径 R35 压盖,用 4x M3x8 在电机前端盖 BCD55 上把电机
|
|
|
|
|
|
从前端夹一次 —— 电机被前后两块同心 Ø60.3 端面双向夹紧,倾斜自由度归零;
|
|
|
|
|
|
螺钉沉在压盖沉孔内不外凸,不占用 J2 轴向间隙(P05 法兰盘已相应后移);
|
2026-09-27 05:02:34 +08:00
|
|
|
|
5. 严格满足 single-solid 流形拓扑与 360° 全范围零干涉 (COLLISION pairs = 0)。
|
2026-09-26 18:05:21 +08:00
|
|
|
|
"""
|
2026-09-27 00:28:49 +08:00
|
|
|
|
# 1. M2 后端安装法兰盘 (Y: 92..100, R=35mm)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
rear_plate = Ycyl(35.0, Y_REAR - 8.0, Y_REAR, X_ARM, Z_SH)
|
|
|
|
|
|
|
2026-09-27 05:02:34 +08:00
|
|
|
|
# 2. M2 前端定位环 (Y: 149.5..155.5, R=35mm)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
front_collar = Ycyl(35.0, Y_COVER - 6.5, Y_COVER - 0.5, X_ARM, Z_SH)
|
|
|
|
|
|
s = rear_plate.fuse(front_collar)
|
|
|
|
|
|
|
2026-10-02 12:06:23 +08:00
|
|
|
|
# 2b. 【2026-10-02 新增】M2 前端压盖 (Y: 155.5..161.0, R=35,与后端板同径)
|
|
|
|
|
|
# 根部与 front_collar 前端面 (Y_COVER-0.5=155.5) 共面熔接成一体,无缝隙、无悬浮面。
|
|
|
|
|
|
# 压盖背面 (Y_COVER=156.0) 与电机前端盖外端面 0.0 间隙面压贴合;Ø37 中央让位孔
|
|
|
|
|
|
# 让出 P05 的 J2 直锁凸台 (R17.8) 与 3xS01 输出螺钉头;Ø60.3 让位槽把压盖背面
|
|
|
|
|
|
# 精确落在 Y=156.0,不让根部那 0.5mm 啃到电机前端盖 R30.15 的外圆。
|
|
|
|
|
|
FP_Y0 = Y_COVER - 0.5 # 155.5 压盖根部(= front_collar 前端面,保证熔接)
|
|
|
|
|
|
FP_Y1 = Y_COVER + 5.0 # 161.0 压盖前端面(与 P05 法兰盘 162.0 留 1.0mm 动间隙)
|
|
|
|
|
|
FP_BORE = 27.5 # 4xM3 分布圆半径 (BCD55,与 P03→M1 的 S04 同约定)
|
|
|
|
|
|
fp = Ycyl(35.0, FP_Y0, FP_Y1, X_ARM, Z_SH)
|
|
|
|
|
|
fp = fp.cut(Ycyl(18.5, FP_Y0 - 0.5, FP_Y1 + 0.5, X_ARM, Z_SH)) # Ø37 中央让位孔
|
|
|
|
|
|
fp = fp.cut(Ycyl(30.15, FP_Y0 - 0.5, Y_COVER, X_ARM, Z_SH)) # Ø60.3 让位槽
|
|
|
|
|
|
for deg in (17.8, 107.8, 197.8, 287.8):
|
|
|
|
|
|
rad = math.radians(deg)
|
|
|
|
|
|
fu, fz = X_ARM + FP_BORE * math.cos(rad), Z_SH + FP_BORE * math.sin(rad)
|
|
|
|
|
|
# Ø6.0 沉孔深 3.0 (自前端面 FP_Y1 往 -Y 沉到 Y=158.0):M3 圆柱头(Ø5.5x3.0)
|
|
|
|
|
|
# 全沉入压盖,头面 Y=158.0 压在 Ø3.4 孔口台阶上;压盖背面(156.0)压电机前端盖,
|
|
|
|
|
|
# 中间 2.0mm 压盖本体受压 —— 夹紧力全部走面压,螺钉只提供压紧力不提供定位。
|
|
|
|
|
|
fp = fp.cut(Ycyl(3.0, Y_COVER + 2.0, FP_Y1 + 0.5, fu, fz))
|
|
|
|
|
|
fp = fp.cut(Ycyl(1.7, Y_COVER - 0.5, Y_COVER + 2.0, fu, fz))
|
|
|
|
|
|
# 压盖在第 7 步 M2 接口成型(座孔/让位槽)之后才熔接,避免被那些 R30.15~30.5 的
|
|
|
|
|
|
# 圆柱刀具蹭掉根部一圈 0.1mm 薄边。
|
|
|
|
|
|
|
2026-09-28 00:02:01 +08:00
|
|
|
|
# 3. J1 从动法兰圆盘已删除:原 R=36.5 圆盘盘面在 column 前缘形成圆盘鼓楞,
|
|
|
|
|
|
# J1 与 P04 的连接由 boss(Ø35.6 贯通 P03 前盖中心孔 R=19.5)直连电机输出盘
|
|
|
|
|
|
# 承担,螺钉走 boss 端面 4xB 孔,圆盘无传力功能已去除。
|
2026-09-27 00:28:49 +08:00
|
|
|
|
|
2026-09-27 21:08:28 +08:00
|
|
|
|
# 4. XZ 平面有机连续流线轮廓(随 X_FORK_GAP 整体前移,避让顺滑过渡):
|
|
|
|
|
|
x_b, z_b = -12.65 + X_FORK_GAP, 506.0
|
|
|
|
|
|
x_a, z_a = 10.5 + X_FORK_GAP, 545.0
|
2026-09-26 18:05:21 +08:00
|
|
|
|
Lz = z_a - z_b
|
|
|
|
|
|
d0 = 0.514 * Lz
|
|
|
|
|
|
d1 = 0.0
|
|
|
|
|
|
|
|
|
|
|
|
hermite_pts = []
|
|
|
|
|
|
N_h = 16
|
|
|
|
|
|
for i in range(N_h + 1):
|
|
|
|
|
|
t = i / N_h
|
|
|
|
|
|
h00 = 2.0 * (t**3) - 3.0 * (t**2) + 1.0
|
|
|
|
|
|
h10 = t**3 - 2.0 * (t**2) + t
|
|
|
|
|
|
h01 = -2.0 * (t**3) + 3.0 * (t**2)
|
|
|
|
|
|
h11 = t**3 - t**2
|
|
|
|
|
|
xh = x_b * h00 + d0 * h10 + x_a * h01 + d1 * h11
|
|
|
|
|
|
zh = z_b + t * Lz
|
|
|
|
|
|
hermite_pts.append((xh, zh))
|
|
|
|
|
|
|
2026-09-27 21:08:28 +08:00
|
|
|
|
dx_flare = (53.5 + X_FORK_GAP) - (44.0 + X_FORK_GAP)
|
2026-09-27 05:02:34 +08:00
|
|
|
|
dz_flare = 545.0 - 490.0
|
|
|
|
|
|
R_flare = (dx_flare**2 + dz_flare**2) / (2.0 * dx_flare)
|
|
|
|
|
|
|
2026-09-26 18:05:21 +08:00
|
|
|
|
xz_wire = (cq.Workplane("XZ", origin=(0, Y_AXIS, 0))
|
2026-09-27 21:08:28 +08:00
|
|
|
|
.moveTo(10.5 + X_FORK_GAP, 545.0)
|
2026-09-28 00:02:01 +08:00
|
|
|
|
.lineTo(10.5 + X_FORK_GAP, Z_RL + 36.5)
|
|
|
|
|
|
.lineTo(28.0 + X_FORK_GAP, Z_RL + 36.5)
|
2026-09-27 21:08:28 +08:00
|
|
|
|
.radiusArc((44.0 + X_FORK_GAP, 630.0), 18.0)
|
|
|
|
|
|
.lineTo(44.0 + X_FORK_GAP, 545.0)
|
|
|
|
|
|
.radiusArc((53.5 + X_FORK_GAP, 490.0), -R_flare)
|
|
|
|
|
|
.lineTo(18.5 + X_FORK_GAP, 490.0)
|
|
|
|
|
|
.lineTo(-16.5 + X_FORK_GAP, 490.0)
|
|
|
|
|
|
.threePointArc((-15.1 + X_FORK_GAP, 498.5), (-12.65 + X_FORK_GAP, 506.0)))
|
2026-09-26 18:05:21 +08:00
|
|
|
|
for pt in hermite_pts[1:]:
|
|
|
|
|
|
xz_wire = xz_wire.lineTo(pt[0], pt[1])
|
|
|
|
|
|
xz_wire = xz_wire.close()
|
2026-09-27 05:02:34 +08:00
|
|
|
|
xz_shape = cq.Shape(xz_wire.extrude(100.0, both=True).val().wrapped)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 05:02:34 +08:00
|
|
|
|
# 5. YZ 平面包络
|
2026-09-26 18:05:21 +08:00
|
|
|
|
yz_pts = [
|
2026-09-28 00:02:01 +08:00
|
|
|
|
(Y_AXIS - 36.5, Z_RL + 36.5),
|
|
|
|
|
|
(Y_AXIS + 36.5, Z_RL + 36.5),
|
2026-09-26 18:05:21 +08:00
|
|
|
|
(Y_COVER - 0.5, Z_SH + 36.0),
|
|
|
|
|
|
(Y_COVER - 0.5, Z_SH),
|
|
|
|
|
|
(Y_REAR - 8.0, Z_SH),
|
|
|
|
|
|
(Y_REAR - 8.0, Z_SH + 36.0),
|
|
|
|
|
|
]
|
|
|
|
|
|
yz_solid = Xplate(yz_pts, -20.0, 60.0)
|
|
|
|
|
|
|
|
|
|
|
|
c_int = BRepAlgoAPI_Common(yz_solid.wrapped, xz_shape.wrapped)
|
|
|
|
|
|
c_int.Build()
|
|
|
|
|
|
column = cq.Shape(c_int.Shape())
|
|
|
|
|
|
|
2026-09-27 00:28:49 +08:00
|
|
|
|
s = s.fuse(column)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 05:02:34 +08:00
|
|
|
|
# 6. 中部电机定子散热切除
|
2026-09-27 00:28:49 +08:00
|
|
|
|
s = s.cut(Ycyl(30.5, Y_REAR + 0.5, Y_COVER - 6.5, X_ARM, Z_SH))
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 00:28:49 +08:00
|
|
|
|
# 7. M2 接口成型
|
2026-09-26 18:05:21 +08:00
|
|
|
|
s = j2.front_collar_pocket(s, r_bore=30.25, z0=50.0, z1=56.5)
|
|
|
|
|
|
s = j2.rear_mount_holes(s, t_plate=8.0, hole_d=2.8, cb_d=5.5, cb_depth=4.0)
|
|
|
|
|
|
c_m2 = [cyl(BORE_R, -0.6, COVER_Z - 3.5), cyl(CB_R, COVER_Z - 3.5, COVER_Z + 0.6)]
|
|
|
|
|
|
s = s.cut(*[j2.L(item) for item in c_m2])
|
|
|
|
|
|
|
2026-10-02 12:06:23 +08:00
|
|
|
|
# 7b. M2 前端压盖熔接(见 2b):必须在 6/7 步所有 R30.15~30.5 圆柱刀具走完之后,
|
|
|
|
|
|
# 否则压盖根部会被 front_collar_pocket / c_m2 啃掉一圈 0.1mm 薄边。
|
|
|
|
|
|
s = s.fuse(fp)
|
|
|
|
|
|
|
2026-09-27 21:08:28 +08:00
|
|
|
|
# 8. 头部转接凸台加长(贯通 P03 前盖中心孔,跨越装配缝直连 J1 输出盘)
|
|
|
|
|
|
boss = cyl(17.8, 54.942, 61.5 + X_FORK_GAP)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
s = s.fuse(j1.L(boss))
|
|
|
|
|
|
s = s.cut(j1.L(cyl(3.5, 54.0, 74.0 + 30.0)))
|
|
|
|
|
|
for a in AB.HUB_M2_CLOCK:
|
|
|
|
|
|
u = AB.M['m2_bcd'] / 2.0 * math.cos(a * AB.D2R)
|
|
|
|
|
|
v = AB.M['m2_bcd'] / 2.0 * math.sin(a * AB.D2R)
|
2026-09-27 21:08:28 +08:00
|
|
|
|
th = cyl(1.4, 54.0, 63.0 + X_FORK_GAP, u, v)
|
2026-10-02 04:39:12 +08:00
|
|
|
|
# 沉孔台阶固定在 63.0(不随前移):M2x10 旋入电机输出毂的咬合量与改前一致;
|
|
|
|
|
|
# 螺钉头(63..65)相对叉板背面(64.5)外露 0.5mm,位于 2mm 叉缝空隙内,无干涉。
|
|
|
|
|
|
cb = cyl(2.8, 63.0, 74.0 + 40.0 + X_FORK_GAP, u, v)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
s = s.cut(j1.L(th)).cut(j1.L(cb))
|
|
|
|
|
|
|
|
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
|
2026-10-02 12:06:23 +08:00
|
|
|
|
def make_pitch_to_roll_bracket(j_pitch, j_roll, z_pitch, z_r, name="bracket", hub_gap=1.0):
|
2026-09-26 18:05:21 +08:00
|
|
|
|
"""Half-wrapped (半包) 双曲面有机流线型 Pitch-to-Roll 结构座 (P05 & P08):
|
2026-09-27 00:28:49 +08:00
|
|
|
|
1. 顶部从动法兰与前侧 Loft 自然相切顺接;
|
|
|
|
|
|
2. 严格清除 z_plate 顶面以上与上级旋转件贴面的多余材料 (cut_top_solid),保证关节大范围摆动动态 0 干涉;
|
|
|
|
|
|
3. 下方电机实行半包散热设计,-Y侧敞开,+Y侧背脊与圆柱一体化融合;
|
|
|
|
|
|
4. 严格满足 single-solid 流形拓扑与零干涉 (COLLISION pairs = 0)。
|
2026-10-02 12:06:23 +08:00
|
|
|
|
|
|
|
|
|
|
hub_gap = 从动法兰盘背面与上级电机前端盖之间的轴向让位间隙。
|
|
|
|
|
|
默认 1.0(贴合防磨)。P05 传 6.0:J2 处 P04 新增了 M2 前端压盖
|
|
|
|
|
|
(Y 155.5..161.0),必须让出这 6.0mm 才能装下;见 p_shoulder_roll_base。
|
2026-09-26 18:05:21 +08:00
|
|
|
|
"""
|
2026-09-27 00:28:49 +08:00
|
|
|
|
z_bot = z_r - 56.0 # roll 电机底端 (front collar)
|
|
|
|
|
|
z_plate = z_r + 7.0 # roll 电机顶端安装板 (rear plate top)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
y_out = HL.Y_HUB + HL.PLATE_T # 174.0 (俯仰直连法兰外侧面)
|
2026-10-02 12:06:23 +08:00
|
|
|
|
y_hub_in = HL.Y_COVER + hub_gap # 157.0 / (P05) 162.0 从动法兰内侧面
|
|
|
|
|
|
z_hub_in = y_hub_in - HL.Y_REAR # 法兰盘背面的电机局部 z(凸台长度跟着它走)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
y_cyl_max = HL.Y_AXIS + 35.0 # 163.0 (下方电机外轮廓极值)
|
|
|
|
|
|
|
|
|
|
|
|
# 1. 基础立柱:Ø70mm 实心圆柱 (Z: z_bot .. z_plate, R=35mm)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
s = cyl(35.0, z_bot, z_plate, HL.X_ARM, HL.Y_AXIS)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 00:28:49 +08:00
|
|
|
|
# 2. 俯仰轴直连法兰盘:全圆柱实体 (Y: y_hub_in .. y_out, R=35mm)
|
|
|
|
|
|
disc = Ycyl(35.0, y_hub_in, y_out, HL.X_ARM, z_pitch)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
s = s.fuse(disc)
|
|
|
|
|
|
|
2026-09-27 00:28:49 +08:00
|
|
|
|
# 3. 前侧从底端 Ø70mm 圆柱到顶端法兰的有机相切平滑渐变过渡体 (Loft Morph)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
Z_top = z_pitch - 35.0
|
|
|
|
|
|
z_start = z_bot
|
2026-09-28 03:33:27 +08:00
|
|
|
|
N = 16
|
2026-09-26 18:05:21 +08:00
|
|
|
|
wp = cq.Workplane("XY")
|
|
|
|
|
|
for i in range(N + 1):
|
|
|
|
|
|
t = i / float(N)
|
|
|
|
|
|
z_curr = z_start + t * (Z_top - z_start)
|
|
|
|
|
|
st = 3.0 * (t**2) - 2.0 * (t**3)
|
|
|
|
|
|
y_center = y_cyl_max + st * (y_out - y_cyl_max)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
y_side = HL.Y_AXIS + st * (y_out - HL.Y_AXIS)
|
|
|
|
|
|
v_c = y_center - HL.Y_AXIS
|
|
|
|
|
|
v_s = y_side - HL.Y_AXIS
|
2026-09-26 18:05:21 +08:00
|
|
|
|
v_mid = max(v_c, v_s + 0.02)
|
2026-09-28 03:33:27 +08:00
|
|
|
|
# 后缘两角 R2 圆角:把 y=123 凸包与 R35 柱面交汇的两条 90° 竖棱圆润化
|
|
|
|
|
|
# (磨掉"凸起来的"尖角,不动后缘高度/位置,打印无悬挂)
|
|
|
|
|
|
FR = 2.0
|
2026-09-27 00:28:49 +08:00
|
|
|
|
w = (cq.Workplane("XY", origin=(HL.X_ARM, HL.Y_AXIS, z_curr))
|
2026-09-26 18:05:21 +08:00
|
|
|
|
.moveTo(-35.0, v_s)
|
|
|
|
|
|
.threePointArc((0.0, v_mid), (35.0, v_s))
|
2026-09-28 03:33:27 +08:00
|
|
|
|
.lineTo(35.0, -5.0 + FR)
|
|
|
|
|
|
.radiusArc((35.0 - FR, -5.0), FR)
|
|
|
|
|
|
.lineTo(-35.0 + FR, -5.0)
|
|
|
|
|
|
.radiusArc((-35.0, -5.0 + FR), FR)
|
|
|
|
|
|
.lineTo(-35.0, v_s)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
.close())
|
|
|
|
|
|
wp = wp.add(w)
|
|
|
|
|
|
|
|
|
|
|
|
loft = wp.toPending().loft()
|
|
|
|
|
|
s = s.fuse(loft.val())
|
|
|
|
|
|
|
2026-09-27 00:28:49 +08:00
|
|
|
|
# 4. 顶部填充(仅保留 y >= y_hub_in 与法兰盘对齐的部分,避免侵入上级关节旋转扫掠区域)
|
|
|
|
|
|
top_fill = (cq.Workplane("YZ", origin=(HL.X_ARM, 0, 0))
|
|
|
|
|
|
.moveTo(y_hub_in, Z_top)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
.lineTo(y_out, Z_top)
|
|
|
|
|
|
.lineTo(y_out, z_pitch)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
.lineTo(y_hub_in, z_pitch)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
.close()
|
|
|
|
|
|
.extrude(35.0, both=True))
|
|
|
|
|
|
s = s.fuse(top_fill.val())
|
|
|
|
|
|
|
2026-09-27 00:28:49 +08:00
|
|
|
|
# 5. 旋转清让切除:彻底清除 z >= z_plate 且 y <= y_hub_in 范围内的多余材料,
|
|
|
|
|
|
# 消除导致与上游旋转件(P04/P07)严重干涉的立壁与尖角,保持顶面平整规整!
|
|
|
|
|
|
cut_top_solid = (cq.Workplane("YZ", origin=(HL.X_ARM, 0, 0))
|
|
|
|
|
|
.moveTo(-999.0, z_plate)
|
|
|
|
|
|
.lineTo(y_hub_in, z_plate)
|
|
|
|
|
|
.lineTo(y_hub_in, z_pitch + 50.0)
|
|
|
|
|
|
.lineTo(-999.0, z_pitch + 50.0)
|
|
|
|
|
|
.close()
|
|
|
|
|
|
.extrude(60.0, both=True))
|
|
|
|
|
|
s = s.cut(cut_top_solid.val())
|
|
|
|
|
|
|
|
|
|
|
|
# 6. 电机半包处理 (Half-Enclosure):-Y侧敞开散热,+Y侧背脊壳体加强
|
|
|
|
|
|
cut_open = bx(HL.X_ARM - 40.0, HL.X_ARM + 40.0, HL.Y_AXIS - 40.0, HL.Y_AXIS + 3.0, z_bot + 6.0, z_r - 1.0)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
s = s.cut(cut_open)
|
|
|
|
|
|
|
2026-09-27 00:28:49 +08:00
|
|
|
|
# 7. 上级电机同心圆弧避让
|
|
|
|
|
|
clearance = Ycyl(35.5, HL.Y_AXIS - 40.0, HL.Y_COVER + 0.1, HL.X_ARM, z_pitch)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
s = s.cut(clearance)
|
|
|
|
|
|
|
2026-09-27 00:28:49 +08:00
|
|
|
|
# 8. 下方电机安装孔位与定位止口
|
2026-09-26 18:05:21 +08:00
|
|
|
|
s = j_roll.rear_mount_holes(s, t_plate=7.0, hole_d=2.8, cb_d=5.5, cb_depth=4.0)
|
|
|
|
|
|
s = j_roll.front_collar_pocket(s, r_bore=30.25, z0=50.0, z1=56.5)
|
|
|
|
|
|
s = j_roll.pocket(s)
|
|
|
|
|
|
|
2026-09-27 00:28:49 +08:00
|
|
|
|
# 9. 电机定子配合空腔
|
|
|
|
|
|
s = s.cut(cyl(30.5, z_r - 49.5, z_r - 0.5, HL.X_ARM, HL.Y_AXIS))
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-10-02 12:06:23 +08:00
|
|
|
|
# 10. 俯仰轴直连法兰结构(凸台延伸至法兰盘背面之后 2.5mm,跨过间隙与法兰盘牢固熔接,
|
|
|
|
|
|
# 保持单实体)。凸台长度跟着 y_hub_in 走:法兰盘后移时凸台同步加长,
|
|
|
|
|
|
# 3xS01 输出螺钉的头面台阶(局部 z=58)、杆长、咬合量与改前完全一致。
|
|
|
|
|
|
boss = cyl(17.8, 54.942, z_hub_in + 2.5)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
s = s.fuse(j_pitch.L(boss))
|
|
|
|
|
|
s = s.cut(j_pitch.L(cyl(3.5, 54.0, 74.0 + 30.0)))
|
|
|
|
|
|
for a in AB.HUB_M2_CLOCK:
|
|
|
|
|
|
u = AB.M["m2_bcd"] / 2.0 * math.cos(a * AB.D2R)
|
|
|
|
|
|
v = AB.M["m2_bcd"] / 2.0 * math.sin(a * AB.D2R)
|
|
|
|
|
|
th = cyl(1.4, 54.0, 58.0, u, v)
|
|
|
|
|
|
cb = cyl(2.8, 58.0, 74.0 + 40.0, u, v)
|
|
|
|
|
|
s = s.cut(j_pitch.L(th)).cut(j_pitch.L(cb))
|
|
|
|
|
|
|
2026-09-27 16:52:27 +08:00
|
|
|
|
# 11. L 型转角连接处圆角过渡(圆角 R=2.0mm):
|
|
|
|
|
|
# 平滑消除立柱顶面与竖直臂交汇处的 90° 尖角与应力集中
|
2026-09-27 00:28:49 +08:00
|
|
|
|
try:
|
|
|
|
|
|
wp_s = cq.Workplane(obj=s)
|
|
|
|
|
|
sel_l = cq.NearestToPointSelector((HL.X_ARM, y_hub_in, z_plate))
|
2026-09-27 16:52:27 +08:00
|
|
|
|
s = wp_s.edges(sel_l).fillet(2.0).val()
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"[{name}] L型转角圆角异常: {e}")
|
2026-09-27 00:28:49 +08:00
|
|
|
|
|
2026-09-26 18:05:21 +08:00
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_shoulder_roll_base(j2, j3, half=None):
|
2026-10-02 12:06:23 +08:00
|
|
|
|
"""P05_大臂旋转座_螺旋体30%_墙4底5_竖打(深度圆角优化版)
|
|
|
|
|
|
|
|
|
|
|
|
hub_gap=6.0:J2 处 P04 新增了 M2 前端压盖(前端夹紧电机,消除大扭矩下的倾斜),
|
|
|
|
|
|
压盖占 Y 155.5..161.0,所以从动法兰盘背面必须从 Y=157 后移到 Y=162(留 1.0mm 动间隙)。
|
|
|
|
|
|
P08 保持默认 1.0 —— J5 处 P07 没有前端压盖,不需要这段轴向空间。
|
|
|
|
|
|
"""
|
|
|
|
|
|
return make_pitch_to_roll_bracket(j2, j3, Z_SH, Z_R3,
|
|
|
|
|
|
name="P05_大臂旋转座_螺旋体30%_墙4底5_竖打",
|
|
|
|
|
|
hub_gap=6.0)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_humerus_bone(j3, j4):
|
2026-09-28 03:33:27 +08:00
|
|
|
|
"""P06_大臂骨架_螺旋体25%_墙4底5_竖打 (Humerus Bone - Loft 圆弧转方有机过渡版):
|
2026-09-26 18:05:21 +08:00
|
|
|
|
受 J3 (大臂自转, -Z轴, hub@Z_HUB3=380) 驱动,
|
|
|
|
|
|
向下延伸构成大臂主体骨架,底端抱紧 M4 (肘部俯仰电机, +Y轴, 轴线位于 Z_EL=332.0)。
|
2026-09-27 05:02:34 +08:00
|
|
|
|
1. 借鉴 P05 大臂旋转座几何放样算法:
|
|
|
|
|
|
- 顶端结合面 (Z = 388.5mm):与 J3 轴径严格相切的 Ø70mm 正圆形轮廓,彻底消除原先外突的方形水平阶梯;
|
|
|
|
|
|
- 底端结合面 (Z = 367.0mm):平滑展开融入 M4 电机套筒的 70x63.5mm 方形截面;
|
|
|
|
|
|
- 过渡区 (Z: 367.0..388.5mm):采用 Hermite s(t) = 3t² - 2t³ 驱动 20 层放样切片连续渐变;
|
|
|
|
|
|
2. 下部抱紧套筒与安装板 (R=35mm),电机定子 100% 裸露散热开窗;
|
|
|
|
|
|
3. 严格单实体 (solids = 1) 且与上下级旋转构件及电机实现动态 0 碰撞干涉。
|
2026-09-26 18:05:21 +08:00
|
|
|
|
"""
|
|
|
|
|
|
# 1. M4 底部抱紧套筒与后端安装板 (R=35mm)
|
|
|
|
|
|
rear_m4 = Ycyl(35.0, Y_REAR - 8.0, Y_REAR, X_ARM, Z_EL)
|
|
|
|
|
|
front_m4 = Ycyl(35.0, Y_COVER - 6.0, Y_COVER - 0.5, X_ARM, Z_EL)
|
|
|
|
|
|
s = rear_m4.fuse(front_m4)
|
|
|
|
|
|
|
2026-09-27 05:02:34 +08:00
|
|
|
|
# 顶端结合面与过渡高度
|
2026-09-26 18:05:21 +08:00
|
|
|
|
z_top = 388.5
|
|
|
|
|
|
z_bot = Z_EL + 35.0 # 367.0
|
|
|
|
|
|
|
2026-09-27 05:02:34 +08:00
|
|
|
|
# 2. 下部实心基座块 (Z: Z_EL..z_bot + 0.5)
|
|
|
|
|
|
lower_block = bx(X_ARM - 35.0, X_ARM + 35.0, Y_REAR - 8.0, Y_COVER - 0.5, Z_EL, z_bot + 0.5)
|
|
|
|
|
|
s = s.fuse(lower_block)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 05:02:34 +08:00
|
|
|
|
# 3. 借鉴 P05 的 Loft 放样过渡体:圆弧变方形(20 层平滑放样,保持严格对称 4 段式截面拓扑)
|
|
|
|
|
|
N = 20
|
|
|
|
|
|
wp = cq.Workplane("XY")
|
|
|
|
|
|
for i in range(N + 1):
|
|
|
|
|
|
t = i / float(N)
|
|
|
|
|
|
z_curr = z_bot + t * (z_top - z_bot)
|
|
|
|
|
|
st = 3.0 * (t**2) - 2.0 * (t**3)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 05:02:34 +08:00
|
|
|
|
# 前侧:t=0 为平直面 (Y=155.5, v=27.5),t=1 渐变为与 Ø70 正切的圆弧顶点 (Y=163.0, v=35.0)
|
|
|
|
|
|
v_sf = 27.5 * (1.0 - st) + 0.05 * st
|
|
|
|
|
|
v_cf = max(27.5 * (1.0 - st) + 35.0 * st, v_sf + 0.05)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 05:02:34 +08:00
|
|
|
|
# 后侧:从 t=0 的平直面 (Y=92.0, v=-36.0) 渐变到 t=1 的圆弧 (Y=93.0, v=-35.0)
|
|
|
|
|
|
v_sr = -36.0 * (1.0 - st) - 0.05 * st
|
|
|
|
|
|
v_cr = min(-36.0 * (1.0 - st) - 35.0 * st, v_sr - 0.05)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 05:02:34 +08:00
|
|
|
|
w = (cq.Workplane("XY", origin=(X_ARM, Y_AXIS, z_curr))
|
|
|
|
|
|
.moveTo(-35.0, v_sf)
|
|
|
|
|
|
.threePointArc((0.0, v_cf), (35.0, v_sf))
|
|
|
|
|
|
.lineTo(35.0, v_sr)
|
|
|
|
|
|
.threePointArc((0.0, v_cr), (-35.0, v_sr))
|
|
|
|
|
|
.close())
|
|
|
|
|
|
wp = wp.add(w)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 05:02:34 +08:00
|
|
|
|
loft = wp.toPending().loft()
|
|
|
|
|
|
s = s.fuse(loft.val())
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
|
|
|
|
|
# 4. 电机中间定子散热裸露切除 (100% 裸露)
|
|
|
|
|
|
s = s.cut(Ycyl(30.5, Y_REAR + 0.5, Y_COVER - 6.5, X_ARM, Z_EL))
|
|
|
|
|
|
|
2026-09-27 05:02:34 +08:00
|
|
|
|
# 5. M4 接口成型
|
2026-09-26 18:05:21 +08:00
|
|
|
|
s = j4.front_collar_pocket(s, r_bore=30.25, z0=50.0, z1=56.5)
|
|
|
|
|
|
s = j4.rear_mount_holes(s, t_plate=8.0, hole_d=2.8, cb_d=5.5, cb_depth=4.0)
|
|
|
|
|
|
s = j4.pocket(s)
|
2026-09-27 05:02:34 +08:00
|
|
|
|
|
|
|
|
|
|
# 6. J3 直连法兰结构(凸台延伸至 59.5 跨过结合面牢固熔接,保持单实体与零干涉)
|
|
|
|
|
|
boss = cyl(17.8, 54.942, 59.5)
|
|
|
|
|
|
chamfer_cone = cyl(18.5, 54.5, 54.942)
|
|
|
|
|
|
s = s.fuse(j3.L(boss)).cut(j3.L(chamfer_cone))
|
|
|
|
|
|
s = s.cut(j3.L(cyl(3.5, 54.0, 58.0 + 30.0)))
|
|
|
|
|
|
for a in AB.HUB_M2_CLOCK:
|
|
|
|
|
|
u = AB.M["m2_bcd"] / 2.0 * math.cos(a * AB.D2R)
|
|
|
|
|
|
v = AB.M["m2_bcd"] / 2.0 * math.sin(a * AB.D2R)
|
|
|
|
|
|
th = cyl(1.4, 54.0, 58.0, u, v)
|
|
|
|
|
|
cb = cyl(2.8, 58.0, 58.0 + 40.0, u, v)
|
|
|
|
|
|
s = s.cut(j3.L(th)).cut(j3.L(cb))
|
|
|
|
|
|
|
2026-09-26 18:05:21 +08:00
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_forearm_bone(j4, j5, half=None):
|
2026-09-28 03:33:27 +08:00
|
|
|
|
"""P07_小臂骨架_螺旋体30%_墙5底5_竖打 L型高刚度无干涉版(深度圆角优化版)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
设计要点:
|
|
|
|
|
|
1. 改为与 P05/P08 统一的 L 型结构(L-bracket):
|
|
|
|
|
|
- +Y侧垂直背脊立柱(Y: y_hub_in..y_out),避开上级大臂骨架 P06(Y <= 155.5)
|
|
|
|
|
|
- 彻底消除原全深S弯在J4轴下方向两边突出的干涉结构(两边突出的结构全部去除)
|
|
|
|
|
|
- 垂直立柱与下方 M5 电机水平座之间采用规则折角(Corner Chamfer/Gusset)刚性连接
|
|
|
|
|
|
2. 下方 M5 电机实行半包散热结构,底部与内腔开窗散热
|
|
|
|
|
|
3. J4 轴俯仰动态行程从受限的 ±54° 大幅释放至无死角大范围摆动(零干涉)
|
|
|
|
|
|
4. 满足单实体 (solids=1) 与装配零碰撞。
|
2026-09-26 18:05:21 +08:00
|
|
|
|
"""
|
2026-09-27 04:48:49 +08:00
|
|
|
|
y_out = Y_HUB + PLATE_T # 174.0
|
|
|
|
|
|
y_hub_in = HL.Y_COVER + 0.5 + CLEARANCE_GAP # 158.5
|
|
|
|
|
|
y_front = Y_COVER - 0.5 # 155.5
|
|
|
|
|
|
y_rear = Y_REAR - 8.0 # 92.0
|
2026-09-27 17:21:50 +08:00
|
|
|
|
z_top_housing = Z_WR + 39.0 # 261.0 (顶面加厚 4.0mm,消除过薄破面问题)
|
2026-09-28 01:00:04 +08:00
|
|
|
|
z_roof_top = z_top_housing + 19.0 # 280.0 (顶板整条加高 19mm,用户确认方案4)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
# 1. J5 电机前后安装环
|
2026-09-26 18:05:21 +08:00
|
|
|
|
collar_front = Ycyl(35.0, HL.Y_COVER - 6.0, HL.Y_COVER - 0.5, X_ARM, Z_WR)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
rear_plate = Ycyl(35.0, HL.Y_REAR - 8.0, HL.Y_REAR, X_ARM, Z_WR)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
s = collar_front.fuse(rear_plate)
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
# 2. J4 顶部从动法兰盘 (Y: y_hub_in..y_out, R=35mm, Z: Z_EL)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
disc = Ycyl(35.0, y_hub_in, y_out, X_ARM, Z_EL)
|
|
|
|
|
|
s = s.fuse(disc)
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
# 3. M5 电机壳体水平顶部顶板 (Z: Z_WR..z_top_housing, Y: y_rear..y_front)
|
|
|
|
|
|
roof_w = (cq.Workplane("YZ", origin=(X_ARM, 0, 0))
|
|
|
|
|
|
.moveTo(y_rear, Z_WR)
|
2026-09-28 01:00:04 +08:00
|
|
|
|
.lineTo(y_rear, z_roof_top)
|
|
|
|
|
|
.lineTo(y_front - 3.0, z_roof_top)
|
|
|
|
|
|
.threePointArc((y_front - 3.0 + 3.0 * math.cos(math.pi / 4),
|
|
|
|
|
|
z_roof_top - 3.0 + 3.0 * math.sin(math.pi / 4)),
|
|
|
|
|
|
(y_front, z_roof_top - 3.0))
|
2026-09-27 04:48:49 +08:00
|
|
|
|
.lineTo(y_front, Z_WR)
|
|
|
|
|
|
.close()
|
|
|
|
|
|
.extrude(35.0, both=True))
|
|
|
|
|
|
s = s.fuse(roof_w.val())
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
# 4. L型垂直立柱臂 (+Y侧,Y: y_hub_in..y_out,从 Z_EL 顶端延伸至下方电机座)
|
|
|
|
|
|
vert_leg = (cq.Workplane("YZ", origin=(X_ARM, 0, 0))
|
|
|
|
|
|
.moveTo(y_hub_in, z_top_housing)
|
|
|
|
|
|
.lineTo(y_out, z_top_housing)
|
|
|
|
|
|
.lineTo(y_out, Z_EL)
|
|
|
|
|
|
.lineTo(y_hub_in, Z_EL)
|
|
|
|
|
|
.close()
|
|
|
|
|
|
.extrude(35.0, both=True))
|
|
|
|
|
|
s = s.fuse(vert_leg.val())
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
# 5. L型内侧圆弧加强过渡(Circular Arc Gusset,用户要求"改成圆弧而不是折角,消掉悬空小块")
|
|
|
|
|
|
# 彻底取代直角折角与直斜线折角,采用与顶面和立柱双相切的平滑内凹大圆弧 (R=28.0mm)
|
2026-09-28 01:00:04 +08:00
|
|
|
|
# 起点在顶板平整面 (y_arc_start, z_roof_top),精确相切至立柱内侧面 (y_hub_in, z_arc_end)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
# 严控全域 Z >= z_top_housing,彻底消除侵入下方旋转副的悬空小方块与多余突起!
|
2026-09-28 01:00:04 +08:00
|
|
|
|
# 注:顶板整条加高19mm(z_roof_top=280)后,R28改R14使弧仍与顶板面光滑相切,不出现折角
|
|
|
|
|
|
R_arc = 14.0 # 随顶板加高联动重定:相切起点(144.5,280)->终点(158.5,294),避开P06环底z=297留3mm
|
2026-09-27 04:48:49 +08:00
|
|
|
|
y_arc_start = y_hub_in - R_arc
|
2026-09-28 01:00:04 +08:00
|
|
|
|
z_arc_end = z_roof_top + R_arc
|
2026-09-27 04:48:49 +08:00
|
|
|
|
p_mid_arc = (y_arc_start + R_arc * math.cos(math.pi / 4),
|
|
|
|
|
|
z_arc_end - R_arc * math.sin(math.pi / 4))
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
gusset_w = (cq.Workplane("YZ", origin=(X_ARM, 0, 0))
|
2026-09-28 01:00:04 +08:00
|
|
|
|
.moveTo(y_arc_start, z_roof_top)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
.threePointArc(p_mid_arc, (y_hub_in, z_arc_end))
|
|
|
|
|
|
.lineTo(y_out, z_arc_end)
|
|
|
|
|
|
.lineTo(y_out, z_top_housing)
|
|
|
|
|
|
.lineTo(y_arc_start, z_top_housing)
|
|
|
|
|
|
.close()
|
|
|
|
|
|
.extrude(35.0, both=True))
|
|
|
|
|
|
s = s.fuse(gusset_w.val())
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
# 6. 下级 P08 旋转圆盘动态避让切除(R=35.5mm,预留 0.5mm 间隙)
|
|
|
|
|
|
p08_clearance = Ycyl(35.5, 156.0, y_out + 2.0, X_ARM, Z_WR)
|
|
|
|
|
|
s = s.cut(p08_clearance)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
# 7. M5 电机安装接口与定子空腔
|
|
|
|
|
|
s = j5.front_collar_pocket(s, r_bore=30.25 + CLEARANCE_GAP, z0=50.0, z1=56.5)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
s = j5.rear_mount_holes(s, t_plate=8.0, hole_d=2.8, cb_d=5.5, cb_depth=4.0)
|
|
|
|
|
|
s = j5.pocket(s)
|
2026-09-27 17:21:50 +08:00
|
|
|
|
s = s.cut(Ycyl(30.5 + CLEARANCE_GAP, HL.Y_REAR - 0.5, y_front - 6.0, X_ARM, Z_WR))
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
# 半包散热设计:-Z底部电机定子通风口
|
|
|
|
|
|
vent_cut = bx(X_ARM - 40.0, X_ARM + 40.0, y_rear + 8.0, y_front - 6.0, Z_WR - 40.0, Z_WR - 25.0)
|
|
|
|
|
|
s = s.cut(vent_cut)
|
|
|
|
|
|
|
|
|
|
|
|
# 8. J4 直连法兰结构(凸台延伸至 60.0 跨过间隙与法兰盘牢固熔接,保持单实体)
|
|
|
|
|
|
boss = cyl(17.8, 54.942, 60.0)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
s = s.fuse(j4.L(boss))
|
|
|
|
|
|
s = s.cut(j4.L(cyl(3.5, 54.0, 74.0 + 30.0)))
|
|
|
|
|
|
for a in AB.HUB_M2_CLOCK:
|
|
|
|
|
|
u = AB.M["m2_bcd"] / 2.0 * math.cos(a * AB.D2R)
|
|
|
|
|
|
v = AB.M["m2_bcd"] / 2.0 * math.sin(a * AB.D2R)
|
|
|
|
|
|
th = cyl(1.4, 54.0, 58.0, u, v)
|
|
|
|
|
|
cb = cyl(2.8, 58.0, 74.0 + 40.0, u, v)
|
|
|
|
|
|
s = s.cut(j4.L(th)).cut(j4.L(cb))
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
# 9. 工艺走线通孔
|
|
|
|
|
|
slot_z = (Z_EL + z_top_housing) / 2.0
|
|
|
|
|
|
slot = Ycyl(7.0, y_hub_in - 2.0, y_out + 2.0, X_ARM, slot_z)
|
|
|
|
|
|
s = s.cut(slot)
|
|
|
|
|
|
|
|
|
|
|
|
# ========== 关键圆角优化 ==========
|
|
|
|
|
|
try:
|
2026-09-28 01:00:04 +08:00
|
|
|
|
# 后侧顶板外边缘圆角(平滑消除水平顶板与后部垂直端面交汇处的 90° 尖角,用户要求倒角改圆角)
|
2026-09-27 17:21:50 +08:00
|
|
|
|
wp_s = cq.Workplane(obj=s)
|
|
|
|
|
|
sel_rear = cq.selectors.BoxSelector(
|
2026-09-28 01:00:04 +08:00
|
|
|
|
(X_ARM - 40, y_rear - 1.0, z_roof_top - 1.0),
|
|
|
|
|
|
(X_ARM + 40, y_rear + 1.0, z_roof_top + 1.0)
|
2026-09-27 17:21:50 +08:00
|
|
|
|
)
|
2026-09-28 01:00:04 +08:00
|
|
|
|
s = wp_s.edges(sel_rear).fillet(FILLET_SMALL).val()
|
2026-09-27 17:21:50 +08:00
|
|
|
|
except Exception as e:
|
2026-09-28 01:00:04 +08:00
|
|
|
|
print(f"P07 顶板后边缘圆角异常: {e}")
|
2026-09-27 04:48:49 +08:00
|
|
|
|
|
2026-09-26 18:05:21 +08:00
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_wrist_bracket(j5, j6):
|
2026-09-28 03:33:27 +08:00
|
|
|
|
"""P08_腕偏转座_螺旋体25%_墙4底5_竖打(深度圆角优化版)"""
|
|
|
|
|
|
return make_pitch_to_roll_bracket(j5, j6, Z_WR, Z_R6, name="P08_腕偏转座_螺旋体25%_墙4底5_竖打")
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_tool_flange(j6):
|
2026-09-28 03:33:27 +08:00
|
|
|
|
"""P09_工具法兰_螺旋体100%_墙4底5_竖打 深度圆角优化版
|
2026-09-27 04:48:49 +08:00
|
|
|
|
关键改进:
|
|
|
|
|
|
1. 外轮廓全圆角(R=4mm)
|
|
|
|
|
|
2. 法兰面倒角(2mm)
|
|
|
|
|
|
3. 螺孔边缘倒角(1.5mm)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
"""
|
|
|
|
|
|
z_bot = Z_HUB6 - PLATE_T - 9.0
|
|
|
|
|
|
s = cyl(35.0, z_bot, Z_HUB6, X_ARM, Y_AXIS)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
|
|
|
|
|
|
# 4x M4螺栓孔
|
2026-09-26 18:05:21 +08:00
|
|
|
|
for a in (0, 90, 180, 270):
|
|
|
|
|
|
rad = 20.0
|
|
|
|
|
|
u = rad * math.cos(a * D2R)
|
|
|
|
|
|
v = rad * math.sin(a * D2R)
|
|
|
|
|
|
h = cyl(1.85, z_bot - 1.0, z_bot + 12.0, X_ARM + u, Y_AXIS + v)
|
|
|
|
|
|
cb = cyl(3.5, z_bot - 1.0, z_bot + 4.0, X_ARM + u, Y_AXIS + v)
|
|
|
|
|
|
s = s.cut(h).cut(cb)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
|
|
|
|
|
|
# 定位止口 + 走线孔
|
2026-09-26 18:05:21 +08:00
|
|
|
|
pilot = cyl(10.0, z_bot - 1.0, z_bot + 2.5, X_ARM, Y_AXIS)
|
|
|
|
|
|
thru = cyl(5.0, z_bot - 1.0, Z_HUB6 + 1.0, X_ARM, Y_AXIS)
|
|
|
|
|
|
s = s.cut(pilot).cut(thru)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
|
|
|
|
|
|
# 直连法兰
|
2026-09-26 18:05:21 +08:00
|
|
|
|
s = make_direct_hub(s, j6, r_disc=35.0, z_out=74.0)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
|
|
|
|
|
|
# ========== 关键圆角优化 ==========
|
|
|
|
|
|
try:
|
|
|
|
|
|
# 外轮廓圆角
|
|
|
|
|
|
s = s.edges("|Z").fillet(FILLET_SMALL)
|
|
|
|
|
|
except:
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
# 法兰面倒角
|
|
|
|
|
|
s = s.edges("<Z").chamfer(CHAMFER_EDGE)
|
|
|
|
|
|
except:
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
# 顶部边缘圆角
|
|
|
|
|
|
s = s.edges(">Z").fillet(FILLET_TINY)
|
|
|
|
|
|
except:
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
2026-09-26 18:05:21 +08:00
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------- assembly ----------------
|
|
|
|
|
|
def build():
|
2026-09-27 04:48:49 +08:00
|
|
|
|
print("=" * 80, flush=True)
|
|
|
|
|
|
print("【第一阶段 1/5】开始生成手臂各级构件 3D 几何实体模型...", flush=True)
|
|
|
|
|
|
print("=" * 80, flush=True)
|
|
|
|
|
|
t_stage1 = time.time()
|
|
|
|
|
|
|
|
|
|
|
|
print(" [0/9] 载入电机标准件模组 (STEP)...", end="", flush=True)
|
|
|
|
|
|
t0 = time.time()
|
2026-09-26 18:05:21 +08:00
|
|
|
|
motor = cq.importers.importStep(AB.SRC_STEP).val()
|
|
|
|
|
|
motor = place(motor, T(0, 0, -2.57))
|
|
|
|
|
|
AB.MOTOR, AB.HALF, AB.CLAMP = motor, None, None
|
2026-09-27 04:48:49 +08:00
|
|
|
|
print(f" 完成 ({time.time()-t0:.2f}s) ✓", flush=True)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
|
|
|
|
|
JS = {}
|
|
|
|
|
|
for tag, cn, rear, d, xd, holder, driven in HL.JOINTS:
|
|
|
|
|
|
JS[tag] = Joint(tag, cn, rear, d, xd, lug_phase=90.0 if tag == "J1" else 0.0)
|
|
|
|
|
|
j1, j2, j3, j4, j5, j6 = (JS["J%d" % k] for k in range(1, 7))
|
|
|
|
|
|
|
|
|
|
|
|
PARTS[:] = []
|
|
|
|
|
|
AB.CENTS.clear()
|
|
|
|
|
|
AB.GRP = {}
|
|
|
|
|
|
par = {"J1": "root", "J2": "J1", "J3": "J2", "J4": "J3", "J5": "J4", "J6": "J5"}
|
2026-09-28 03:33:27 +08:00
|
|
|
|
driven = {"J1": "P04_肩叉_螺旋体30%_墙5底5_竖打", "J2": "P05_大臂旋转座_螺旋体30%_墙4底5_竖打", "J3": "P06_大臂骨架_螺旋体25%_墙4底5_竖打",
|
|
|
|
|
|
"J4": "P07_小臂骨架_螺旋体30%_墙5底5_竖打", "J5": "P08_腕偏转座_螺旋体25%_墙4底5_竖打", "J6": "P09_工具法兰_螺旋体100%_墙4底5_竖打"}
|
2026-09-26 18:05:21 +08:00
|
|
|
|
motor_of = {"J1": "M1_J1", "J2": "M2_J2", "J3": "M3_J3",
|
|
|
|
|
|
"J4": "M4_J4", "J5": "M5_J5", "J6": "M6_J6"}
|
|
|
|
|
|
for t in ("J1", "J2", "J3", "J4", "J5", "J6"):
|
2026-09-27 04:48:49 +08:00
|
|
|
|
AB.GRP[motor_of[t]] = par[t]
|
2026-09-26 18:05:21 +08:00
|
|
|
|
AB.GRP[driven[t]] = t
|
2026-09-27 17:21:50 +08:00
|
|
|
|
AB.GRP.update({
|
2026-09-28 03:33:27 +08:00
|
|
|
|
"P01_A_立柱下段_三角形30%_墙4底5_竖打": "root", "P01_B_立柱中段_三角形30%_墙4底5_竖打": "root", "P01_C_立柱上段_三角形30%_墙4底5_竖打": "root",
|
|
|
|
|
|
"P02_Center_底座中核心_螺旋体30%_墙5底6_平打": "root", "P02_Front_前向防翻力臂_螺旋体30%_墙4底5_平打": "root", "P02_Rear_后向防翻力臂_螺旋体30%_墙4底5_平打": "root",
|
|
|
|
|
|
"P03_肩吊臂_螺旋体35%_墙5底5_竖打": "root"
|
2026-09-27 17:21:50 +08:00
|
|
|
|
})
|
2026-09-26 18:05:21 +08:00
|
|
|
|
AB.JAW = {}
|
|
|
|
|
|
|
2026-09-27 17:21:50 +08:00
|
|
|
|
p01_full = p_chest()
|
|
|
|
|
|
p01_a, p01_b, p01_c = split_p01_poka_yoke(p01_full)
|
|
|
|
|
|
p02_c, p02_f, p02_r = make_p02_poka_yoke()
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
parts_to_build = [
|
2026-09-28 03:33:27 +08:00
|
|
|
|
("P01_A_立柱下段_三角形30%_墙4底5_竖打", "立柱下段", lambda: p01_a, 0x0284c7,
|
2026-10-02 04:39:12 +08:00
|
|
|
|
"200mm适配分段A:高166mm+16mm阶梯公榫+顶端 2x Ø3.9 对锁孔(M4x16 自攻)+底部50x50x12榫头+P01-A 竖排TOP刻字"),
|
2026-09-28 03:33:27 +08:00
|
|
|
|
("P01_B_立柱中段_三角形30%_墙4底5_竖打", "立柱中段", lambda: p01_b, 0x2563eb,
|
2026-10-02 04:39:12 +08:00
|
|
|
|
"200mm适配分段B:高165mm+双端公母榫+两端各 2x Ø3.9 对锁孔(M4x16 自攻,非对称孔位防反装)+P01-B 竖排TOP刻字"),
|
2026-09-28 03:33:27 +08:00
|
|
|
|
("P01_C_立柱上段_三角形30%_墙4底5_竖打", "立柱上段", lambda: p01_c, 0x1d4ed8,
|
2026-10-02 04:39:12 +08:00
|
|
|
|
"200mm适配分段C:高149mm+底端母榫+底端 2x Ø3.9 对锁孔(非对称孔位防反装)+顶面P03安装台(4x Ø3.9 安装孔 + 1x Ø3.9 横向锁紧孔)+P01-C 竖排TOP刻字"),
|
2026-09-28 03:33:27 +08:00
|
|
|
|
("P02_Center_底座中核心_螺旋体30%_墙5底6_平打", "底座核心承力座", lambda: p02_c, 0x475569,
|
2026-09-27 21:08:28 +08:00
|
|
|
|
"200mm适配中座:195x190mm核心承力座+48mm套筒+12mm阶梯榫座(轴向面承载)+前后三角加强筋+前后非对称防呆母榫槽+刻字"),
|
2026-09-28 03:33:27 +08:00
|
|
|
|
("P02_Front_前向防翻力臂_螺旋体30%_墙4底5_平打", "前向防翻力臂", lambda: p02_f, 0xe11d48,
|
2026-09-27 17:21:50 +08:00
|
|
|
|
"200mm适配前臂:145x190mm扩展力臂+104mm宽跨距双公榫+底部M5预埋螺母沉槽+P02-FRONT刻字"),
|
2026-09-28 03:33:27 +08:00
|
|
|
|
("P02_Rear_后向防翻力臂_螺旋体30%_墙4底5_平打", "后向防翻力臂", lambda: p02_r, 0xd97706,
|
2026-09-27 17:21:50 +08:00
|
|
|
|
"200mm适配后臂:45x190mm扩展力臂+80mm窄跨距双公榫+底部M5预埋螺母沉槽+P02-REAR刻字"),
|
2026-09-28 03:33:27 +08:00
|
|
|
|
("P03_肩吊臂_螺旋体35%_墙5底5_竖打", "肩关节安装悬臂", lambda: p_girdle(j1), 0x4b5563,
|
2026-10-02 04:39:12 +08:00
|
|
|
|
"轻量化板式桁架版:主干由 66mm 实心块改为双侧 6mm 桁架竖板+帐篷减重窗(斜面≥52°自支撑)+R4内角,外轮廓与旧版并集完全一致,实心 728->286cm³;底部 9mm 承力鞍座(Ø3.9 安装孔)+12mm 中位龙骨筋(自鞍座斜拉至法兰下缘)+40~45°外扩斜撑;保留 10mm 后置法兰、侧开式电机托架、Ø60.7 直通电机舱(平孔无台阶)(M1 从+Y滑入,后端 4xM3x16 锁死)、大散热窗与对流槽;无封闭空腔、免支撑"),
|
2026-09-28 03:33:27 +08:00
|
|
|
|
("P04_肩叉_螺旋体30%_墙5底5_竖打", "肩叉", lambda: p_fork(j1, j2), 0x2563eb,
|
2026-10-02 12:06:23 +08:00
|
|
|
|
"齐平插槽+ M2 前端压盖版:叉板背面与P03托架端面(11.5)0.0硬贴平(用户要求外观齐平),P03侧插槽独立加长3mm,M1电机可倾斜卡入,J1输出凸台贯通直连电机,J1从动法兰圆盘鼓楞已删(接缝区与P03止脱环齐径齐高R36.5/顶646.5),单实体全角度零干涉;【2026-10-02 新增】M2 前端压盖(R35, Y155.5..161.0):电机前端盖外端面加 4xM3x8 沉孔(BCD55)夹紧,与后端安装板 4xM3x10 形成前后双向面压,消除大扭矩下电机在座孔里的倾斜"),
|
2026-09-28 03:33:27 +08:00
|
|
|
|
("P05_大臂旋转座_螺旋体30%_墙4底5_竖打", "大臂旋转座", lambda: p_shoulder_roll_base(j2, j3, None), 0x059669,
|
2026-10-02 12:06:23 +08:00
|
|
|
|
"V3圆角+ J2前端夹紧配合:Loft外轮廓R=10mm,L型转角内部2mm倒角,后缘凸包两角90°竖棱磨R2圆角(结构/后缘高度不变,打印无悬挂);J2 从动法兰盘背面由 Y=157 后移至 Y=162(hub_gap=6.0,给 P04 新增的 M2 前端压盖让位,J2 直锁凸台同步加长到 Y=165.5,3xS01 输出螺钉咬合量不变);保证 J2 全角度 0 干涉"),
|
2026-09-28 03:33:27 +08:00
|
|
|
|
("P06_大臂骨架_螺旋体25%_墙4底5_竖打", "大臂骨架", lambda: p_humerus_bone(j3, j4), 0x0d9488,
|
2026-09-27 05:02:34 +08:00
|
|
|
|
"Loft有机过渡版:借鉴P05圆弧变方形放样算法,顶端Ø70正圆与J3平齐无台阶,底端渐变融入M4抱紧套筒与壳体,单实体0干涉"),
|
2026-09-28 03:33:27 +08:00
|
|
|
|
("P07_小臂骨架_螺旋体30%_墙5底5_竖打", "小臂骨架", lambda: p_forearm_bone(j4, j5, None), 0x7c3aed,
|
2026-09-28 01:00:04 +08:00
|
|
|
|
"V2 L型结构:+Y侧背脊立柱避让大臂骨架,过渡区采用与顶板和立柱双相切的R=28mm平滑内凹大圆弧,彻底消除直斜线折角与悬空阶梯小块,顶板前后外缘2mm倒角改R3圆角,顶板整条加高19mm(z261->280)加强连接且gusset弧R28->R14重定相切融入,J4圆盘外沿与立柱外棱不倒圆保持原始尖角,下方M5电机半包散热,俯仰大范围自由运动零干涉"),
|
2026-09-28 03:33:27 +08:00
|
|
|
|
("P08_腕偏转座_螺旋体25%_墙4底5_竖打", "腕部转接座", lambda: p_wrist_bracket(j5, j6), 0xd97706,
|
2026-09-27 04:48:49 +08:00
|
|
|
|
"V2圆角:Loft外轮廓R=10mm,L型转角内部2mm倒角,彻底清除立壁保证J5全角度0干涉"),
|
2026-09-28 03:33:27 +08:00
|
|
|
|
("P09_工具法兰_螺旋体100%_墙4底5_竖打", "末端工具法兰", lambda: p_tool_flange(j6), 0xdc2626,
|
2026-09-27 04:48:49 +08:00
|
|
|
|
"V2圆角:外轮廓R=3mm,法兰面倒角2mm"),
|
|
|
|
|
|
]
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 17:21:50 +08:00
|
|
|
|
total_parts = len(parts_to_build)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
for idx, (name, cn, fn, color, note) in enumerate(parts_to_build, 1):
|
2026-09-27 17:21:50 +08:00
|
|
|
|
print(f" [{idx}/{total_parts}] 正在构建 {name} ({cn})...", end="", flush=True)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
t0 = time.time()
|
|
|
|
|
|
sh = fn()
|
|
|
|
|
|
dt = time.time() - t0
|
|
|
|
|
|
vol = AB.vol_of(sh) / 1000.0
|
|
|
|
|
|
n_solids = len(solids_of(sh))
|
|
|
|
|
|
print(f" 完成 ✓ ({dt:.2f}s | 体积: {vol:.1f} cm³ | 实体数: {n_solids})", flush=True)
|
|
|
|
|
|
add(name, cn, sh, color, note=note)
|
|
|
|
|
|
|
|
|
|
|
|
print(" [装配] 正在将 M1~M6 电机定位至各关节坐标位姿...", end="", flush=True)
|
|
|
|
|
|
t0 = time.time()
|
2026-09-26 18:05:21 +08:00
|
|
|
|
for k, (tag, cn, rear, d, xd, holder, driven_name) in enumerate(HL.JOINTS):
|
|
|
|
|
|
j = JS[tag]
|
|
|
|
|
|
add("M%d_%s" % (k + 1, tag), "%s 电机模组" % tag, place(motor, j.t), 0x9ca3af,
|
|
|
|
|
|
printed=False, note="复用 电机.STEP")
|
2026-09-27 04:48:49 +08:00
|
|
|
|
print(f" 完成 ✓ ({time.time()-t0:.2f}s)", flush=True)
|
|
|
|
|
|
print(f"-> 构件模型全部生成完成,总耗时: {time.time()-t_stage1:.2f}s\n", flush=True)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
return JS
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CHAIN = ["root", "J1", "J2", "J3", "J4", "J5", "J6"]
|
2026-09-27 04:48:49 +08:00
|
|
|
|
SEP = 74.0
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def explode_chain(p, JS, cents, gmean):
|
2026-09-27 17:21:50 +08:00
|
|
|
|
"""爆炸图偏移:立柱垂直阶梯拉开,底座前后防呆拉开,电机沿轴拉出,机械臂整体随上段分离"""
|
|
|
|
|
|
nm = p["name"]
|
2026-09-28 03:33:27 +08:00
|
|
|
|
if nm == "P01_A_立柱下段_三角形30%_墙4底5_竖打":
|
2026-09-27 17:21:50 +08:00
|
|
|
|
return [0.0, 0.0, 0.0]
|
2026-09-28 03:33:27 +08:00
|
|
|
|
if nm == "P01_B_立柱中段_三角形30%_墙4底5_竖打":
|
2026-09-27 17:21:50 +08:00
|
|
|
|
return [0.0, 0.0, 60.0]
|
2026-09-28 03:33:27 +08:00
|
|
|
|
if nm == "P01_C_立柱上段_三角形30%_墙4底5_竖打":
|
2026-09-27 17:21:50 +08:00
|
|
|
|
return [0.0, 0.0, 120.0]
|
2026-09-28 03:33:27 +08:00
|
|
|
|
if nm == "P02_Center_底座中核心_螺旋体30%_墙5底6_平打":
|
2026-09-27 17:21:50 +08:00
|
|
|
|
return [0.0, 0.0, 0.0]
|
2026-09-28 03:33:27 +08:00
|
|
|
|
if nm == "P02_Front_前向防翻力臂_螺旋体30%_墙4底5_平打":
|
2026-09-27 17:21:50 +08:00
|
|
|
|
return [65.0, 0.0, 0.0]
|
2026-09-28 03:33:27 +08:00
|
|
|
|
if nm == "P02_Rear_后向防翻力臂_螺旋体30%_墙4底5_平打":
|
2026-09-27 17:21:50 +08:00
|
|
|
|
return [-65.0, 0.0, 0.0]
|
2026-09-28 03:33:27 +08:00
|
|
|
|
if nm == "P03_肩吊臂_螺旋体35%_墙5底5_竖打":
|
2026-09-27 17:21:50 +08:00
|
|
|
|
return [0.0, 0.0, 120.0]
|
|
|
|
|
|
|
2026-09-26 18:05:21 +08:00
|
|
|
|
grp = AB.GRP.get(p["name"], "root")
|
|
|
|
|
|
if grp == "root":
|
|
|
|
|
|
return [0.0, 0.0, 0.0]
|
|
|
|
|
|
k = CHAIN.index(grp)
|
2026-09-27 17:21:50 +08:00
|
|
|
|
off = [0.0, 0.0, 120.0 - SEP * k]
|
2026-09-26 18:05:21 +08:00
|
|
|
|
j = JS.get(grp)
|
|
|
|
|
|
if j:
|
|
|
|
|
|
w = 0.0
|
|
|
|
|
|
if "半联轴器" in nm or "抱箍" in nm:
|
|
|
|
|
|
w = 34.0 * (1.0 if ("A" in nm[-1:]) else -1.0)
|
|
|
|
|
|
elif nm.startswith("M"):
|
|
|
|
|
|
w = 62.0
|
|
|
|
|
|
for q in range(3):
|
|
|
|
|
|
off[q] += j.d[q] * w
|
|
|
|
|
|
return off
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
|
JS = build()
|
2026-09-27 04:48:49 +08:00
|
|
|
|
|
|
|
|
|
|
print("=" * 80, flush=True)
|
|
|
|
|
|
print("【单实体拓扑完整性校验】验证所有打印构件流形实体状态...", flush=True)
|
|
|
|
|
|
print("=" * 80, flush=True)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
bad = 0
|
2026-09-27 04:48:49 +08:00
|
|
|
|
printed_list = [p for p in PARTS if p["printed"]]
|
2026-09-27 17:21:50 +08:00
|
|
|
|
total_pr = len(printed_list)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
for idx, p in enumerate(printed_list, 1):
|
2026-09-26 18:05:21 +08:00
|
|
|
|
n = len(solids_of(p["shape"]))
|
|
|
|
|
|
if n != 1:
|
|
|
|
|
|
bad += 1
|
2026-09-27 04:48:49 +08:00
|
|
|
|
status = "单实体 ✓" if n == 1 else f"异常 ({n} 个实体) ❌"
|
2026-09-27 17:21:50 +08:00
|
|
|
|
print(f" [{idx}/{total_pr}] {p['name']:<14} : 体积 {p['vol']/1000.0:6.1f} cm³ | {status}", flush=True)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
if bad == 0:
|
2026-09-27 17:21:50 +08:00
|
|
|
|
print(f"-> 单实体检查全部通过!{total_pr}/{total_pr} 构件均为完美单一流形拓扑 ✓\n", flush=True)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
else:
|
|
|
|
|
|
print(f"-> 发现 {bad} 个非单实体构件!\n", flush=True)
|
|
|
|
|
|
|
2026-09-26 18:05:21 +08:00
|
|
|
|
AB.explode_vec = explode_chain
|
|
|
|
|
|
bom = AB.export(JS)
|
2026-09-28 03:33:27 +08:00
|
|
|
|
|
|
|
|
|
|
# 紧固件(螺钉)实例注入:把 docs/screws.json 的 72 颗螺钉按真实孔位还原成三维实例,
|
|
|
|
|
|
# 追加进 web/mesh_arm.json 的 parts(查看器可点 BOM 螺丝行高亮定位;纯数据,不动 CAD)
|
|
|
|
|
|
try:
|
|
|
|
|
|
import screw_mesh
|
|
|
|
|
|
screw_mesh.main()
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print("螺钉实例注入失败(不影响主流程,可手动跑 src/screw_mesh.py):", e, flush=True)
|
|
|
|
|
|
|
2026-09-26 18:05:21 +08:00
|
|
|
|
cl = AB.collide()
|
2026-09-27 04:48:49 +08:00
|
|
|
|
|
2026-09-27 00:28:49 +08:00
|
|
|
|
try:
|
|
|
|
|
|
from build_viewer import rebuild_viewer
|
|
|
|
|
|
rebuild_viewer()
|
|
|
|
|
|
except Exception as e:
|
2026-09-27 04:48:49 +08:00
|
|
|
|
print("rebuild_viewer error:", e, flush=True)
|
|
|
|
|
|
|
2026-09-28 03:33:27 +08:00
|
|
|
|
# 可达包络自动注入:AB.export 刚重写过 mesh_arm.json(包络件会被冲掉),
|
|
|
|
|
|
# 这里重跑 FK 采样 + 包络网格注入,再重打包一次查看器(约 3~4s,纯数据无 CAD 计算)
|
|
|
|
|
|
try:
|
|
|
|
|
|
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
|
|
|
|
|
"..", "scratch"))
|
|
|
|
|
|
import ws_sweep
|
|
|
|
|
|
import gen_env_mesh
|
|
|
|
|
|
t_env = time.time()
|
|
|
|
|
|
ws_sweep.main()
|
|
|
|
|
|
gen_env_mesh.main()
|
|
|
|
|
|
from build_viewer import rebuild_viewer as _rbv
|
|
|
|
|
|
_rbv()
|
|
|
|
|
|
print(f"-> 可达包络已自动注入查看器(+{time.time()-t_env:.1f}s)✓\n", flush=True)
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print("可达包络自动注入失败(不影响主流程,修复后手动跑 scratch/gen_env_mesh.py + src/build_viewer.py):",
|
|
|
|
|
|
e, flush=True)
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
print("=" * 80, flush=True)
|
|
|
|
|
|
print("✅ 机器人手臂编译、导出与查看器发布全流程完成!", flush=True)
|
|
|
|
|
|
print("=" * 80, flush=True)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
sys.stdout.flush()
|
2026-09-26 18:05:21 +08:00
|
|
|
|
os._exit(0)
|