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,
|
|
|
|
|
|
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-09-26 18:05:21 +08:00
|
|
|
|
def p_chest():
|
2026-09-27 04:48:49 +08:00
|
|
|
|
"""P01_胸腔支撑立柱 (High-Rigidity Box Mast Tower - 后置台架立柱):
|
|
|
|
|
|
1. 66x66mm 封闭中空厚壁箱型柱(壁厚 8mm),中心在 (-115.0, 128.0),位于手臂正后方;
|
2026-09-27 00:28:49 +08:00
|
|
|
|
2. 顶部接收 P03 48x48x15mm 榫头插槽与 4x M5 安装螺栓;
|
|
|
|
|
|
3. 底部插入 P02 沉槽(深度 12mm),剪切力由槽壁全周承载;
|
|
|
|
|
|
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 00:28:49 +08:00
|
|
|
|
.rect(50.0, 50.0)
|
|
|
|
|
|
.extrude(z_top - z_bot + 1.0)
|
|
|
|
|
|
.edges("|Z").fillet(4.0)).val()
|
|
|
|
|
|
s = s.cut(cav)
|
|
|
|
|
|
|
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 00:28:49 +08:00
|
|
|
|
s = s.cut(cyl(2.75, z_bot - 0.01, z_bot + 15.0, xx, yy))
|
|
|
|
|
|
s = s.cut(cyl(2.75, z_top - 20.0, z_top + 0.01, xx, yy))
|
|
|
|
|
|
|
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 00:28:49 +08:00
|
|
|
|
def split_p01_stack(p01):
|
|
|
|
|
|
"""将 P01 拆分为适合 250mm 桌面 3D 打印机的两段(P01_A 与 P01_B),带 16mm 阶梯互锁榫卯"""
|
|
|
|
|
|
z_split = 246.0
|
|
|
|
|
|
h_lap = 16.0
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
cut_b = bx(X_COL - 45.0, X_COL + 45.0, Y_COL - 45.0, Y_COL + 45.0, z_split, 500.0)
|
|
|
|
|
|
tongue_outer = (cq.Workplane("XY", origin=(X_COL, Y_COL, z_split))
|
2026-09-27 00:28:49 +08:00
|
|
|
|
.rect(64.8, 64.8)
|
|
|
|
|
|
.extrude(h_lap)
|
|
|
|
|
|
.edges("|Z").fillet(5.5)).val()
|
2026-09-27 04:48:49 +08:00
|
|
|
|
tongue_cav = (cq.Workplane("XY", origin=(X_COL, Y_COL, z_split - 1.0))
|
2026-09-27 00:28:49 +08:00
|
|
|
|
.rect(51.0, 51.0)
|
|
|
|
|
|
.extrude(h_lap + 2.0)).val()
|
|
|
|
|
|
tongue = cq.Shape(tongue_outer.wrapped).cut(tongue_cav)
|
|
|
|
|
|
|
|
|
|
|
|
p01_a = p01.cut(cut_b).fuse(tongue)
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
cut_a = bx(X_COL - 45.0, X_COL + 45.0, Y_COL - 45.0, Y_COL + 45.0, 0.0, z_split)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
p01_b = p01.cut(cut_a)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
pocket = (cq.Workplane("XY", origin=(X_COL, Y_COL, z_split - 0.1))
|
2026-09-27 00:28:49 +08:00
|
|
|
|
.rect(65.6, 65.6)
|
|
|
|
|
|
.extrude(h_lap + 0.5)
|
|
|
|
|
|
.edges("|Z").fillet(6.0)).val()
|
|
|
|
|
|
p01_b = p01_b.cut(pocket)
|
|
|
|
|
|
|
|
|
|
|
|
z_bolt = z_split + h_lap / 2.0
|
2026-09-27 04:48:49 +08:00
|
|
|
|
for xx in (X_COL - 19.0, X_COL + 19.0):
|
|
|
|
|
|
y_bolt = Ycyl(2.2, Y_COL - 38.0, Y_COL + 38.0, xx, z_bolt)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
p01_a = p01_a.cut(y_bolt)
|
|
|
|
|
|
p01_b = p01_b.cut(y_bolt)
|
|
|
|
|
|
|
|
|
|
|
|
return p01_a, p01_b
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-09-26 18:05:21 +08:00
|
|
|
|
def p_base_foot():
|
2026-09-27 04:48:49 +08:00
|
|
|
|
"""P02_测试台架底座 (后置防倾翻大底盘):
|
|
|
|
|
|
1. 260x220x22mm 重型防倾翻大底盘,中心在 (-55.0, 128.0);
|
|
|
|
|
|
2. 立柱安装沉槽设在 (-115.0, 128.0),深度 12mm;
|
|
|
|
|
|
3. 四个边角各设有一组 28x7mm 的 M6 夹持腰槽;
|
|
|
|
|
|
4. 底部隐蔽走线通槽;
|
|
|
|
|
|
5. 四周棱角全部采用 R=16mm 大圆角过渡与 2.5mm 上边缘倒角。
|
2026-09-27 00:28:49 +08:00
|
|
|
|
"""
|
|
|
|
|
|
z0 = 0.0
|
|
|
|
|
|
z1 = 22.0
|
2026-09-27 04:48:49 +08:00
|
|
|
|
base_plate = (cq.Workplane("XY", origin=(-55.0, Y_COL, z0))
|
|
|
|
|
|
.rect(260.0, 220.0)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
.extrude(z1)
|
|
|
|
|
|
.edges("|Z").fillet(16.0)
|
|
|
|
|
|
.edges(">Z").fillet(2.5)).val()
|
|
|
|
|
|
s = cq.Shape(base_plate.wrapped)
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
socket_box = (cq.Workplane("XY", origin=(X_COL, Y_COL, z1 - 12.0))
|
2026-09-27 00:28:49 +08:00
|
|
|
|
.rect(67.0, 67.0)
|
|
|
|
|
|
.extrude(13.0)
|
|
|
|
|
|
.edges("|Z").fillet(6.5)).val()
|
|
|
|
|
|
s = s.cut(socket_box)
|
|
|
|
|
|
|
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 00:28:49 +08:00
|
|
|
|
th = cyl(2.75, -0.01, z1 - 11.0, xx, yy)
|
|
|
|
|
|
cb = cyl(5.0, -0.01, 6.0, xx, yy)
|
|
|
|
|
|
s = s.cut(th).cut(cb)
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
for cx in (-160.0, 50.0):
|
|
|
|
|
|
for cy in (Y_COL - 75.0, Y_COL + 75.0):
|
2026-09-27 00:28:49 +08:00
|
|
|
|
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)
|
|
|
|
|
|
|
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-09-27 04:48:49 +08:00
|
|
|
|
"""P03_肩关节安装悬臂 (高强受力多筋桁架 + 前向电机镂空散热托架):
|
|
|
|
|
|
1. 10mm 后端重载法兰盘 (X: -61.0..-51.0, 74x74mm);
|
|
|
|
|
|
2. 双侧大截面三角加强筋 (8mm 厚,Y = Y_ARM ± 28mm);
|
|
|
|
|
|
3. 下腹部纵向大受力龙骨筋 (12mm 厚);
|
|
|
|
|
|
4. 顶部横向锁紧环抱筋 (60x10x10mm);
|
|
|
|
|
|
5. 前向电机包覆托架 (X: -51.0..2.0, 托长 53mm,内径 Ø60.7mm),彻底消除后置小螺钉拉脱应力;
|
|
|
|
|
|
6. 两侧大面积散热舷窗 (34x20mm) + 顶部双斜向对流排热槽 (30x6.5mm);
|
|
|
|
|
|
7. 4x 直通式螺丝刀安装通道 (Ø8.5mm) 与 Ø26mm 中央走线孔。
|
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-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
# 1. 主安装法兰盘 (74x74mm, 倒圆角 R=8mm)
|
|
|
|
|
|
flange = (cq.Workplane("YZ", origin=(X_BACK, Y_ARM, Z_ARM))
|
|
|
|
|
|
.rect(74.0, 74.0)
|
|
|
|
|
|
.extrude(T_FLANGE)
|
|
|
|
|
|
.edges("|X").fillet(8.0)
|
|
|
|
|
|
.edges("<X").chamfer(2.0)).val()
|
|
|
|
|
|
s = cq.Shape(flange.wrapped)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
# 2. 斜挑支撑主干 (Central Arch Backbone)
|
|
|
|
|
|
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),
|
|
|
|
|
|
(X_COL - 10.0, 580.0),
|
|
|
|
|
|
(X_COL - 33.0, 550.0),
|
2026-09-26 18:05:21 +08:00
|
|
|
|
]
|
2026-09-27 04:48:49 +08:00
|
|
|
|
trunk = (cq.Workplane("XZ", origin=(0, Y_ARM, 0))
|
|
|
|
|
|
.polyline(trunk_pts).close()
|
|
|
|
|
|
.extrude(33.0, both=True)).val()
|
|
|
|
|
|
s = s.fuse(cq.Shape(trunk.wrapped))
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
# 3. 左右两侧主抗弯抗扭大三角加强筋 (厚度 8mm)
|
|
|
|
|
|
for sign in (-1, 1):
|
|
|
|
|
|
y_rib = Y_ARM + sign * 28.0
|
|
|
|
|
|
rib_pts = [
|
|
|
|
|
|
(X_COL - 30.0, Z_CHEST1),
|
|
|
|
|
|
(X_COL + 30.0, Z_CHEST1),
|
|
|
|
|
|
(X_BACK + 0.1, 565.0),
|
|
|
|
|
|
(X_BACK + 0.1, Z_ARM + 32.0),
|
|
|
|
|
|
(X_BACK - 15.0, Z_ARM + 32.0),
|
|
|
|
|
|
(X_COL - 15.0, 575.0),
|
|
|
|
|
|
(X_COL - 30.0, 530.0),
|
|
|
|
|
|
]
|
|
|
|
|
|
side_rib = (cq.Workplane("XZ", origin=(0, y_rib, 0))
|
|
|
|
|
|
.polyline(rib_pts).close()
|
|
|
|
|
|
.extrude(5.0, both=True)).val()
|
|
|
|
|
|
s = s.fuse(cq.Shape(side_rib.wrapped))
|
|
|
|
|
|
|
|
|
|
|
|
# 4. 下腹部纵向抗弯龙骨筋 (厚度 12mm)
|
|
|
|
|
|
keel_pts = [
|
|
|
|
|
|
(X_COL + 33.0, Z_CHEST1),
|
|
|
|
|
|
(X_COL + 33.0, 495.0),
|
|
|
|
|
|
(X_BACK + 0.1, 570.0),
|
|
|
|
|
|
(X_BACK + 0.1, 555.0),
|
|
|
|
|
|
(X_COL + 20.0, 480.0),
|
|
|
|
|
|
(X_COL + 20.0, Z_CHEST1),
|
|
|
|
|
|
]
|
|
|
|
|
|
keel = (cq.Workplane("XZ", origin=(0, Y_ARM, 0))
|
|
|
|
|
|
.polyline(keel_pts).close()
|
|
|
|
|
|
.extrude(12.0, both=True)).val()
|
|
|
|
|
|
s = s.fuse(cq.Shape(keel.wrapped))
|
|
|
|
|
|
|
|
|
|
|
|
# 5. 顶部横向锁紧环抱横筋
|
|
|
|
|
|
tie_rib = (cq.Workplane("YZ", origin=(X_BACK - 10.0, Y_ARM, Z_ARM + 28.0))
|
|
|
|
|
|
.rect(60.0, 10.0)
|
|
|
|
|
|
.extrude(10.0)
|
|
|
|
|
|
.edges("|X").fillet(3.0)).val()
|
|
|
|
|
|
s = s.fuse(cq.Shape(tie_rib.wrapped))
|
|
|
|
|
|
|
|
|
|
|
|
# 与立柱顶部配合的榫头 (48x48x15mm)
|
|
|
|
|
|
boss = (cq.Workplane("XY", origin=(X_COL, Y_COL, Z_CHEST1 - 15.0))
|
2026-09-27 00:28:49 +08:00
|
|
|
|
.rect(48.0, 48.0)
|
|
|
|
|
|
.extrude(15.0)
|
|
|
|
|
|
.edges("|Z").fillet(4.0)).val()
|
|
|
|
|
|
s = s.fuse(cq.Shape(boss.wrapped))
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
# 4x M5 连接螺栓孔
|
|
|
|
|
|
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 00:28:49 +08:00
|
|
|
|
s = s.cut(cyl(2.75, Z_CHEST1 - 16.0, Z_CHEST1 + 25.0, xx, yy))
|
2026-09-27 04:48:49 +08:00
|
|
|
|
|
|
|
|
|
|
# 4x M3 连接螺孔与直通螺丝刀通道
|
|
|
|
|
|
for dy in (-17.55, 17.55):
|
|
|
|
|
|
for dz in (-20.46, 20.46):
|
|
|
|
|
|
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)
|
|
|
|
|
|
access_tunnel = Xcyl(4.25, X_COL - 40.0, X_BACK + 0.1, py, pz)
|
|
|
|
|
|
s = s.cut(th).cut(cb).cut(access_tunnel)
|
|
|
|
|
|
|
|
|
|
|
|
# 中央走线孔 (Ø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-09-27 04:48:49 +08:00
|
|
|
|
# 6. 前向电机包覆托架与散热骨架 (X: -51.0..2.0)
|
|
|
|
|
|
X_FRONT = 2.0
|
|
|
|
|
|
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))
|
|
|
|
|
|
|
|
|
|
|
|
# 电机滑配安装内腔
|
|
|
|
|
|
motor_pocket = Xcyl(R_BORE, X_MOUNT - 0.2, X_FRONT + 0.5, Y_ARM, Z_ARM)
|
|
|
|
|
|
s = s.cut(motor_pocket)
|
|
|
|
|
|
|
|
|
|
|
|
# 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-27 04:48:49 +08:00
|
|
|
|
# 8. 前端径向 M3 止退/紧定孔
|
|
|
|
|
|
for deg in (60, 120):
|
|
|
|
|
|
rad = math.radians(deg)
|
|
|
|
|
|
lock_hole = cq.Plane(
|
|
|
|
|
|
origin=(-2.0, Y_ARM + 33.0 * math.cos(rad), Z_ARM + 33.0 * math.sin(rad)),
|
|
|
|
|
|
xDir=(1, 0, 0),
|
|
|
|
|
|
normal=(0, math.cos(rad), math.sin(rad))
|
2026-09-27 00:28:49 +08:00
|
|
|
|
)
|
2026-09-27 04:48:49 +08:00
|
|
|
|
lh = cq.Workplane(lock_hole).circle(1.4).extrude(15.0, both=True).val()
|
|
|
|
|
|
s = s.cut(lh)
|
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-27 04:48:49 +08:00
|
|
|
|
"""P04_肩叉 (Shoulder Fork / L-Bracket) - 大扭矩强化版:
|
|
|
|
|
|
1. 恢复并加固 M2 前端定位环 (front_collar, Y: 150..155.5, R=35mm),电机不再裸露;
|
|
|
|
|
|
2. 彻底抹平 J1 从动盘与立柱之间 26mm 生硬阶梯,顶部连续齐平于 Z = Z_RL + 38 = 648.0mm,以大圆角自然顺滑过渡;
|
|
|
|
|
|
3. 外侧一体化强化背脊加固 (Backbone Bridge),消除突兀薄片蓝条,大幅提升抗弯抗扭刚度;
|
|
|
|
|
|
4. 严格满足 single-solid 流形拓扑与 0 干涉 (COLLISION pairs = 0)。
|
2026-09-26 18:05:21 +08:00
|
|
|
|
"""
|
|
|
|
|
|
x0 = X_J1_HUB # 14.0
|
|
|
|
|
|
|
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 00:28:49 +08:00
|
|
|
|
# 2. M2 前端定位环 (Y: 149.5..155.5, R=35mm) - 恢复并加固蓝色的环!
|
|
|
|
|
|
front_collar = Ycyl(35.0, Y_COVER - 6.5, Y_COVER - 0.5, X_ARM, Z_SH)
|
|
|
|
|
|
s = rear_plate.fuse(front_collar)
|
|
|
|
|
|
|
|
|
|
|
|
# 3. J1 从动法兰盘 (X: 5.5..23.0, R=38mm)
|
|
|
|
|
|
disc_j1 = Xcyl(38.0, 5.5, 23.0, Y_AXIS, Z_RL)
|
|
|
|
|
|
s = s.fuse(disc_j1)
|
|
|
|
|
|
|
|
|
|
|
|
# 4. XZ 平面有机连续流线轮廓(加固并彻底抹平顶部 26mm 生硬阶梯):
|
|
|
|
|
|
# 顶部:自 (5.5, 648.0) 保持与 J1 从动盘同高延伸至 (23.0, 648.0),完全抹平阶梯!
|
|
|
|
|
|
# 右侧:自 (23.0, 648.0) 以 R=18mm 顺滑倒角过渡到 (39.0, 630.0),再以 R=111.56mm 切线大圆弧顺接下方 (53.5, 490.0)
|
|
|
|
|
|
# 左侧:维持 Hermite C1 切线连续自然过渡
|
|
|
|
|
|
dx_flare = 53.5 - 39.0
|
|
|
|
|
|
dz_flare = 545.0 - 490.0
|
|
|
|
|
|
R_flare = (dx_flare**2 + dz_flare**2) / (2.0 * dx_flare) # 111.56 mm
|
|
|
|
|
|
|
2026-09-26 18:05:21 +08:00
|
|
|
|
x_b, z_b = -12.65, 506.0
|
|
|
|
|
|
x_a, z_a = 5.5, 545.0
|
|
|
|
|
|
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))
|
|
|
|
|
|
|
|
|
|
|
|
xz_wire = (cq.Workplane("XZ", origin=(0, Y_AXIS, 0))
|
|
|
|
|
|
.moveTo(5.5, 545.0)
|
2026-09-27 00:28:49 +08:00
|
|
|
|
.lineTo(5.5, Z_RL + 38.0) # 648.0: 与 J1 圆盘顶部平齐共顶!
|
|
|
|
|
|
.lineTo(23.0, Z_RL + 38.0) # 抹平 X=23 处的 26mm 巨型台阶!
|
|
|
|
|
|
.radiusArc((39.0, 630.0), 18.0) # 自然圆角顺滑过渡到外侧肩部
|
2026-09-26 18:05:21 +08:00
|
|
|
|
.lineTo(39.0, 545.0)
|
|
|
|
|
|
.radiusArc((53.5, 490.0), -R_flare)
|
|
|
|
|
|
.lineTo(18.5, 490.0)
|
|
|
|
|
|
.lineTo(-16.5, 490.0)
|
|
|
|
|
|
.threePointArc((-15.1, 498.5), (-12.65, 506.0)))
|
|
|
|
|
|
for pt in hermite_pts[1:]:
|
|
|
|
|
|
xz_wire = xz_wire.lineTo(pt[0], pt[1])
|
|
|
|
|
|
xz_wire = xz_wire.close()
|
|
|
|
|
|
xz_solid = xz_wire.extrude(100.0, both=True).val()
|
|
|
|
|
|
xz_shape = cq.Shape(xz_solid.wrapped)
|
|
|
|
|
|
|
2026-09-27 00:28:49 +08:00
|
|
|
|
# YZ 平面包络:
|
|
|
|
|
|
# 顶部顺接 J1 圆盘 (Y_AXIS - 38 .. Y_AXIS + 38, Z=648)
|
|
|
|
|
|
# 底端全深顺接 M2 前后安装端 (Y: 92.0 .. 155.5)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
yz_pts = [
|
2026-09-27 00:28:49 +08:00
|
|
|
|
(Y_AXIS - 38.0, Z_RL + 38.0),
|
|
|
|
|
|
(Y_AXIS + 38.0, Z_RL + 38.0),
|
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 00:28:49 +08:00
|
|
|
|
# 6. 中部电机定子散热切除(R=30.5,保证电机定子散热,同时保留外侧与上下坚固承力壁)
|
|
|
|
|
|
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-09-27 04:48:49 +08:00
|
|
|
|
# 8. J1 直连法兰结构(定位止口 + 走线通孔 + 3x M2 贯通沉头孔)
|
2026-09-26 18:05:21 +08:00
|
|
|
|
boss = cyl(17.8, 54.942, 56.5)
|
|
|
|
|
|
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)
|
|
|
|
|
|
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(j1.L(th)).cut(j1.L(cb))
|
|
|
|
|
|
|
|
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
|
2026-09-26 18:05:21 +08:00
|
|
|
|
def make_pitch_to_roll_bracket(j_pitch, j_roll, z_pitch, z_r, name="bracket"):
|
|
|
|
|
|
"""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-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-09-27 00:28:49 +08:00
|
|
|
|
y_hub_in = HL.Y_COVER + 1.0 # 157.0 (从动法兰内侧面,预留 1.0mm 动间隙)
|
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-27 00:28:49 +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-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))
|
|
|
|
|
|
.lineTo(35.0, -5.0)
|
|
|
|
|
|
.lineTo(-35.0, -5.0)
|
|
|
|
|
|
.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-09-27 00:28:49 +08:00
|
|
|
|
# 10. 俯仰轴直连法兰结构(凸台延伸至 59.5 跨过间隙与法兰盘牢固熔接,保持单实体)
|
|
|
|
|
|
boss = cyl(17.8, 54.942, 59.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 00:28:49 +08:00
|
|
|
|
# 11. 竖直臂前侧外角倒角(5mm):平滑消除圆柱体以外的两侧垂直尖角
|
|
|
|
|
|
c_size = 5.0
|
|
|
|
|
|
c_left = (cq.Workplane("XY", origin=(HL.X_ARM - 35.0, y_hub_in, z_plate))
|
|
|
|
|
|
.moveTo(-0.1, -0.1)
|
|
|
|
|
|
.lineTo(c_size, -0.1)
|
|
|
|
|
|
.lineTo(-0.1, c_size)
|
|
|
|
|
|
.close()
|
|
|
|
|
|
.extrude(z_pitch - z_plate + 10.0))
|
|
|
|
|
|
c_right = (cq.Workplane("XY", origin=(HL.X_ARM + 35.0, y_hub_in, z_plate))
|
|
|
|
|
|
.moveTo(0.1, -0.1)
|
|
|
|
|
|
.lineTo(-c_size, -0.1)
|
|
|
|
|
|
.lineTo(0.1, c_size)
|
|
|
|
|
|
.close()
|
|
|
|
|
|
.extrude(z_pitch - z_plate + 10.0))
|
|
|
|
|
|
s = s.cut(c_left.val()).cut(c_right.val())
|
|
|
|
|
|
|
|
|
|
|
|
# 12. L 型转角连接处倒角过渡(倒角 2.0mm):
|
|
|
|
|
|
# 平滑消除立柱顶面与竖直臂交汇处的 90° 尖角与应力集中,严控动间隙保证动态零干涉
|
|
|
|
|
|
try:
|
|
|
|
|
|
wp_s = cq.Workplane(obj=s)
|
|
|
|
|
|
sel_l = cq.NearestToPointSelector((HL.X_ARM, y_hub_in, z_plate))
|
|
|
|
|
|
s = wp_s.edges(sel_l).chamfer(2.0).val()
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
2026-09-26 18:05:21 +08:00
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_shoulder_roll_base(j2, j3, half=None):
|
2026-09-27 04:48:49 +08:00
|
|
|
|
"""P05_大臂旋转座(深度圆角优化版)"""
|
2026-09-26 18:05:21 +08:00
|
|
|
|
return make_pitch_to_roll_bracket(j2, j3, Z_SH, Z_R3, name="P05_大臂旋转座")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_humerus_bone(j3, j4):
|
|
|
|
|
|
"""P06_大臂骨架 (Humerus Bone):
|
|
|
|
|
|
受 J3 (大臂自转, -Z轴, hub@Z_HUB3=380) 驱动,
|
|
|
|
|
|
向下延伸构成大臂主体骨架,底端抱紧 M4 (肘部俯仰电机, +Y轴, 轴线位于 Z_EL=332.0)。
|
|
|
|
|
|
1. XZ 视图满宽 Ø70mm 直通过渡:左右两侧(X: -16.5..53.5)全宽平滑垂直到达 Z_EL,严格相切融入 M4 下圆柱,彻底消除腰身台阶断差;
|
|
|
|
|
|
2. YZ 视图连续相切双 S 弯有机顺接:顶端 Ø70mm 圆柱与底端前端套筒(Y=155.5)及后端安装板(Y=92.0)严格切线顺接,彻底消除水平方顶阶梯平台;
|
2026-09-27 04:48:49 +08:00
|
|
|
|
3. 取消侧壁贯穿开孔,消除镂空,保持骨架为浑然一体的高强度流线型实体,彻底移除破坏曲面的多余切角与破碎倒角。
|
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)
|
|
|
|
|
|
|
|
|
|
|
|
# 顶端 Disc 结合面及底端过渡高度
|
|
|
|
|
|
z_top = 388.5
|
|
|
|
|
|
z_bot = Z_EL + 35.0 # 367.0
|
|
|
|
|
|
|
|
|
|
|
|
# 2. XZ 平面满宽流线轮廓(左右两侧严格相切于底端 M4 轴线圆柱,无收腰台阶):
|
|
|
|
|
|
xz_w = (cq.Workplane("XZ", origin=(0, Y_AXIS, 0))
|
|
|
|
|
|
.moveTo(-16.5, Z_EL)
|
|
|
|
|
|
.lineTo(-16.5, z_top)
|
|
|
|
|
|
.lineTo(53.5, z_top)
|
|
|
|
|
|
.lineTo(53.5, Z_EL)
|
|
|
|
|
|
.close())
|
|
|
|
|
|
xz_solid = xz_w.extrude(100.0, both=True).val()
|
|
|
|
|
|
xz_shape = cq.Shape(xz_solid.wrapped)
|
|
|
|
|
|
|
|
|
|
|
|
# 3. YZ 平面双向精确切线 S 弯顺接(前后平滑连续切线顺接,严控与 P07 动间隙):
|
|
|
|
|
|
dz_f = (z_top - z_bot) / 2.0 # 10.75 mm
|
|
|
|
|
|
dy_f = (163.0 - (Y_COVER - 0.5)) / 2.0 # 3.75 mm
|
|
|
|
|
|
R_f = (dy_f**2 + dz_f**2) / (2.0 * dy_f) # 17.283 mm
|
|
|
|
|
|
p_mid_f = (163.0 - dy_f, z_top - dz_f)
|
|
|
|
|
|
|
|
|
|
|
|
theta_max_f = math.asin(dz_f / R_f)
|
|
|
|
|
|
C_f1 = (Y_COVER - 0.5 + R_f, z_bot)
|
|
|
|
|
|
p_quarter_f1 = (C_f1[0] - R_f * math.cos(theta_max_f / 2.0),
|
|
|
|
|
|
C_f1[1] + R_f * math.sin(theta_max_f / 2.0))
|
|
|
|
|
|
C_f2 = (163.0 - R_f, z_top)
|
|
|
|
|
|
p_quarter_f2 = (C_f2[0] + R_f * math.cos(theta_max_f / 2.0),
|
|
|
|
|
|
C_f2[1] - R_f * math.sin(theta_max_f / 2.0))
|
|
|
|
|
|
|
|
|
|
|
|
dz_r = (z_top - z_bot) / 2.0 # 10.75 mm
|
|
|
|
|
|
dy_r = (93.0 - (Y_REAR - 8.0)) / 2.0 # 0.5 mm
|
|
|
|
|
|
R_r = (dy_r**2 + dz_r**2) / (2.0 * dy_r) # 115.8125 mm
|
|
|
|
|
|
p_mid_r = (93.0 - dy_r, z_top - dz_r)
|
|
|
|
|
|
|
|
|
|
|
|
theta_max_r = math.asin(dz_r / R_r)
|
|
|
|
|
|
C_r1 = (Y_REAR - 8.0 - R_r, z_bot)
|
|
|
|
|
|
p_quarter_r1 = (C_r1[0] + R_r * math.cos(theta_max_r / 2.0),
|
|
|
|
|
|
C_r1[1] + R_r * math.sin(theta_max_r / 2.0))
|
|
|
|
|
|
C_r2 = (93.0 + R_r, z_top)
|
|
|
|
|
|
p_quarter_r2 = (C_r2[0] - R_r * math.cos(theta_max_r / 2.0),
|
|
|
|
|
|
C_r2[1] - R_r * math.sin(theta_max_r / 2.0))
|
|
|
|
|
|
|
|
|
|
|
|
yz_w = (cq.Workplane("YZ", origin=(X_ARM, 0, 0))
|
|
|
|
|
|
.moveTo(Y_REAR - 8.0, Z_EL)
|
|
|
|
|
|
.lineTo(Y_COVER - 0.5, Z_EL)
|
|
|
|
|
|
.lineTo(Y_COVER - 0.5, z_bot)
|
|
|
|
|
|
.threePointArc(p_quarter_f1, p_mid_f)
|
|
|
|
|
|
.threePointArc(p_quarter_f2, (163.0, z_top))
|
|
|
|
|
|
.lineTo(93.0, z_top)
|
|
|
|
|
|
.threePointArc(p_quarter_r2, p_mid_r)
|
|
|
|
|
|
.threePointArc(p_quarter_r1, (Y_REAR - 8.0, z_bot))
|
|
|
|
|
|
.close())
|
|
|
|
|
|
yz_solid = yz_w.extrude(50.0, both=True).val()
|
|
|
|
|
|
yz_shape = cq.Shape(yz_solid.wrapped)
|
|
|
|
|
|
|
|
|
|
|
|
c_int = BRepAlgoAPI_Common(yz_shape.wrapped, xz_shape.wrapped)
|
|
|
|
|
|
c_int.Build()
|
|
|
|
|
|
body = cq.Shape(c_int.Shape())
|
|
|
|
|
|
s = s.fuse(body)
|
|
|
|
|
|
|
|
|
|
|
|
# 4. 电机中间定子散热裸露切除 (100% 裸露)
|
|
|
|
|
|
s = s.cut(Ycyl(30.5, Y_REAR + 0.5, Y_COVER - 6.5, X_ARM, Z_EL))
|
|
|
|
|
|
|
|
|
|
|
|
# 5. 保持腰身为坚固完整实体,移除侧向镂空贯穿槽
|
|
|
|
|
|
|
|
|
|
|
|
# 6. M4 接口成型
|
|
|
|
|
|
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)
|
|
|
|
|
|
s = make_direct_hub(s, j3, r_disc=35.0, z_out=58.0)
|
|
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_forearm_bone(j4, j5, half=None):
|
2026-09-27 04:48:49 +08:00
|
|
|
|
"""P07_小臂骨架 L型高刚度无干涉版(深度圆角优化版)
|
|
|
|
|
|
设计要点:
|
|
|
|
|
|
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
|
|
|
|
|
|
z_top_housing = Z_WR + 35.0 # 257.0
|
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)
|
|
|
|
|
|
.lineTo(y_rear, z_top_housing)
|
|
|
|
|
|
.lineTo(y_front, z_top_housing)
|
|
|
|
|
|
.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)
|
|
|
|
|
|
# 起点在顶板平整面 (y_arc_start, z_top_housing),精确相切至立柱内侧面 (y_hub_in, z_arc_end)
|
|
|
|
|
|
# 严控全域 Z >= z_top_housing,彻底消除侵入下方旋转副的悬空小方块与多余突起!
|
|
|
|
|
|
R_arc = 28.0
|
|
|
|
|
|
y_arc_start = y_hub_in - R_arc
|
|
|
|
|
|
z_arc_end = z_top_housing + R_arc
|
|
|
|
|
|
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))
|
|
|
|
|
|
.moveTo(y_arc_start, z_top_housing)
|
|
|
|
|
|
.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 04:48:49 +08:00
|
|
|
|
s = s.cut(Ycyl(30.5 + CLEARANCE_GAP, 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:
|
|
|
|
|
|
s = s.edges("|X").chamfer(CHAMFER_EDGE)
|
|
|
|
|
|
except:
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
# 圆润化 J4 圆盘外沿
|
|
|
|
|
|
s = s.edges(cq.selectors.BoxSelector(
|
|
|
|
|
|
(X_ARM - 40, y_out - 2, Z_EL - 40),
|
|
|
|
|
|
(X_ARM + 40, y_out + 2, Z_EL + 40)
|
|
|
|
|
|
)).fillet(FILLET_SMALL)
|
|
|
|
|
|
except:
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
# 圆润化垂直立柱外侧边棱
|
|
|
|
|
|
s = s.edges(cq.selectors.BoxSelector(
|
|
|
|
|
|
(X_ARM - 37, y_out - 2, z_top_housing),
|
|
|
|
|
|
(X_ARM + 37, y_out + 2, Z_EL + 40)
|
|
|
|
|
|
)).fillet(FILLET_SMALL)
|
|
|
|
|
|
except:
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
2026-09-26 18:05:21 +08:00
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_wrist_bracket(j5, j6):
|
2026-09-27 04:48:49 +08:00
|
|
|
|
"""P08_腕偏转座(深度圆角优化版)"""
|
2026-09-26 18:05:21 +08:00
|
|
|
|
return make_pitch_to_roll_bracket(j5, j6, Z_WR, Z_R6, name="P08_腕偏转座")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def p_tool_flange(j6):
|
2026-09-27 04:48:49 +08:00
|
|
|
|
"""P09_工具法兰 深度圆角优化版
|
|
|
|
|
|
关键改进:
|
|
|
|
|
|
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"}
|
|
|
|
|
|
driven = {"J1": "P04_肩叉", "J2": "P05_大臂旋转座", "J3": "P06_大臂骨架",
|
|
|
|
|
|
"J4": "P07_小臂骨架", "J5": "P08_腕偏转座", "J6": "P09_工具法兰"}
|
|
|
|
|
|
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
|
|
|
|
|
|
AB.GRP.update({"P01_胸板": "root", "P02_底脚": "root", "P03_肩吊臂": "root"})
|
|
|
|
|
|
AB.JAW = {}
|
|
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
parts_to_build = [
|
|
|
|
|
|
("P01_胸板", "胸腔支撑立柱(高刚性箱型梁+榫卯台座+走线窗)", lambda: p_chest(), 0x4b5563,
|
|
|
|
|
|
"V2高刚度立柱:66x66mm厚壁封闭箱梁+8mm壁厚+顶部P03榫卯台座+两组大圆角工艺走线窗"),
|
|
|
|
|
|
("P02_底脚", "测试台架底座(高刚度抗倾覆底盘+嵌装定位槽)", lambda: p_base_foot(), 0x374151,
|
|
|
|
|
|
"V2加长大底盘:200x320mm重型防倾覆底座+12mm嵌装槽+4xM6夹持槽+底部走线槽"),
|
|
|
|
|
|
("P03_肩吊臂", "肩关节基座机壳(高刚性规整风道散热版)", lambda: p_girdle(j1), 0x4b5563,
|
|
|
|
|
|
"V2浑然一体散热版:Ø73mm机舱+7组轴向散热格栅+PCBA对流窗+一体化顺滑斜挑立柱"),
|
|
|
|
|
|
("P04_肩叉", "肩叉(深度圆角版:顶部凸台R=8mm圆弧+圆盘边缘R=10mm)", lambda: p_fork(j1, j2), 0x2563eb,
|
|
|
|
|
|
"V2圆角:顶部方形突起改为R=8mm圆弧过渡,圆盘边缘R=10mm大圆角;散热腔顶板改为与前后安装环同一R=35圆柱凹弧(J2轴心),腔体保持敞开散热"),
|
|
|
|
|
|
("P05_大臂旋转座", "大臂旋转座(深度圆角版:16层Loft+内部L转角2mm倒角+动态零干涉)", lambda: p_shoulder_roll_base(j2, j3, None), 0x059669,
|
|
|
|
|
|
"V2圆角:Loft外轮廓R=10mm,L型转角内部2mm倒角,彻底清除立壁保证J2全角度0干涉"),
|
|
|
|
|
|
("P06_大臂骨架", "大臂骨架(平整版+前侧圆形过渡:顶部R10.5圆弧卷入)", lambda: p_humerus_bone(j3, j4), 0x0d9488,
|
|
|
|
|
|
"平整版:XZ两侧竖直直面,前侧上段竖直面+R10.5圆形过渡(净空P07立柱带3mm,J4不再卡死),电机散热腔+M4/J3接口"),
|
|
|
|
|
|
("P07_小臂骨架", "小臂骨架(L型圆弧加强版:R=28mm双相切内凹大圆弧+消除悬空块)", lambda: p_forearm_bone(j4, j5, None), 0x7c3aed,
|
|
|
|
|
|
"V2 L型结构:+Y侧背脊立柱避让大臂骨架,过渡区采用与顶面和立柱双相切的R=28mm平滑内凹大圆弧,彻底消除直斜线折角与悬空阶梯小块,下方M5电机半包散热,俯仰大范围自由运动零干涉"),
|
|
|
|
|
|
("P08_腕偏转座", "腕部转接座(深度圆角版:16层Loft+内部L转角2mm倒角+动态零干涉)", lambda: p_wrist_bracket(j5, j6), 0xd97706,
|
|
|
|
|
|
"V2圆角:Loft外轮廓R=10mm,L型转角内部2mm倒角,彻底清除立壁保证J5全角度0干涉"),
|
|
|
|
|
|
("P09_工具法兰", "末端工具法兰(深度圆角版:外轮廓R=3mm)", lambda: p_tool_flange(j6), 0xdc2626,
|
|
|
|
|
|
"V2圆角:外轮廓R=3mm,法兰面倒角2mm"),
|
|
|
|
|
|
]
|
2026-09-26 18:05:21 +08:00
|
|
|
|
|
2026-09-27 04:48:49 +08:00
|
|
|
|
for idx, (name, cn, fn, color, note) in enumerate(parts_to_build, 1):
|
|
|
|
|
|
print(f" [{idx}/9] 正在构建 {name} ({cn})...", end="", flush=True)
|
|
|
|
|
|
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 04:48:49 +08:00
|
|
|
|
"""爆炸图偏移:每个链接关节链逐级下移,电机沿自身轴拉出"""
|
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)
|
|
|
|
|
|
off = [0.0, 0.0, -SEP * k]
|
|
|
|
|
|
j = JS.get(grp)
|
|
|
|
|
|
if j:
|
|
|
|
|
|
nm = p["name"]
|
|
|
|
|
|
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"]]
|
|
|
|
|
|
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} 个实体) ❌"
|
|
|
|
|
|
print(f" [{idx}/9] {p['name']:<14} : 体积 {p['vol']/1000.0:6.1f} cm³ | {status}", flush=True)
|
|
|
|
|
|
if bad == 0:
|
|
|
|
|
|
print("-> 单实体检查全部通过!9/9 构件均为完美单一流形拓扑 ✓\n", flush=True)
|
|
|
|
|
|
else:
|
|
|
|
|
|
print(f"-> 发现 {bad} 个非单实体构件!\n", flush=True)
|
|
|
|
|
|
|
2026-09-26 18:05:21 +08:00
|
|
|
|
AB.explode_vec = explode_chain
|
|
|
|
|
|
bom = AB.export(JS)
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
|
|
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)
|