Files
Robot_Arm/.workbuddy/memory/2026-10-03.md
T

375 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 2026-10-03 工作日志
## P06 大臂骨架减重窗取消(视觉整改)
**问题**:用户实机视点反馈,J4 关节正上方 P06 大臂骨架(青绿色)顶部的"帐篷形减重窗"
正面看是一个贯通的矩形黑洞,位于整机最显眼的落脚点,非常不雅观。
该窗是 2026-10-02 减重改造时开的(XZ 轮廓 X3~37 沿 Y 切穿,Z362~374)。
**处理**:在 `src/arm_model.py` 加开关 `P06_HOLLOW_WIN = False`,`p_upper_bone()` 5c 处
改为条件 cut,该段恢复实心。保留 `P06_WIN_XZ` 轮廓与全部设计注释,改开关即可复原。
**结果**:
- P06 体积 161.1 -> **183.3 cm3**(与减重前的 183 一致),+22cm3 / 约 +27g PLA
- 碰撞检测 8 组接触面全部零干涉
- 强度校核 0 处不合格;z=365 剖面 SF=101.23(该段本就不缺强度,减重收益纯锦上添花)
- 已同步更新 BOM 说明、`src/strength_check.py` 剖面名("大臂骨架减重窗 @z=365"
-> "大臂骨架过渡块 @z=365",保留为该高度的安全裕度监控点)
- 重新导出 STEP/STL,重跑 `scratch/make_3mf.py` 打包 3MF,查看器已刷新
**备份**:`backups/20261003_p06_fill/arm_model.py.bak`
**结论/偏好**:减重窗不是越多越好。P04 立柱槽与 P07 顶板槽是朝上敞开的(不破坏外观)
故保留;P06 这个沿 Y 贯通、直接开在外观面上的窗属于"减重减出负面观感",已回退。
以后开减重腔要先问一句:会不会在外露面上形成可见的洞。
## J3(M3) 电机前端压盖 —— 补齐 roll 关节的"电机两端固定"
**定位**:用户截图里红圈标的电机裸露端 = J3 大臂自转电机 M3 的前端盖。
红圈周围两个零件:P05 大臂旋转座(绿 0x059669,抱紧 M3 的**holder**)与
P06 大臂骨架(青 0x0d9488,被 M3 驱动的 driven)。M3 前端盖外端面在 Z=389,
原来只有 P05 后端板 4xM3x10(S02)单面锁死 —— 与 2026-10-02 已做完的
J2/J4/J5(M2/M4/M5)三处相比是唯一还缺前端夹紧的 pitch/roll 关节。
**统一配方(复用,不重复实现)**:`arm_model.motor_front_clamp` 改成轴向无关 —
`axis="Y"`(J2/J4/J5 旧路径,几何逐位不变)/ `axis="Z"`(J3 roll,轴向 -Z)。
新增 `CLAMP_CLOCK_LOCAL`(= 72.2°+90k 的**关节局部相位**):trs() 里 y = z×x,
两个轴向换算到全局都是"全局相位 = −局部相位",所以 Y 轴仍是原来的 17.8°+90k,
Z 轴同一组数落在全局 (x,y) 平面 —— 全机 BCD55 孔位约定不变,改一处必须同步另一处。
**代价(关键)**:J3 的从动件 P06 毂面原本在 Z=388.5,与 M3 前端盖只差 0.5mm,
**放不下 5mm 压盖**。按 Y 轴三处的老办法让位:`z_top` 388.5→383.0、直锁凸台
59.5→65.0(+CLAMP_BACKOFF=5.5 = 压盖 5.0 + 动间隙 1.0 − 原基准 0.5)。
凸台同步加长后 3xS01 的头面台阶(s=58)/杆长/咬合量与 J3 直锁关系一律不变。
P05 侧 `roll_clamp=True` 开关在 `make_pitch_to_roll_bracket`(P05/P08 共用),
P08 传 False —— J6/M6 的前端压盖**还没做**,要从动件 P09 工具法兰让位(改直锁凸台)。
**结果**:13/13 单实体 ✓;P05 155.0 cm³(Z 384..525)、P06 166.5 cm³;
碰撞 8 组全零干涉(P05×P06 = 0.00 mm³);4xM3x8 与压盖零干涉(各自 0.00 mm³);
螺钉 S12 12→16 颗(docs/screws.json + screw_mesh.py 同步,实例数自洽断言通过);
3MF 重打包(P05 切片高 136→141mm)。改前改后对比图 `docs/shots/cmp_j3_before_after.png`。
**教训**:J3/J6 这类 roll 关节的"电机前端盖外侧"就是从动件的毂面,
加压盖前必须先量从动件到前端盖的轴向净空(Y 轴是 1.0mm,Z 轴只有 0.5mm)。
## 电机轴向厚度公差 2mm —— 全机 5 个夹紧关节的承压面让空
**用户提问**:"类似这种安装电机的地方是否考虑了 2mm 的电机厚度公差"。
**审计结论:完全没考虑,而且比"没留量"更糟 —— +2mm 的电机根本装不进去。**
轴向链是「后端板 4×M3x10 顶住电机尾端面 + 前端 R35 压盖 4×M3x8 压住前端盖」两个刚性面。
螺钉头一旦坐在沉孔台阶上就不能再进给(螺钉只能进不能退),所以两端都是硬约束,长度必须
对上。实测窗口:承压面在 s=-0.6 时,电机只能 L ≤ 56.6(长边 +0.6mm);L=58 时前端盖越位
1.4mm 直接撞压盖本体。
**关键设计判断:公差不能靠"拧紧"消化,只能靠垫片位。** 曾评估过三条路:
- 加长压盖/让关节长 2mm → 从动毂面让位要再动 5 个零件的轮毂间距,且关节轴向全链 +2mm;
- 一端改径向夹紧 → 要重做后端接口;
- **后端承压面让空成垫片位(选中)** —— 几何只改一处数,关节长度不变,全机统一。
**实现(单一事实源)**:
- `armcore.MOTOR_TOL = 2.0`(现场口径),`arm_build.REAR_SEAT = 0.6 + MOTOR_TOL = 2.6`;
- `Joint.pocket()` 的 PCB 腔底(电机尾端面承压面)从 -0.6 让到 -2.6 → 覆盖 J3/J4/J5/J6;
- P04 走自带刀具 `c_m2`(没调 `Joint.pocket`),同步改成 `-AB.REAR_SEAT` → 覆盖 J2;
- roll 关节 `rear_mount_holes(t_plate)` 7.0→8.0:让空 2mm 后承压面到螺钉沉孔台阶只剩
`t_plate - cb_depth - REAR_SEAT`,给到 8 才保住 1.4mm 膜厚(给 7 会退化成 0.4mm);
连带 `z_plate = z_r + 7` → `z_r + 8`(P05 杯顶 452→453,J2 让位圆柱底在 454.5,仍有余量)。
- 装配配方写进 README 与 `docs/screws.json` S02:T = 58.6 − L,量程 0~2.6mm,M3 平垫组合。
**验证**:`scratch/motor_tol_window.py`(窗口换算,改前 +0.6 → 改后 +2.6);
`scratch/motor_tol_check.py`(真实电机包络 R30/R30.15 布尔)5 个夹紧关节 × ΔL∈{-2,0,+2}
**全部 0.0mm³ 干涉且前端盖面压间隙 0.0**;13/13 单实体;碰撞 8 组全零;3MF 重打包。
**教训(比结论更重要)**:两个刚性夹持面 = 固定长度,零公差。想吃公差必须有一个面变成
"可垫可让"的软面,否则再大的公差也换不来行程 —— 这条同样适用于以后任何"双面夹紧"改法。
另:J1/M1 天然免疫(P03 是 Ø60.7 直通长孔,比电机长 3mm),所以公差只需要改 J2~J6。
## 承压面让位 2mm 的"残留凸台"—— 排查结论:消不掉,是承压面下沉的必然结果
**用户反馈**:P05/P06/P07/P08 后端都有凸台,是之前给电机预留 2mm 时"削掉了一些"
造成的;认为应该"通过减薄面"而不是"掏掉",没掏干净所以残留了凸台。
**实测确认现象**(`scratch` 里用双 Common 相减法量,band z=-2.6..0 内、64.4 方柱之外):
P05 759 / P06 1089 / P07 3139 / P08 721 mm3。成因确认无误:REAR_SEAT 从 0.6 抬到
2.6 时只把 64.4 方形腔加深(纯掏腔),腔壁以外 z=-2.6..0 的 R35 料没动,
相对新承压面(-2.6)凸起 2.6mm。
**两条消除路线都实测失败**(重要,别再重复试):
- A. 整段全截面切 z=-2.6..0 -> **P05/P08 碎成 2~3 块**。这圈 R35 料连同承压环
是"电机尾端安装板"与"臂身"之间**唯一**的轴向连接,切掉就断。
- B. 沿腔口做让位斜面(方形放样 taper_rect 与圆锥 taper_round 都试了)
-> 余料只降约 20%,且 P05/P08 仍碎 2 块。因为这圈料在 z>0 是杯体本体
(继续往上长),斜面一刀切下去等于削臂身。
**结论**:这不是"没掏干净"。承压面下沉 2mm 与"腔壁保持原 0.6mm 直壁"在几何上
互斥 —— 台阶是下沉的必然产物。它不顶到电机(电机尾端面在腔内、四周已让空),
只是外观上的一道台阶。要彻底消掉必须改承压面方案本身(承压环整体下沉 / R35 座
改短),那属于关节轴向长度调整,不在"预留 2mm 公差"这件事的范围内。
**本次改动**:`Joint.pocket` 与 P04 `c_m2` 的**几何未动**(体积与改前逐件一致,
13/13 单实体),只把上述实测结论写进 `Joint.pocket` 的 docstring 与
`arm_build.py` 常量区注释;`armcore.py` 新增 `REAR_LAND` / `R35_SEAT` 两个具名
常量把"0.6 原台肩"和"R35 外壁"显式化,避免以后再靠注释里的裸数字。
**教训(方法论,比结论更重要)**:
1. 这次我在**错误的坐标系**上浪费了大量时间 —— `map_pt(jp.t, ...)` 必须用
**被抱电机所属关节**的变换(P06 用 J4,不是驱动它的 J3),用错关节算出来的
footprint 全是错的 U 形,还误导我把余料误判成"Loft 方棱"。
2. 布尔测量不要用 `BRepAlgoAPI_Common(shape, slab.cut(sq))` 这种嵌套 cut ——
结果不可靠(我因此得到过 bbox 跨 86mm 的荒谬值)。用**两个独立 Common 相减**:
`vol(∩slab) - vol(∩sq)`。
3. 结论前先确认工具本身对不对:中途 `HALF, SEAT = AB.PCB_W/2.0, AB.REAR_SEAT`
之后又被覆盖,导致打印出 `SEAT=32.2` 这种自相矛盾的值,我却继续解读了好几轮。
## 承压面悬空凸台 —— 已彻底解决(用户第二次指出,我第一次判断错了)
**用户纠正**(重要):上一轮我结论是"凸台消不掉,是承压面下沉的必然产物",**错了**。
用户明确指出:① 不是去掉整个地方,只消掉一部分凸台;② 凸台本身不起任何作用;
③ 正确做法是把上面的厚度改成下面的厚度,或用更大半径的电机做布尔把面弄平;
④ 现状不好 3D 打印(需更多支撑、公差打不好)。
**真正的根因(这次用正确坐标系统一量就清楚了)**:
`Joint.pocket` 原来用 64.4 **方**腔从 -0.6 加深到 -2.6 掏出垫片位。64.4 方腔的
**内切圆半径恰好 = 32.2**,所以方腔在 45° 方向已吃穿到 r=45.5,R35 壁只剩
**四条边中点附近**的料 —— 定量实测 r=34 处材料沿 z 的区间(承压面 -2.6):
- 0°/180°/260°/280°:-8.0..12.0(贯通,属臂身本体 = 承力桥)
- 80°/100°:-8.0..-0.0(**只比承压面多 2.6mm,这段就是凸台**)
- 其余 20~160°:-8.0..-2.6(承压环本体,齐平)
**我上一轮失败的原因**:一直以为"整圈 R35 料是承压板与臂身之间唯一连接",
所以任何整段切都试过。实际上 0/90 方向那条桥在 z>0 是**臂身本体**(r=34 贯通到 z=12),
不是承压环的一部分。是我没量清楚才下了错误结论。
**修法(一刀,不做角度分区)**:承压面所在的 z=-REAR_SEAT..+SEAT_TOP 段,
腔口从 64.4 **方**改成 R35 **圆**(新增常量 `arm_build.SEAT_R=35.0` / `SEAT_TOP=1.0`);
z=0 以上的 PCBA 腔仍保持 64.4 方(PCB 是方的必须方腔)。整圈一次挖到承压面高度,
凸台零残留。P04 走自己的 `c_m2` 圆柱刀具,同步加 `cyl(AB.SEAT_R, -AB.REAR_SEAT, AB.SEAT_TOP)`。
`SEAT_TOP=1.0` 顺带清掉 roll 关节半包薄壁(R32.2..35 的 0.05cm3 残片)。
**连带好处**:承压环从"方腔内切 32.2 − 沉孔外缘 30.25 = 1.95mm 窄环"
变成"完整 R35 圆环 4.75mm",**受压面积 383 → 974 mm²(2.5 倍)**。
**验证**:13/13 单实体 ✓;静态干涉 8 组全零 ✓;`motor_tol_check.py` 5 关节 ×
±2mm 共 15 组全部 0.0mm³ 且面压间隙 0.0 ✓(±2mm 公差未受影响);
4xS02 沉孔残余 0.0(未被 R35 圆腔侵占)✓。
**方法论教训(比结论重要)**:
1. 上一轮我因为在**错误坐标系**里反复兜圈(`map_pt` 用了驱动关节而非电机所属关节),
得出了"消不掉"的错误结论。**遇到"改不动"的几何,先确认坐标系对不对**,
再考虑方案 —— 坐标系错了会把可解的问题判成无解。
2. **区分"桥"和"悬空料"要靠轴向区间实测**(固定半径 r=34 扫 z),
而不是靠体积或目测。体积法(P05 759 / P07 3139 mm3)会让人误以为整圈都是残留。
3. `solids_of` 会把 <0.01cm3 的布尔退化薄片也算成独立实体,判单实体时要设阈值,
否则会误报"碎块"。
## 修复:R35 圆腔切断连接壁 —— 肩叉顶部"没连上"(我 10-04 的改法有错)
**用户反馈**:最上面的蓝色肩叉(P04)顶部有一道缝,没连接上,要求连上。
**根因(几何实测)**:上一轮为了消"悬空凸台",我把承压面段(z=-2.6..0)的让位腔
从 64.4 方腔改成 **R35 圆腔**(`arm_build.SEAT_R=35.0`, `SEAT_TOP=1.0`)。这是错的 ——
R35 恰好等于后端板外壁半径,等于把 r=32.2..35 那圈 **2.8mm 厚的连接壁整圈挖穿**。
实测(`scratch/_rad.py` 逐方位径向扫描,P04 电机局部系):
| z | 0°/45°/90°/135°/180° | 225° | 270° |
|---|---|---|---|
| -3.0(承压面下) | 28.0-35.0 有料 | 有料 | 有料 |
| -2.4 .. +0.8 | **全空** | 35.0-35.5(0.5mm 薄片) | 35.0-56.0 |
即:后端法兰(R35 圆盘,z=-8..-2.6)与杯壁(z>=+1.0)之间被切出一条 **3.6mm 宽、
360° 全通的环槽**,只剩 240~320° 方位靠臂身本体相连,225° 还留了一片 0.5mm 厚的
孤立薄片 —— 打印出来就是你截图里那道缝。**单实体校验查不出来**(13/13 仍通过,
因为臂身本体兜住了),只有逐方位测轴向材料区间才看得见。
**修法(一处数值)**:`SEAT_R: 35.0 -> PCB_W/2.0 = 32.2`、`SEAT_TOP: 1.0 -> 0.0`。
32.2 = 64.4 方腔的内切圆半径,正好只挖掉悬空凸台、保留 r=32.2..35 整圈连接壁,
且在0/90/180/270 方向与上方方腔壁齐平、45° 方向比方腔多留料把四角补实。
同步改 P04 的 `c_m2`(走自己的圆柱刀具)+ 5 处 BOM 说明 + `screws.json` S02 备注。
**验证**:
- 改前/改后对照(`scratch` 布尔复现两版):改前连接壁 **36/36 方位全断**,
改后 **360° 整圈连续**
- 5/5 件(P04~P08)连接壁整圈连续、单实体、4xS02 沉孔残余 0.00mm³
- 13/13 单实体 ✓;静态干涉 8 组全零 ✓
- `motor_tol_check.py` 5 关节 × ±2mm 共 15 组全部 0.0mm³、面压间隙 0.0 ✓(公差未受影响)
- 体积回归:P04 280.1 -> 282.1 cm³(补回了被误挖的料)
**教训(补上一轮的方法论空白)**:
1. **单实体 + 零干涉不代表结构对**。这次13/13 全过、8 组零干涉,但零件内部被切出一条
360° 通槽 —— 因为臂身本体在另一侧兜住了连接。"是否连通"必须单独验证:
固定半径(如 r=33.6)逐方位扫 z,找材料轴向区间是否连续。
2. **"把面弄平"不等于"把料全挖到外壁"**。用户说"用更大半径的电机做布尔把面弄平",
正确解读是"挖到能让表面齐平的那个半径",即方腔内切圆 32.2,而不是外壁 R35。
选刀半径前必须先确认**哪一圈料是承力连接**,不能只看凸台本身。
3. 改完要**回头验上一轮修过的所有件**,不能只验当前这件。P05~P08 是共享 `pocket()`
自动受益,但 P04 走自己的 `c_m2`,是最容易漏的一处 —— 本次两处都改了。
## 压盖"拼接痕"视觉整改:四处前端压盖外缘倒 R4(新增 blend_clamp_seam)
**用户反馈**:给了两张 P04/M2 压盖的截图 —— 第一张红圈里能看到一圈**硬棱**("圆盘贴在
臂身上"的接缝),第二张是圆润连续的过渡。要求"两面的都变成第二张一样圆润的"。
**定位(几何实测,不是目测)**:
1. 先怀疑是压盖 R35 圆柱面本身的棱 -> 枚举同心 R35 圆边,发现 Y157 以上压盖外表面
**完全暴露**(四周 r>35.2 无料),R35 圆柱面上根本没有任何棱边。
2. 又怀疑压盖圆盘被叉板切出缺口 -> 扫 Y=161.0 截面每个方位的 Rmax,**全周都是
35.00,完整圆盘无缺口**。
3. 最后按"轴向坐标 ≈ 压盖前端面 且 到轴距离 34~36.5"筛棱边,命中**唯一一条
弧长 219.9mm 的样条边**(Y=161.0 平面、r 恒 35.0)—— 这就是拼接缝:
压盖是 `s.fuse(fp)` 直接熔接的圆盘,前缘落在臂身曲面上,交角处留硬棱。
4. 沿 Y 的 Rmax 剖面佐证:Y<=156.5 时 R@90=60(叉板圆柱),Y>=157.5 时 R@90=35
—— 台阶高 25mm,圆角正是要把它化开。
**修法**:新增 `blend_clamp_seam(shape, px, py, pz, s_face, axis, r, tag)`,
按"轴向坐标 ≈ 前端面 且 半径 ≈ R35"定位缝边并倒圆;倒圆失败只打印提示、**退回原形状**
(一个装饰性圆角绝不能毁掉整件)。`CLAMP_SEAM_FILLET = 4.0`(实测 R4 可行、R5 报
BRep_API 失败)。四处统一调用:P04/M2、P05/M3(roll-Z)、P06/M4、P07/M5。
**必须放在各自零件的最后一步布尔之后** —— 缝边是压盖与臂身相交才产生的,中途任何
一刀都可能改变它。
**踩的坑**:`near_face()` 里我把 Y 轴关节的面坐标写成了 `p.z`(应为 `p.y`),
导致函数一条边都找不到、静默"保持原样"(幸好有打印,否则会以为改好了)。
**教训:几何选择器写错时的默认行为是"什么都不做",必须让它打印命中数量**,
否则"没报错"会被误读成"已生效"。调试手段:先用独立脚本按同样条件验证选择器
能命中 1 条,再进源码。
**验证**:4/4 命中并倒圆;13/13 单实体 ✓;静态干涉 8 组全零 ✓;
`motor_tol_check.py` 5 关节 × ±2mm 共 15 组仍 0.0mm³ ✓(沉孔在 BCD27.5,
离 R35 外缘还有 7.5mm,倒圆完全不涉及螺钉孔)。
**方法论**:定位"视觉棱线"要**按几何条件筛边**(轴向坐标 + 半径区间),
不要靠渲染图目测猜是哪条棱。我这次先猜了两次圆柱面、一次缺口,三次都错,
第四次用条件筛选才一次命中。
## 撤回:压盖"拼接痕"R4 圆角(我误判,用户纠正)
**用户反馈**(两次纠正):
1. 我把圆角加到了 J2/J3/J4/J5 **四处**压盖 -> 用户:"我说的是**同个零件的两边**,
只改我发你图片的部分"。已把 P05/P06/P07 的调用撤回。
2. 我又改回只做 P04 一处 -> 用户:"不是圆角,而是你要把**拼接的痕迹去掉**,
现在另外一边是中间有个面,两边会凸出出来的"。
**已全部撤回**:删掉 `blend_clamp_seam()` 函数、`CLAMP_SEAM_FILLET` 常量、
P04 的调用、P04 BOM 里的说明、`screws.json` S12 的圆角备注。
`grep blend_clamp_seam|CLAMP_SEAM_FILLET src/arm_model.py` = 0。
重跑构建:13/13 单实体、8 组零干涉,代码回到加圆角之前的状态。
**为什么撤回(我的诊断是错的)**:
用户描述的目标是"**去掉拼接的痕迹**"(几何问题),我却理解成"**在缝上加圆角**"
(装饰问题)。这两件事完全不同:加圆角不改变"这里是两个零件熔接出来的"这个事实,
只是把锐边磨圆;用户要的是让它们**本来就长成一个连续曲面**。
**我实测到的(可能有用,但结论未定)**:
- 压盖本体在 Y=158 沿径向的最大材料半径**全周恒为 35.00**,是完整 R35 圆筒、
没有任何切削或缺口 -> 第一张图里那条"竖直直棱 + 右侧平面"**不是压盖本体**。
- 那个"中间有个面"实测是 P04 上Z=526..646.5 / X=2.8..46.1 / Y=155.5..164.5 的
**4048mm² 平面**(法向 (0,1,-0.07),带 4° 斜度),位于**电机上方 36mm 处**,
由 `p_fork` 第 5 步 `Xplate(yz_pts, -20.0, 60.0)` 的轮廓线段与 XZ loft 求交切出。
- 两侧"凸出的弧"最可能是 X=45.0 平面(5697mm²,法向 +X)与 R=164 圆柱
@(209,128,545) 的交接,以及立柱减重槽的两片腹板(X=23.0 / X=35.0 两面)。
- 减重槽参数 `P04_CH = x0=23, x1=35, y0=102, y1=154, z_floor=525`。
**教训(比这次的错更重要)**:
1. **"视觉缺陷"先分辨是几何问题还是表面质量问题**。用户的措辞
("去掉痕迹""两边凸出来")指向**形状本身不对**;我却直接跳到"加个圆角_smooth 一下"
—— 这是用装饰手段掩盖几何问题,既没解决需求,也白改了四个零件。
2. **"两边"是拓扑位置,不是"多处"**。用户说"同个零件的两边"指同一个零件上
对称的两个侧面,我却推广成了"全机四处"。**改动范围要严格贴着用户指的地方**,
有歧义就问(我第一次就该问,而不是先改了四处再撤回)。
3. 定位不准时**该早点问**。我换了 6~7 种测量方式(面枚举、边枚举、截面扫、
径向扫、剪影投影)都没能确定那个面,就该停下来问,而不是继续猜下去。
## 视觉整改(成功):P04 电机上方 4048mm2 大平面 -> Hermite 弧面
**用户反馈**(第三次纠正后终于对题):给了标注红线的截图 —— "在电机上方的地方,
是一整个非常大的面,需要做成弧形面",并确认"平顶面需要匹配两边突出的弧度"。
**定位(面枚举法,一次命中)**:枚举 P04 所有平面中「法向 +Y、Z>=520」且面积最大的面:
```
面积 4048mm² 法向 (0.00, 1.00, -0.07) X 2.8..46.1 Y 155.5..164.5 Z 526.0..646.5
```
就是它。成因是 `p_fork` 第 5 步 `yz_pts` 里这一段**直线**:
```
(Y_AXIS+36.5, Z_RL+36.5)=(164.5,646.5)→ (Y_COVER-0.5, Z_SH+36.0)=(155.5,526)
```
沿 X 拉成平板,法向 (0,1,-0.07) 的 4° 斜度就是这么来的。两侧"鼓"的是
`xz_wire` 的 R18 圆弧(`(28,646.5)→(44,630)` 那段 radiusArc(18.0))。
**为什么不能用单段圆弧**:起点 A=(155.5,526) 处切线须沿 Y(接 Y=155.5 竖直段),
终点 B=(164.5,646.5) 处切线须沿 Z(接 Z=646.5 顶段)—— 解圆心得 R=9 与 R=120.5
**互相矛盾**,单个圆弧无法同时满足。故用**三次 Hermite**(与 P05/P06 的 Loft 过渡同款):
m0 = -0.5·d·0.35(沿 -Y),m1 = 0.5·d·0.5(沿 +Z),12 段采样。
中部向 +Y 外凸约 3mm,弧度观感与两侧 R18 协调。
**踩的坑(重要)**:第一次实现把曲线采样成 `y_a → y_b`,而原列表是 `y_b → y_a`
—— **顶点绕序反了**,多边形自交,布尔后零件 **碎成 3 块、体积从 282 掉到 48.7cm³**。
改回原绕序立刻恢复单实体、体积 274.27cm³。
**教训:改动多边形顶点序列时必须保持原有绕序**,否则自交会让布尔结果彻底失真,
而症状(体积暴跌 + 碎块)看起来像"刀切掉了大量料",极易误判方向。
这次是体积对不上基准(差 233cm³)才立刻回头查绕序。
**验证**:13/13 单实体 ✓;静态干涉 8 组全零 ✓;
`motor_tol_check.py` 5 关节 × ±2mm 共 15 组仍 0.0mm³ ✓;
面枚举确认 4048mm2 平面已消失,原位置变成 **R=18 圆柱面 1447mm²**(Z 630..646.5);
体积 282.07 → 274.27 cm³(弧面替代平面削掉 7.8cm³,符合预期)。
**方法论(这次做对了的地方)**:不再靠截图目测猜,而是**按几何条件筛面**
(法向 +Y + Z 下界 + 面积最大),第一轮就锁定了目标面及其成因代码行。
前两轮失败(改圆角、改范围)都是因为没先定位清楚就开始动手。
## 承压面"围挡"消除:SEAT_R 必须是 R35(用户第三次指出,我前两次都错在"取值方向"上)
**用户反馈**(第三次纠正):"之前削平面的时候还是不对,凸台还是在的,你加了一圈围挡,
这不是正确做法,需要把凸台、围挡一起弄平,做成和电机两头齐平一起的平面。"
截图是 P08(#d97706 橙色)M6 电机后端,能看到 R35 端面上有一圈凸起的环。
**根因(一行公式,之前两次都没想透)**:
```
只要 SEAT_R < R35,外壁与刀半径之间那圈环墙就必然存在,
且相对承压面凸起 (R35 − SEAT_R),把电机尾端面围在中间。
```
- 我第一次取 64.4 **方**腔 -> 四角被吃穿,残留 4 段弧 = "凸台"
- 我第二次取 32.2 = 方腔**内切圆**(想"保住连接壁")-> 32.2 与 35 之间那圈
**2.8mm 宽环墙完整保留**,承压面只挖到 32.2,于是环墙凸起 2.6mm = "围挡"
(P08 实测该圈**1536.9 mm³**)
两次都不是"残留",而是**取值的必然产物**。用户第三次要求"一起弄平"就是指这个。
**正确改法(一处数值)**:`SEAT_R: 32.2 -> 35.0`(= 外壁 R35)、`SEAT_TOP: 0.0 -> 1.0`。
承压面段整圈挖到外壁 -> 承压面变成**完整 R35 平圆盘**,凸台与围挡同时消失。
`SEAT_TOP=+1.0` 是为了吃掉半包开口(Y93.0~95.8)那截 0.052cm³ 残片
(取 0 时它脱空成独立碎块,P05/P08 各多一块)。
**为什么不重演 2026-10-04 的"肩叉顶部没连上"**:
那版切 R35 但 `SEAT_TOP=0`,在 z=0..1.0 残留一截薄片 + 承力桥判定失误。
这次实测:band 段(z=-2.4..+0.8)r33.5 处**围挡残留 0/36**,
r36..58(臂身)有料方位 P04 10/36、其余各 15/36,其余方位靠 z>+1.0 杯体连接,
**无整圈通槽**。关键差别是 SEAT_TOP 抬到 +1.0,不是改回 32.2。
**连带好处**:承压环由「方腔内切 32.2 − 沉孔外缘 30.25 = 1.95mm 窄环」
变为「完整 R35 圆环 4.75mm」,**受压面积 383 -> 974 mm²(2.5 倍)**。
**验证**:
- 13/13 单实体 ✓(P04 272.3 / P05 151.4 / P06 158.8 / P07 222.6 / P08 138.1 cm³)
- 静态干涉 8/8 零 ✓
- `motor_tol_check.py` 5 关节 × ΔL∈{−2,0,+2} 共 15 组全部 0.0mm³、面压间隙 0.0 ✓
- 4×S02 沉孔残余 **0.00mm³**(沉孔 z=-8..-4 与圆腔 z=-2.6..+1.0 不重叠)✓
**踩的坑(重要)**:
1. **自己写的光栅化投影渲染器(从 mesh_arm.json 三角网格直接光栅)完全不能用** ——
深度缓冲/背面剔除/缩放全错,出一堆三角形碎面。排查这个问题花掉十几轮。
**教训:项目已有 `src/shot.py`(headless Edge)就是唯一可靠的渲染链路,别自己造。**
2. `src/shot.py` 并发渲染会随机 FAIL —— 根因是**没加 `--user-data-dir`**,
多个 Edge 实例抢同一个默认 profile 的锁。已修:每次 `tempfile.mkdtemp()`
建独立 profile,收尾 `shutil.rmtree`。加上之后 4 视图并发 100% 成功。
3. 写 BOM 说明时在 `"` 引号字符串里放了未转义的中文引号 `"一圈围挡"` ——
直接 SyntaxError 把 109KB 的 arm_model.py 写坏。已从 `.bak/` 备份恢复。
**教训:批量替换长中文注释时,别把双引号文本塞进 Python 双引号字符串。**
已建立 `.bak/arm_model.py.bak20261005` / `arm_build.py.bak20261005`。
**方法论教训(第三次了)**:
"改不动 / 消不掉"的几何问题,先想清楚**是不是某个取值的必然结果**,
而不是急着找"残留料"去切。SEAT_R 这个旋钮从 64.4 方腔 -> 32.2 -> 35.0,
每次换取值都改变了"环墙是否存在",而我一直只在 32.2 这一档里找原因。
**参数化几何里,"某段料消失"几乎总是某个半径/长度取值的函数,不是布尔残留。**