戰(zhàn):用自然語(yǔ)言生成STEP/URDF/G-code的完整方案)
CAD 這行當(dāng)有個(gè)特別擰巴的地方腦子里想清楚一個(gè)零件只要三秒手上把它畫(huà)出來(lái)可能要三十分鐘。拉伸、倒角、打孔、裝配每一步都是重復(fù)勞動(dòng)。所以當(dāng)“用一句話生成 CAD 模型”這個(gè)念頭冒出來(lái)的時(shí)候我第一反應(yīng)不是“這能行嗎”而是“這要是能行我能省下多少時(shí)間”。text-to-cad 就是沖著這個(gè)痛點(diǎn)去的——把自然語(yǔ)言描述直接翻譯成可用的 CAD 文件輸出 STEP、URDF、G-code 這些下游工具能直接吃進(jìn)去的格式。它解決的不是“畫(huà)得更好看”而是“從想法到可制造文件”這一段最枯燥的搬運(yùn)工作。適合誰(shuí)看做機(jī)械設(shè)計(jì)的、搞機(jī)器人仿真的、玩 3D 打印的以及任何被重復(fù)建模折磨過(guò)的工程師。下面我把自己折騰這套流程的完整思路和踩過(guò)的坑攤開(kāi)講。1. 整體設(shè)計(jì)思路與方案選型1.1 為什么是“文本到 CAD”而不是“文本到網(wǎng)格”很多人第一次聽(tīng)到 text-to-cad會(huì)下意識(shí)把它和文生 3D 模型混為一談。這倆差別大了去了。文生 3D 模型比如生成一個(gè)花瓶擺件輸出的是網(wǎng)格文件STL 或者 OBJ本質(zhì)上是一堆三角面片拼出來(lái)的殼。這東西看著像但你沒(méi)法改。想在那個(gè)花瓶上開(kāi)個(gè)直徑 20 毫米的孔對(duì)不起網(wǎng)格沒(méi)有參數(shù)化信息你只能重新生成或者手動(dòng)修。CAD 不一樣。CAD 的核心是參數(shù)化特征——拉伸了多少、孔在哪個(gè)基準(zhǔn)面上、倒角半徑多大這些信息都以特征樹(shù)的形式存著。STEP 文件之所以在工業(yè)界通用就是因?yàn)樗A袅藥缀蔚木_數(shù)學(xué)描述NURBS 曲面而不是近似網(wǎng)格。所以 text-to-cad 的技術(shù)路線本質(zhì)上是要讓語(yǔ)言模型理解“特征建?!钡倪壿嫸皇恰澳笮螤睢?。我選定的方案是大語(yǔ)言模型負(fù)責(zé)語(yǔ)義解析和代碼生成CAD 內(nèi)核負(fù)責(zé)幾何構(gòu)建中間用腳本橋接。具體來(lái)說(shuō)讓模型把“一個(gè) 50x50x10 的底板四角各有一個(gè)直徑 5 的通孔”翻譯成 CadQuery 或 OpenSCAD 的代碼然后調(diào)用內(nèi)核執(zhí)行最后導(dǎo)出 STEP。這條路的好處是每一步都可控——代碼你能看、能改、能版本管理出了問(wèn)題知道去哪找。1.2 工具鏈選型CadQuery 還是 OpenSCAD這是第一個(gè)要做的關(guān)鍵決策。兩個(gè)都是代碼驅(qū)動(dòng)建模的利器但脾氣完全不同。OpenSCAD 更老牌語(yǔ)法像寫(xiě)程序CSG構(gòu)造實(shí)體幾何的思路——用立方體、圓柱體這些基本體做布爾運(yùn)算。上手快社區(qū)大但它的幾何內(nèi)核是網(wǎng)格化的導(dǎo)出的 STEP 精度有限而且不支持 NURBS 曲面。做簡(jiǎn)單零件沒(méi)問(wèn)題做復(fù)雜曲面就力不從心。CadQuery 基于 OCCTOpen CASCADE Technology內(nèi)核這是工業(yè)級(jí)的幾何內(nèi)核和 SolidWorks、FreeCAD 用的是同一套底層。它支持真正的 B-rep邊界表示建模導(dǎo)出的 STEP 是精確幾何。語(yǔ)法上更接近“選擇面、在上面做操作”的建模思維比如Workplane(XY).box(50,50,10).faces(Z).workplane().hole(5)讀起來(lái)就是建模步驟本身。我最終選 CadQuery理由有三條。第一STEP 導(dǎo)出質(zhì)量是硬指標(biāo)下游要做仿真或者 CAM 加工網(wǎng)格化的幾何根本沒(méi)法用。第二CadQuery 的選擇器語(yǔ)法selector和語(yǔ)言模型的輸出習(xí)慣很契合——模型很容易學(xué)會(huì)“選頂面、選邊、做操作”這種鏈?zhǔn)奖磉_(dá)。第三URDF 導(dǎo)出需要精確的幾何和坐標(biāo)系定義CadQuery 的裝配體功能能直接給出每個(gè)零件的位姿矩陣。提示如果你只是想做 3D 打印的擺件OpenSCAD 足夠。但只要涉及裝配、仿真、加工CadQuery 是更穩(wěn)妥的選擇。1.3 從文本到代碼的映射策略語(yǔ)言模型怎么知道該生成什么代碼這里有個(gè)關(guān)鍵設(shè)計(jì)我不讓模型直接“想象”幾何而是給它一套模板和約束。具體做法是準(zhǔn)備一個(gè)提示詞框架里面包含幾個(gè)要素。第一是 CadQuery 的常用 API 清單比如box、cylinder、hole、fillet、chamfer這些高頻操作的簽名。第二是坐標(biāo)系約定明確 Z 軸向上、XY 平面為基準(zhǔn)面。第三是輸出格式要求強(qiáng)制模型只輸出可執(zhí)行的 Python 代碼塊不要解釋文字。這么做的原因是語(yǔ)言模型對(duì)幾何空間的理解其實(shí)很弱。你讓它“生成一個(gè)支架”它可能給你一個(gè)比例完全不對(duì)的東西。但如果你把任務(wù)拆解成“底板尺寸、孔位坐標(biāo)、加強(qiáng)筋厚度”這些具體參數(shù)它就能準(zhǔn)確映射到代碼上。所以我的提示詞里會(huì)引導(dǎo)用戶(hù)把描述寫(xiě)具體比如不說(shuō)“一個(gè)安裝板”而說(shuō)“一個(gè) 100x60x8 的矩形板長(zhǎng)邊兩側(cè)各有兩個(gè) M4 沉頭孔孔中心距板邊 10 毫米”。2. 核心細(xì)節(jié)解析與實(shí)操要點(diǎn)2.1 提示詞工程把話說(shuō)清楚比什么都重要我試過(guò)直接用一句話丟給模型“給我生成一個(gè)法蘭盤(pán)”。結(jié)果出來(lái)的東西能用但尺寸全憑它猜內(nèi)徑外徑螺栓孔數(shù)量都是隨機(jī)的。后來(lái)我總結(jié)出一套描述模板效果穩(wěn)定很多。描述里必須包含的信息有整體尺寸長(zhǎng)寬高或者直徑厚度、特征位置孔在哪、槽在哪用坐標(biāo)或者相對(duì)位置描述、特征參數(shù)孔徑、深度、圓角半徑、基準(zhǔn)約定哪個(gè)面是底面。比如“一個(gè)直徑 80 毫米、厚度 10 毫米的圓盤(pán)中心有一個(gè)直徑 30 毫米的通孔沿直徑 60 毫米的圓周均布 6 個(gè)直徑 6 毫米的通孔”這種描述模型幾乎不會(huì)出錯(cuò)。還有個(gè)小技巧用相對(duì)位置而不是絕對(duì)坐標(biāo)。說(shuō)“距邊緣 10 毫米”比說(shuō)“在 x10 的位置”更不容易出錯(cuò)因?yàn)槟P蛯?duì)絕對(duì)坐標(biāo)的推算經(jīng)常翻車(chē)。另外單位要明確我統(tǒng)一用毫米在提示詞里寫(xiě)死避免模型在英寸和毫米之間反復(fù)橫跳。2.2 代碼生成后的校驗(yàn)環(huán)節(jié)模型生成的代碼不能直接信。我踩過(guò)的最大的坑是代碼能跑但幾何是錯(cuò)的。比如孔打穿了不該穿的面或者兩個(gè)實(shí)體沒(méi)有正確合并導(dǎo)出 STEP 的時(shí)候變成兩個(gè)分離的殼。所以我在流程里加了一道自動(dòng)校驗(yàn)。用 CadQuery 執(zhí)行完代碼后檢查幾個(gè)指標(biāo)實(shí)體的數(shù)量應(yīng)該是一個(gè)如果是多個(gè)說(shuō)明布爾運(yùn)算沒(méi)做對(duì)、包圍盒尺寸和描述里的整體尺寸對(duì)比、體積排除掉空殼或者自相交的情況。這些檢查用幾行 Python 就能搞定但能攔下大部分低級(jí)錯(cuò)誤。import cadquery as cq result cq.Workplane(XY).box(50, 50, 10).faces(Z).workplane().hole(5) solid result.val() bbox solid.BoundingBox() print(fX: {bbox.xlen}, Y: {bbox.ylen}, Z: {bbox.zlen}) print(fVolume: {solid.Volume()})如果包圍盒的 Z 方向長(zhǎng)度不是 10或者體積明顯偏離預(yù)期就說(shuō)明生成的代碼有問(wèn)題需要回退重試或者人工介入。2.3 STEP、URDF、G-code 三種輸出的差異處理這三個(gè)格式面向的下游完全不同不能一套代碼走天下。STEP是幾何交換格式重點(diǎn)是幾何精確和拓?fù)渫暾?。?dǎo)出時(shí)要注意單位——STEP 標(biāo)準(zhǔn)默認(rèn)是毫米但有些內(nèi)核會(huì)寫(xiě)成米導(dǎo)入到別的軟件里尺寸就差一千倍。CadQuery 的exportStep默認(rèn)單位是毫米這點(diǎn)比較省心。URDF是機(jī)器人描述格式它不只要幾何還要運(yùn)動(dòng)學(xué)樹(shù)——哪個(gè)零件是父連桿、哪個(gè)是子連桿、關(guān)節(jié)類(lèi)型是什么、旋轉(zhuǎn)軸在哪。所以生成 URDF 的時(shí)候文本描述里必須包含裝配關(guān)系的信息。比如“一個(gè)底座和一個(gè)轉(zhuǎn)臺(tái)轉(zhuǎn)臺(tái)繞 Z 軸旋轉(zhuǎn)”模型需要生成兩個(gè)獨(dú)立的幾何體分別導(dǎo)出為 STL然后在 URDF 的 XML 里定義 link 和 joint。這里有個(gè)坑URDF 引用的網(wǎng)格文件路徑是相對(duì)的如果路徑寫(xiě)錯(cuò)導(dǎo)入 CoppeliaSim 或者 RViz 的時(shí)候會(huì)報(bào)找不到 mesh。G-code是給 CNC 或者 3D 打印機(jī)用的它不關(guān)心幾何的數(shù)學(xué)表示只關(guān)心刀具軌跡。從 CAD 到 G-code 中間通常要經(jīng)過(guò) CAM 工序但簡(jiǎn)單的 2.5 軸加工可以跳過(guò) CAM直接從幾何生成路徑。我的做法是提取零件的輪廓和孔位用簡(jiǎn)單的輪廓偏置算法生成刀具路徑。這一步精度要求高因?yàn)?G-code 直接控制機(jī)床運(yùn)動(dòng)坐標(biāo)錯(cuò)一點(diǎn)就撞刀了。輸出格式核心信息主要坑點(diǎn)校驗(yàn)重點(diǎn)STEP精確幾何、拓?fù)鋯挝徊灰恢?、?shí)體分離包圍盒、實(shí)體數(shù)量URDF幾何運(yùn)動(dòng)學(xué)樹(shù)網(wǎng)格路徑、關(guān)節(jié)軸定義link/joint 完整性G-code刀具軌跡坐標(biāo)系原點(diǎn)、安全高度路徑無(wú)碰撞、坐標(biāo)范圍3. 實(shí)操過(guò)程與核心環(huán)節(jié)實(shí)現(xiàn)3.1 環(huán)境搭建與依賴(lài)安裝先把環(huán)境弄干凈。我用的是 Python 3.10CadQuery 對(duì) 3.11 的支持當(dāng)時(shí)還有點(diǎn)問(wèn)題3.10 最穩(wěn)。安裝用 conda 比 pip 省心因?yàn)?OCCT 內(nèi)核的二進(jìn)制依賴(lài)比較多conda 能自動(dòng)處理。conda create -n text2cad python3.10 conda activate text2cad conda install -c conda-forge cadquery pip install openai這里有個(gè)細(xì)節(jié)CadQuery 的 conda 包和 pip 包不兼容混裝會(huì)出問(wèn)題。我一開(kāi)始用 pip 裝跑起來(lái)報(bào) OCCT 的 DLL 找不到折騰了半天換成 conda 就好了。另外如果你要用 URDF 導(dǎo)出還需要裝urdfpy或者直接手寫(xiě) XML我傾向手寫(xiě)因?yàn)橐蕾?lài)少、可控。3.2 從描述到 CadQuery 代碼的完整鏈路整個(gè)鏈路分四步接收描述、生成代碼、執(zhí)行校驗(yàn)、導(dǎo)出文件。我用一個(gè) Python 腳本串起來(lái)。第一步構(gòu)造提示詞。我把 CadQuery 的常用 API 和幾個(gè)示例代碼拼成 system prompt讓模型知道該用什么語(yǔ)法。示例代碼很關(guān)鍵模型會(huì)模仿示例的風(fēng)格。我放了三個(gè)例子一個(gè)帶孔的板、一個(gè)旋轉(zhuǎn)體、一個(gè)簡(jiǎn)單的裝配體。第二步調(diào)用模型生成代碼。這里用流式輸出還是等完整結(jié)果我選等完整結(jié)果因?yàn)榇a需要整體校驗(yàn)流式?jīng)]意義。生成的時(shí)候設(shè)置temperature0.2降低隨機(jī)性讓輸出更穩(wěn)定。第三步執(zhí)行代碼。用exec在受限的命名空間里跑只允許cadquery和基本數(shù)學(xué)庫(kù)。跑完拿到result對(duì)象。第四步校驗(yàn)并導(dǎo)出。校驗(yàn)通過(guò)后根據(jù)目標(biāo)格式調(diào)用對(duì)應(yīng)的導(dǎo)出函數(shù)。import cadquery as cq def generate_and_export(description, output_format, output_path): code call_llm(description) namespace {cq: cq} exec(code, namespace) result namespace[result] if output_format step: cq.exporters.export(result, output_path) elif output_format stl: cq.exporters.export(result, output_path, tolerance0.01) return output_path3.3 參數(shù)計(jì)算以法蘭盤(pán)為例拿一個(gè)具體例子走一遍。描述是“一個(gè)外徑 100 毫米、內(nèi)徑 40 毫米、厚度 15 毫米的法蘭盤(pán)沿直徑 80 毫米的圓周均布 8 個(gè)直徑 8 毫米的螺栓孔”。模型生成的代碼大致是這樣import cadquery as cq result ( cq.Workplane(XY) .circle(50) .circle(20) .extrude(15) .faces(Z) .workplane() .polarArray(40, 0, 360, 8) .hole(8) )這里有幾個(gè)參數(shù)需要驗(yàn)證。外徑 100 對(duì)應(yīng)circle(50)內(nèi)徑 40 對(duì)應(yīng)circle(20)都對(duì)。螺栓孔分布圓直徑 80 對(duì)應(yīng)polarArray的半徑 40也對(duì)。8 個(gè)孔、360 度均布參數(shù)正確??讖?8 對(duì)應(yīng)hole(8)沒(méi)問(wèn)題。執(zhí)行后檢查包圍盒X 和 Y 方向應(yīng)該是 100Z 方向是 15。體積的話外圓柱體積減去內(nèi)孔體積再減去 8 個(gè)螺栓孔的體積。外圓柱 π×502×15 ≈ 117809內(nèi)孔 π×202×15 ≈ 18850每個(gè)螺栓孔 π×42×15 ≈ 7548 個(gè)就是 6032??傮w積約 117809 - 18850 - 6032 92927 立方毫米。實(shí)際跑出來(lái)如果在這個(gè)數(shù)附近說(shuō)明幾何是對(duì)的。3.4 URDF 導(dǎo)出的裝配體處理URDF 這塊單獨(dú)說(shuō)因?yàn)樗葐瘟慵?dǎo)出復(fù)雜。假設(shè)描述是“一個(gè)兩輪差速小車(chē)底盤(pán)是 200x150x50 的盒子左右兩側(cè)各有一個(gè)直徑 60 毫米的輪子”。模型需要生成三個(gè)幾何體底盤(pán)、左輪、右輪。底盤(pán)導(dǎo)出為base_link.stl輪子導(dǎo)出為left_wheel.stl和right_wheel.stl。然后生成 URDF 文件robot namediff_drive link namebase_link visual geometry mesh filenamebase_link.stl/ /geometry /visual /link link nameleft_wheel visual geometry mesh filenameleft_wheel.stl/ /geometry /visual /link joint nameleft_wheel_joint typecontinuous parent linkbase_link/ child linkleft_wheel/ origin xyz0 0.09 -0.02 rpy0 0 0/ axis xyz0 1 0/ /joint /robot這里的關(guān)鍵是origin的 xyz 值——輪子相對(duì)于底盤(pán)中心的位置。底盤(pán)寬 150輪子裝在兩側(cè)所以 Y 方向偏移是 75 加上輪子厚度的一半。這些數(shù)值需要從幾何計(jì)算里提取不能靠模型瞎猜。我的做法是在生成幾何的代碼里同時(shí)輸出每個(gè)零件的位姿然后自動(dòng)填入 URDF。注意URDF 里的 mesh 路徑是相對(duì)于 URDF 文件所在目錄的。如果你把 URDF 和 STL 放在不同文件夾路徑要寫(xiě)對(duì)否則導(dǎo)入 CoppeliaSim 會(huì)報(bào)錯(cuò)。4. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄4.1 代碼能跑但幾何不對(duì)怎么辦這是最高頻的問(wèn)題。模型生成的代碼語(yǔ)法沒(méi)問(wèn)題執(zhí)行也不報(bào)錯(cuò)但出來(lái)的形狀和你想的完全不一樣。常見(jiàn)原因有三個(gè)。第一是布爾運(yùn)算順序錯(cuò)了。比如先打孔再拉伸結(jié)果孔被拉伸操作覆蓋了。CadQuery 是鏈?zhǔn)讲僮黜樞蚝苤匾?。正確的順序是先做主體再在主體上做減材操作。第二是工作平面選錯(cuò)了。workplane()不指定參數(shù)時(shí)默認(rèn)在 XY 平面但如果你在 Z 方向的面操作需要先f(wàn)aces(Z).workplane()把工作平面移到頂面。模型經(jīng)常忘記這一步導(dǎo)致孔打在了錯(cuò)誤的位置。第三是選擇器用錯(cuò)了。faces(Z)選的是 Z 方向最高的面faces(Z)選最低的。如果模型寫(xiě)反了操作就作用在了底面。排查方法是把中間結(jié)果導(dǎo)出看看或者用result.val().Faces()打印所有面的信息。4.2 STEP 導(dǎo)入其他軟件后尺寸不對(duì)十有八九是單位問(wèn)題。STEP 文件頭里有個(gè)單位定義有些內(nèi)核導(dǎo)出時(shí)寫(xiě)的是米導(dǎo)入方按毫米讀尺寸就差一千倍。CadQuery 默認(rèn)導(dǎo)出毫米但如果你在代碼里用了英寸單位比如box(2, 2, 0.5)想表達(dá)英寸導(dǎo)出的 STEP 會(huì)按毫米解釋變成 2 毫米的盒子。解決辦法是在提示詞里強(qiáng)制單位所有尺寸都用毫米并且在代碼里加注釋標(biāo)明。導(dǎo)出后用文本編輯器打開(kāi) STEP 文件看頭部有沒(méi)有MILLI或者M(jìn)ETRE的字樣確認(rèn)單位正確。4.3 URDF 導(dǎo)入 CoppeliaSim 報(bào)錯(cuò)找不到 mesh這個(gè)問(wèn)題的根源通常是路徑。URDF 里的mesh filename...如果是相對(duì)路徑CoppeliaSim 會(huì)相對(duì)于 URDF 文件的位置去找。如果你把 URDF 放在robot/目錄STL 放在robot/meshes/目錄那 filename 應(yīng)該寫(xiě)meshes/base_link.stl。另一個(gè)可能是 STL 文件本身有問(wèn)題。CadQuery 導(dǎo)出的 STL 默認(rèn)是二進(jìn)制格式有些老版本的仿真軟件只認(rèn) ASCII 格式。導(dǎo)出時(shí)加asciiTrue參數(shù)可以解決。cq.exporters.export(result, base_link.stl, asciiTrue)4.4 G-code 生成后機(jī)床報(bào)警G-code 直接控制機(jī)床出問(wèn)題的后果比較嚴(yán)重。最常見(jiàn)的報(bào)警是“坐標(biāo)超程”原因是 G-code 里的坐標(biāo)超出了機(jī)床行程。排查方法是先看 G-code 里的坐標(biāo)范圍和機(jī)床的實(shí)際行程對(duì)比。另一個(gè)常見(jiàn)問(wèn)題是安全高度不夠??焖僖苿?dòng)時(shí)刀具如果沒(méi)抬到安全高度會(huì)撞到工件或者夾具。我的做法是在生成 G-code 時(shí)強(qiáng)制設(shè)置一個(gè)安全高度比如 Z 軸抬到工件最高點(diǎn)以上 10 毫米再移動(dòng)。問(wèn)題現(xiàn)象可能原因排查方法解決措施代碼能跑但形狀不對(duì)布爾順序、工作平面、選擇器導(dǎo)出中間結(jié)果查看調(diào)整操作順序明確工作平面STEP 尺寸差千倍單位不一致查看 STEP 文件頭統(tǒng)一用毫米檢查導(dǎo)出參數(shù)URDF 找不到 mesh路徑錯(cuò)誤、格式不兼容檢查相對(duì)路徑和文件格式修正路徑導(dǎo)出 ASCII STLG-code 機(jī)床報(bào)警坐標(biāo)超程、安全高度不足對(duì)比坐標(biāo)范圍和行程設(shè)置安全高度檢查原點(diǎn)4.5 模型生成的代碼有安全風(fēng)險(xiǎn)這個(gè)必須單獨(dú)提。語(yǔ)言模型生成的代碼是直接exec執(zhí)行的如果模型被誘導(dǎo)生成了惡意代碼比如刪除文件、發(fā)起網(wǎng)絡(luò)請(qǐng)求后果很?chē)?yán)重。我的做法是沙箱執(zhí)行——在受限的命名空間里跑只暴露cadquery和math這些必要的模塊禁用os、sys、subprocess這些危險(xiǎn)模塊。import cadquery as cq import math safe_globals { __builtins__: {}, cq: cq, math: math, } exec(code, safe_globals)這樣即使模型生成了import os; os.system(rm -rf /)這樣的代碼也會(huì)因?yàn)閛s不在命名空間里而報(bào)錯(cuò)。另外執(zhí)行前可以做個(gè)簡(jiǎn)單的靜態(tài)檢查掃描代碼里有沒(méi)有import os、subprocess、open(這些關(guān)鍵詞有的話直接拒絕執(zhí)行。4.6 批量生成時(shí)的效率優(yōu)化如果你要批量生成幾十個(gè)零件每次都調(diào)用模型會(huì)很慢。我的優(yōu)化策略是緩存 模板。對(duì)于結(jié)構(gòu)相似的零件比如一系列不同尺寸的法蘭盤(pán)先生成一個(gè)模板代碼然后只讓模型輸出參數(shù)用參數(shù)替換模板里的占位符。這樣模型只需要生成幾個(gè)數(shù)字速度快很多而且穩(wěn)定性更高。另一個(gè)優(yōu)化是并行執(zhí)行。幾何構(gòu)建是 CPU 密集型的可以用多進(jìn)程并行。但要注意 CadQuery 的 OCCT 內(nèi)核不是線程安全的多線程會(huì)崩必須用多進(jìn)程。from multiprocessing import Pool def process_one(description): code call_llm(description) return execute_and_export(code) with Pool(4) as p: results p.map(process_one, descriptions)5. 進(jìn)階玩法與擴(kuò)展方向5.1 從單零件到裝配體單零件生成跑通之后下一步自然是裝配體。裝配體的難點(diǎn)在于零件之間的約束關(guān)系。文本描述里說(shuō)“軸穿過(guò)孔”模型需要理解軸的外徑和孔的內(nèi)徑是配合關(guān)系軸的位置由孔的位置決定。我的做法是引入一個(gè)中間表示層——用 JSON 描述裝配結(jié)構(gòu)包含零件列表、每個(gè)零件的幾何參數(shù)、以及零件之間的約束同軸、貼合、距離。模型先生成這個(gè) JSON然后我用確定性的代碼把 JSON 翻譯成 CadQuery 的裝配體代碼。這樣把“理解約束”和“生成幾何”分開(kāi)每步都更可控。5.2 參數(shù)化模板庫(kù)的積累用久了會(huì)發(fā)現(xiàn)很多零件是重復(fù)的——法蘭、支架、齒輪、軸承座。與其每次都讓模型從頭生成不如積累一個(gè)模板庫(kù)。每個(gè)模板是一個(gè)參數(shù)化的 CadQuery 函數(shù)模型只需要識(shí)別出“這是法蘭”然后填參數(shù)就行。模板庫(kù)的好處是質(zhì)量穩(wěn)定。模板是人工驗(yàn)證過(guò)的不會(huì)出幾何錯(cuò)誤。模型只負(fù)責(zé)參數(shù)提取這部分它比較擅長(zhǎng)。我現(xiàn)在已經(jīng)攢了二十多個(gè)常用模板覆蓋了大部分日常需求。5.3 和下游工具的聯(lián)動(dòng)生成的 STEP 可以直接導(dǎo)入 FreeCAD 做進(jìn)一步編輯或者導(dǎo)入切片軟件做 3D 打印。URDF 可以導(dǎo)入 CoppeliaSim 做機(jī)器人仿真。G-code 可以發(fā)給 CNC 或者打印機(jī)。整個(gè)鏈路打通之后從一句話到可制造文件最快只要幾十秒。我最近在試的一個(gè)玩法是閉環(huán)迭代——生成幾何后自動(dòng)做仿真分析比如有限元如果應(yīng)力超標(biāo)自動(dòng)調(diào)整參數(shù)重新生成。這個(gè)還在摸索階段但思路是通的。6. 我踩過(guò)的那些坑第一個(gè)坑是過(guò)度信任模型的空間理解。早期我讓模型直接生成復(fù)雜裝配體的代碼結(jié)果零件位置全亂套。后來(lái)改成先生成結(jié)構(gòu)化的參數(shù)描述再用確定性代碼構(gòu)建幾何問(wèn)題就解決了。模型擅長(zhǎng)語(yǔ)義解析和參數(shù)提取不擅長(zhǎng)空間推理這個(gè)分工要明確。第二個(gè)坑是忽略了幾何校驗(yàn)。有次生成了一批零件直接導(dǎo)出 STEP 發(fā)給加工廠結(jié)果對(duì)方反饋說(shuō)文件打不開(kāi)。查了半天發(fā)現(xiàn)是模型生成的代碼里有個(gè)布爾運(yùn)算沒(méi)做成功導(dǎo)出的 STEP 里是兩個(gè)分離的殼。從那以后我加了自動(dòng)校驗(yàn)實(shí)體數(shù)量不對(duì)的直接攔截。第三個(gè)坑是URDF 的坐標(biāo)系約定。不同仿真軟件對(duì)坐標(biāo)系的原點(diǎn)和朝向約定不一樣。CoppeliaSim 默認(rèn) Z 軸向上但有些機(jī)器人框架用 Y 軸向上。生成 URDF 的時(shí)候如果不注意導(dǎo)入后機(jī)器人是躺著的。解決辦法是在 URDF 里顯式定義每個(gè) link 的 origin不要依賴(lài)默認(rèn)值。第四個(gè)坑是G-code 的安全高度。有次生成的 G-code 里快速移動(dòng)沒(méi)抬刀模擬的時(shí)候直接撞工件。雖然只是模擬沒(méi)造成實(shí)際損失但嚇出一身冷汗?,F(xiàn)在我的 G-code 生成器里強(qiáng)制加安全高度移動(dòng)前先抬到工件最高點(diǎn)以上。7. 一些實(shí)用的參數(shù)速查參數(shù)常用值說(shuō)明STL 導(dǎo)出精度0.01-0.05 mm值越小越精細(xì)文件越大STEP 單位毫米導(dǎo)出前確認(rèn)避免千倍誤差URDF mesh 路徑相對(duì)路徑相對(duì)于 URDF 文件所在目錄G-code 安全高度工件最高點(diǎn)10mm快速移動(dòng)前必須抬到此高度模型 temperature0.1-0.3越低越穩(wěn)定越高越有創(chuàng)意沙箱白名單cq, math只暴露必要模塊這套流程我跑了小半年從最初的一句話生成一個(gè)歪歪扭扭的盒子到現(xiàn)在能穩(wěn)定輸出可用的 STEP 和 URDF中間踩的坑基本都在這了。核心體會(huì)就一條別指望模型一步到位把任務(wù)拆細(xì)每步都加校驗(yàn)比什么都強(qiáng)。模型負(fù)責(zé)它擅長(zhǎng)的語(yǔ)義理解幾何構(gòu)建交給確定性的代碼這個(gè)分工是整套方案能跑通的關(guān)鍵。