戰(zhàn):從自然語言到STEP/URDF/G-code的分層轉(zhuǎn)換與避坑指南)
1. 從一句話到三維模型text-to-cad 到底在解決什么問題第一次聽到 text-to-cad 這個(gè)詞我腦子里蹦出來的畫面是對(duì)著電腦敲一行字比如“一個(gè) 80x40x20 的鋁合金外殼四角帶 M4 沉頭孔壁厚 3 毫米”然后軟件啪一下把 STEP 文件吐出來。這個(gè)畫面在幾年前還屬于科幻范疇但現(xiàn)在已經(jīng)有一批工具和方案在往這個(gè)方向靠了。text-to-cad 本質(zhì)上是一類把自然語言描述轉(zhuǎn)換成 CAD 可識(shí)別幾何模型的技術(shù)路線它的輸出通常不是某個(gè)私有格式而是 STEP、URDF、G-code 這類通用性強(qiáng)的中間格式。為什么是這幾個(gè)格式因?yàn)?STEP 是工業(yè)界公認(rèn)的實(shí)體模型交換標(biāo)準(zhǔn)URDF 是機(jī)器人領(lǐng)域描述連桿和關(guān)節(jié)的通用語言G-code 則是從模型走向加工的最后一步。換句話說text-to-cad 想打通的是“語言描述 → 幾何定義 → 可制造/可仿真文件”這條鏈路。這件事的價(jià)值在哪兒我舉個(gè)自己踩過的場景。做非標(biāo)設(shè)備的時(shí)候經(jīng)常需要根據(jù)客戶口頭描述快速出一個(gè)初步模型去對(duì)尺寸。傳統(tǒng)流程是聽懂需求 → 打開 CAD 軟件 → 草圖 → 拉伸 → 打孔 → 導(dǎo)出。一套下來熟練工也得十幾分鐘而且中間任何一處尺寸理解錯(cuò)了返工成本很高。text-to-cad 的思路是把“草圖→拉伸→打孔”這些重復(fù)性勞動(dòng)交給程序人只負(fù)責(zé)用語言把關(guān)鍵約束說清楚。它解決的不是“替代設(shè)計(jì)師”而是“把設(shè)計(jì)師從重復(fù)建模里撈出來”。適合關(guān)注這個(gè)方向的人其實(shí)挺雜的做機(jī)械設(shè)計(jì)的想提效做機(jī)器人仿真的想快速生成 URDF做 3D 打印的想從文字直接出 G-code甚至做教育的想讓學(xué)生用自然語言理解幾何約束。不同背景的人關(guān)注點(diǎn)不一樣但核心訴求是一致的——降低從想法到模型的門檻。我在這篇文章里會(huì)把這套東西拆開講整體設(shè)計(jì)思路怎么定、核心格式之間怎么轉(zhuǎn)換、實(shí)操環(huán)節(jié)怎么落地、以及我實(shí)際折騰過程中遇到的一堆坑。內(nèi)容會(huì)涉及 STEP、URDF、G-code 的具體處理方式也會(huì)給一些可以直接抄的參數(shù)和代碼片段。不管你是剛接觸 CAD 二次開發(fā)還是已經(jīng)在做參數(shù)化建模想往智能化靠應(yīng)該都能找到能用的東西。2. 整體設(shè)計(jì)思路為什么不是“直接生成”而是“分層轉(zhuǎn)換”2.1 核心架構(gòu)的選型邏輯很多人一開始會(huì)想能不能訓(xùn)練一個(gè)模型輸入文字直接輸出 STEP 文件我試過類似思路結(jié)論是現(xiàn)階段不現(xiàn)實(shí)。原因在于 STEP 文件本質(zhì)上是一堆 NURBS 曲面和拓?fù)潢P(guān)系的集合它的數(shù)據(jù)結(jié)構(gòu)極其嚴(yán)謹(jǐn)一個(gè)實(shí)體的邊界表示BRep要求面、邊、點(diǎn)之間的連接關(guān)系完全自洽。讓語言模型直接生成這種結(jié)構(gòu)化數(shù)據(jù)相當(dāng)于讓它逐字節(jié)寫一個(gè)二進(jìn)制文件錯(cuò)誤率會(huì)高到?jīng)]法用。所以目前靠譜的方案都是分層的自然語言 → 中間參數(shù)化表示 → 幾何內(nèi)核操作 → 目標(biāo)格式導(dǎo)出。這個(gè)中間層可以是 JSON 描述的參數(shù)表也可以是 Python 腳本還可以是 OpenSCAD 那種聲明式代碼。我自己的方案選的是“自然語言 → 結(jié)構(gòu)化參數(shù) JSON → CadQuery/OpenCASCADE 內(nèi)核 → STEP/STL → 后處理”。為什么選 CadQuery因?yàn)樗?OpenCASCADE而 OpenCASCADE 是工業(yè)級(jí)幾何內(nèi)核對(duì) STEP 的支持非常成熟。另一個(gè)原因是 CadQuery 的 API 是鏈?zhǔn)降膶懫饋斫咏匀徽Z言的邏輯順序比如Workplane().box(80,40,20).faces(Z).workplane().hole(4)這種表達(dá)很容易和語言模型輸出的結(jié)構(gòu)對(duì)應(yīng)上。相比之下直接調(diào) OpenCASCADE 的 C 接口學(xué)習(xí)曲線太陡用 FreeCAD 的腳本又受限于它的對(duì)象模型。CadQuery 在靈活性和穩(wěn)定性之間取了一個(gè)不錯(cuò)的平衡點(diǎn)。這里有個(gè)關(guān)鍵決策點(diǎn)中間表示到底用“參數(shù)表”還是“代碼”。參數(shù)表的好處是安全模型只能從預(yù)定義的模板里選參數(shù)不會(huì)生成亂七八糟的幾何壞處是靈活性差遇到模板沒覆蓋的形狀就抓瞎。代碼的好處是靈活理論上能表達(dá)任意幾何壞處是語言模型生成的代碼可能跑不通甚至可能寫出危險(xiǎn)操作。我的做法是混合常見形狀走參數(shù)表模板復(fù)雜形狀走代碼生成但代碼在執(zhí)行前會(huì)經(jīng)過一層 AST 靜態(tài)檢查禁止文件讀寫和網(wǎng)絡(luò)調(diào)用。這個(gè)檢查步驟很關(guān)鍵我后面在避坑部分會(huì)詳細(xì)說。2.2 格式轉(zhuǎn)換鏈的設(shè)計(jì)與取舍從幾何內(nèi)核出來之后往哪個(gè)格式走取決于下游用途。STEP 適合做精確的實(shí)體交換它的優(yōu)勢(shì)是保留了完整的 BRep 信息任何主流 CAD 軟件都能讀而且精度無損。但 STEP 有個(gè)問題它不包含裝配約束和運(yùn)動(dòng)學(xué)信息你拿到的是一個(gè)靜態(tài)的幾何體。如果下游是機(jī)器人仿真就需要 URDF。URDF 描述的是連桿link和關(guān)節(jié)joint的樹狀結(jié)構(gòu)每個(gè) link 有自己的幾何形狀和慣性參數(shù)每個(gè) joint 有類型旋轉(zhuǎn)、平移、固定和軸向。從 STEP 到 URDF 不是簡單的格式轉(zhuǎn)換而是要把一個(gè)整體幾何拆成多個(gè) link再定義它們之間的關(guān)節(jié)關(guān)系。這一步目前沒有全自動(dòng)的可靠方案我的做法是在參數(shù) JSON 里就顯式定義好 link 和 joint 的結(jié)構(gòu)生成 STEP 的同時(shí)也生成 URDF兩者共享同一套尺寸參數(shù)。G-code 則是另一條路。它不關(guān)心幾何的精確表示只關(guān)心刀具軌跡。從模型到 G-code 通常要經(jīng)過切片3D 打印或 CAM 刀路規(guī)劃減材加工。text-to-cad 在這個(gè)環(huán)節(jié)的價(jià)值是語言描述里可以直接包含加工參數(shù)比如“層高 0.2填充 20%PLA 材料”這些參數(shù)和幾何參數(shù)一起進(jìn)入 JSON最后喂給切片引擎。我實(shí)測(cè)下來用 CadQuery 生成 STL再用 CuraEngine 的命令行模式切片整條鏈路可以完全腳本化。但要注意G-code 和 STEP 的精度要求完全不同STL 的網(wǎng)格精度如果設(shè)得太低薄壁特征會(huì)丟失打出來就是殘次品。目標(biāo)格式核心用途關(guān)鍵優(yōu)勢(shì)主要限制STEP精確實(shí)體交換無損 BRep通用性強(qiáng)無裝配運(yùn)動(dòng)信息URDF機(jī)器人仿真含關(guān)節(jié)與慣性需手動(dòng)拆分 linkG-code加工制造直接驅(qū)動(dòng)機(jī)床依賴切片/CAM 參數(shù)STL3D 打印/可視化簡單通用網(wǎng)格精度有損2.3 語言理解層的設(shè)計(jì)邊界語言理解這塊我的建議是不要追求“大而全”。很多人一上來就想讓系統(tǒng)理解“一個(gè)復(fù)雜的機(jī)械臂”結(jié)果發(fā)現(xiàn)模型根本不知道從哪兒下手。正確的做法是限定領(lǐng)域詞匯表。比如你做的是板金件那就把“折彎”“沖孔”“沉頭”“翻邊”這些詞定義清楚每個(gè)詞對(duì)應(yīng)一組幾何操作和默認(rèn)參數(shù)。語言模型的任務(wù)只是把用戶的話映射到這些預(yù)定義操作上而不是自由發(fā)揮。我試過用純 prompt 讓模型輸出 CadQuery 代碼結(jié)果它經(jīng)常發(fā)明一些不存在的 API或者把hole和cboreHole搞混。后來改成“先分類到操作模板再填參數(shù)”穩(wěn)定性大幅提升。另一個(gè)邊界是尺寸推理。用戶說“一個(gè)差不多手掌大的盒子”這個(gè)“手掌大”到底是多大我的處理方式是維護(hù)一個(gè)常用尺寸映射表比如“手掌大”映射到 100mm 左右“拇指粗”映射到 20mm同時(shí)在輸出里明確標(biāo)注“按 100mm 估算如需精確請(qǐng)指定數(shù)值”。這樣既給了結(jié)果又留了修正余地。千萬不要讓模型自己瞎猜一個(gè)精確到小數(shù)點(diǎn)后三位的數(shù)字那是在制造虛假精度。3. 核心細(xì)節(jié)解析STEP、URDF、G-code 的處理要點(diǎn)3.1 STEP 文件的生成與校驗(yàn)用 CadQuery 導(dǎo)出 STEP 就一行代碼cq.exporters.export(result, output.step)。但這一行背后有幾個(gè)坑。第一個(gè)坑是單位。CadQuery 默認(rèn)單位是毫米但 STEP 文件本身不強(qiáng)制單位有些軟件讀的時(shí)候會(huì)按英寸解釋。我遇到過導(dǎo)出的模型在另一個(gè)軟件里大了 25.4 倍就是因?yàn)閱挝粵]對(duì)齊。解決辦法是在導(dǎo)出前顯式設(shè)置cq.Unit或者在文件頭里寫入單位聲明。第二個(gè)坑是實(shí)體有效性。如果幾何操作產(chǎn)生了自相交或零厚度面STEP 文件可能能寫出來但讀的時(shí)候會(huì)報(bào)錯(cuò)。我的習(xí)慣是在導(dǎo)出前跑一遍result.val().isValid()不通過就回退到上一個(gè)有效狀態(tài)。還有一個(gè)實(shí)際問題是文件大小。一個(gè)帶很多小孔和圓角的零件STEP 文件可能幾十兆。如果只是做可視化沒必要用 STEP轉(zhuǎn)成 STL 或 glTF 更合適。我一般會(huì)在 JSON 里加一個(gè)output_format字段根據(jù)用途自動(dòng)選格式。如果是給下游 CAD 做進(jìn)一步編輯必須 STEP如果是給網(wǎng)頁預(yù)覽glTF 足夠如果是 3D 打印STL 加 G-code。import cadquery as cq # 從參數(shù)構(gòu)建模型 length, width, height 80.0, 40.0, 20.0 hole_dia 4.0 result ( cq.Workplane(XY) .box(length, width, height) .faces(Z) .workplane() .rect(length - 10, width - 10, forConstructionTrue) .vertices() .hole(hole_dia) ) # 校驗(yàn)實(shí)體有效性 if not result.val().isValid(): raise ValueError(生成的實(shí)體無效請(qǐng)檢查參數(shù)) # 導(dǎo)出 STEP cq.exporters.export(result, bracket.step)這段代碼里forConstructionTrue是個(gè)容易忽略的點(diǎn)。它表示這個(gè)矩形只用來定位頂點(diǎn)不參與實(shí)際幾何。如果不加這個(gè)參數(shù)矩形會(huì)被當(dāng)成實(shí)體的一部分切出來結(jié)果就完全不對(duì)了。這種細(xì)節(jié)在文檔里往往一筆帶過但實(shí)際用的時(shí)候不知道就會(huì)卡很久。3.2 URDF 的關(guān)節(jié)定義與慣性參數(shù)URDF 的難點(diǎn)不在幾何而在關(guān)節(jié)和慣性。幾何部分可以直接從 STEP 或 STL 引用 mesh 文件但關(guān)節(jié)類型、軸向、限位這些必須顯式定義。我見過很多人把 URDF 寫成了一堆固定關(guān)節(jié)的集合結(jié)果導(dǎo)入仿真環(huán)境后機(jī)器人根本動(dòng)不了。正確的做法是先想清楚運(yùn)動(dòng)鏈哪個(gè) link 是父、哪個(gè)是子、關(guān)節(jié)繞哪個(gè)軸轉(zhuǎn)、轉(zhuǎn)多少度。這些信息在 text-to-cad 的 JSON 里就應(yīng)該定義好而不是等到生成 URDF 時(shí)再補(bǔ)。慣性參數(shù)是另一個(gè)大坑。URDF 要求每個(gè) link 有質(zhì)量和慣性矩陣。如果隨便填一個(gè)值仿真時(shí)會(huì)出現(xiàn)奇怪的抖動(dòng)或者直接飛出去。我的做法是用幾何體積乘以材料密度估算質(zhì)量慣性矩陣用近似公式算。比如一個(gè)長方體繞中心軸的慣性矩是m*(w^2h^2)/12。雖然不精確但比瞎填強(qiáng)得多。如果對(duì)精度要求高可以用 FreeCAD 或 Blender 算完再填進(jìn)去。link namebase_link visual geometry mesh filenamebase.stl scale0.001 0.001 0.001/ /geometry /visual collision geometry mesh filenamebase.stl scale0.001 0.001 0.001/ /geometry /collision inertial mass value0.5/ inertia ixx0.001 ixy0 ixz0 iyy0.001 iyz0 izz0.001/ /inertial /link注意scale那個(gè) 0.001。STL 通常以毫米為單位導(dǎo)出但 URDF 的標(biāo)準(zhǔn)單位是米所以必須縮放。這個(gè)坑我踩過不止一次導(dǎo)入后模型大得像個(gè)房子排查半天才發(fā)現(xiàn)是單位問題。3.3 G-code 的切片參數(shù)與路徑規(guī)劃從模型到 G-code核心是切片參數(shù)。層高、壁厚、填充密度、打印速度、溫度這些參數(shù)直接決定成品質(zhì)量。text-to-cad 在這個(gè)環(huán)節(jié)的價(jià)值是把語言描述里的加工意圖翻譯成切片參數(shù)。比如用戶說“要結(jié)實(shí)一點(diǎn)”那就把填充密度從 20% 提到 40%壁厚從 2 層加到 3 層。說“表面要光滑”那就把層高降到 0.1mm。這些映射關(guān)系需要事先定義好不能指望切片軟件自己理解。我用的是 CuraEngine 的命令行模式因?yàn)樗梢酝耆_本化不需要打開圖形界面。調(diào)用方式大概是CuraEngine slice -j fdmprinter.def.json -l model.stl -o output.gcode -s layer_height0.2 -s infill_sparse_density20 -s wall_line_count3這里-j指定打印機(jī)定義文件-l指定輸入模型-s覆蓋具體參數(shù)。實(shí)測(cè)下來這套流程跑通之后從文字到 G-code 可以做到全自動(dòng)。但有個(gè)前提模型必須是流形manifold的也就是沒有破面、沒有自相交。STL 如果是從有問題的 STEP 轉(zhuǎn)過來的切片時(shí)會(huì)出現(xiàn)空洞或者錯(cuò)層。所以我在導(dǎo)出 STL 之前一定會(huì)做一次網(wǎng)格修復(fù)用trimesh或者admesh都行。4. 實(shí)操過程從一句話到可加工文件的完整鏈路4.1 環(huán)境搭建與依賴安裝先把環(huán)境說清楚。我用的主力是 Python 3.10CadQuery 2.4CuraEngine 5.xtrimesh 3.x。CadQuery 的安裝推薦用 conda因?yàn)樗囊蕾嚴(yán)镉?OpenCASCADE 的二進(jìn)制包pip 裝有時(shí)候會(huì)缺庫。conda create -n text2cad python3.10 conda activate text2cad conda install -c conda-forge cadquery pip install trimesh urdfpyCuraEngine 需要單獨(dú)下載編譯好的二進(jìn)制放到 PATH 里就行。如果你用的是 Windows注意把它的路徑加到系統(tǒng)環(huán)境變量不然命令行調(diào)用會(huì)找不到。我一開始在 Windows 上折騰了半天后來發(fā)現(xiàn)是路徑里有空格導(dǎo)致解析出錯(cuò)換到?jīng)]有空格的目錄就好了。語言理解層我用的是本地部署的小模型加規(guī)則引擎不依賴外部接口。這樣做的好處是響應(yīng)快、數(shù)據(jù)不出本地壞處是理解能力有限。如果你的場景詞匯比較固定規(guī)則引擎加小模型完全夠用。如果場景很開放那可能需要更大的模型但那就涉及到算力和部署成本的問題了得自己權(quán)衡。4.2 參數(shù) JSON 的結(jié)構(gòu)設(shè)計(jì)整個(gè)鏈路的核心是那個(gè)參數(shù) JSON。它既是語言理解的輸出也是幾何生成的輸入。我的結(jié)構(gòu)大概長這樣{ part_name: mounting_bracket, units: mm, geometry: { type: box_with_holes, length: 80, width: 40, height: 20, holes: [ {position: corners, diameter: 4, depth: through} ] }, material: aluminum_6061, output: [step, stl], manufacturing: { process: cnc, tolerance: 0.1 } }這個(gè)結(jié)構(gòu)的好處是清晰、可校驗(yàn)。geometry.type決定了用哪個(gè)模板holes數(shù)組描述了孔的位置和尺寸output決定導(dǎo)出哪些格式。語言理解層的任務(wù)就是把“一個(gè) 80 乘 40 乘 20 的鋁板四角打 4 毫米通孔”映射成這個(gè) JSON。映射規(guī)則可以寫得很細(xì)比如“通孔”對(duì)應(yīng)depth: through“沉頭”對(duì)應(yīng)type: counterbore并附帶沉頭直徑和深度。我建議在 JSON 里加一個(gè)confidence字段記錄每個(gè)參數(shù)的可信度。如果某個(gè)尺寸是從模糊描述里猜的就標(biāo)低一點(diǎn)生成后在界面上高亮提示用戶確認(rèn)。這個(gè)做法在實(shí)際使用中能減少很多“我以為你懂我意思”的扯皮。4.3 幾何生成與格式導(dǎo)出的完整腳本把上面的東西串起來主流程大概是這樣import json import cadquery as cq from cadquery import exporters def build_from_json(params): geo params[geometry] if geo[type] box_with_holes: result cq.Workplane(XY).box(geo[length], geo[width], geo[height]) if geo.get(holes): result ( result.faces(Z).workplane() .rect(geo[length] - 10, geo[width] - 10, forConstructionTrue) .vertices() .hole(geo[holes][0][diameter]) ) else: raise ValueError(f不支持的幾何類型: {geo[type]}) if not result.val().isValid(): raise ValueError(幾何無效) return result def export_all(model, params, basename): outputs params.get(output, [step]) if step in outputs: exporters.export(model, f{basename}.step) if stl in outputs: exporters.export(model, f{basename}.stl, tolerance0.01) if urdf in outputs: generate_urdf(model, params, f{basename}.urdf) if gcode in outputs: slice_to_gcode(f{basename}.stl, params, f{basename}.gcode)這里tolerance0.01是 STL 的網(wǎng)格精度單位是毫米。這個(gè)值越小網(wǎng)格越細(xì)文件越大。對(duì)于大多數(shù) 3D 打印件0.01 到 0.05 之間夠用了。如果零件有很小的特征比如 0.5mm 的細(xì)縫那得設(shè)到 0.005 以下不然縫就糊住了。4.4 從 STL 到 G-code 的切片實(shí)操切片這一步我單獨(dú)拎出來說因?yàn)樗婕暗膮?shù)最多也最容易出問題。以 CuraEngine 為例一個(gè)典型的調(diào)用需要指定打印機(jī)定義、材料定義和一堆覆蓋參數(shù)。我一般會(huì)把常用配置寫成 JSON 文件調(diào)用時(shí)直接引用。CuraEngine slice \ -j fdmprinter.def.json \ -l bracket.stl \ -o bracket.gcode \ -s layer_height0.2 \ -s wall_line_count3 \ -s infill_sparse_density20 \ -s material_print_temperature210 \ -s material_bed_temperature60 \ -s speed_print50跑完之后一定要檢查 G-code 的開頭和結(jié)尾。開頭應(yīng)該有歸零和預(yù)熱指令結(jié)尾應(yīng)該有回抽和關(guān)機(jī)指令。如果這些不對(duì)打印機(jī)可能直接撞頭或者堵嘴。我習(xí)慣用gcode-parser之類的工具快速掃一遍確認(rèn)沒有異常指令。還有一個(gè)實(shí)際經(jīng)驗(yàn)不同品牌的打印機(jī)對(duì) G-code 的方言支持不一樣。比如有的機(jī)器用M104設(shè)溫度有的用M109并等待。如果你的 G-code 是給特定機(jī)器用的最好在切片配置里選對(duì)機(jī)型或者手動(dòng)改一下起始和結(jié)束代碼。這個(gè)沒有通用解只能針對(duì)具體設(shè)備調(diào)。5. 常見問題與排查技巧實(shí)錄5.1 幾何生成階段的典型報(bào)錯(cuò)問題一實(shí)體無效isValid 返回 False。最常見的原因是布爾運(yùn)算產(chǎn)生了零厚度面或者自相交。比如在一個(gè)面上打孔孔的位置正好在邊緣上切出來的面就退化了。解決辦法是調(diào)整孔的位置留出至少一個(gè)壁厚的余量。如果必須貼邊那就把孔改成缺口用切除而不是打孔。問題二圓角失敗。對(duì)一條邊做圓角如果相鄰面的夾角太小或者邊長不夠圓角會(huì)失敗。CadQuery 的fillet會(huì)直接拋異常。我的做法是先用edges()選中要倒角的邊檢查它的長度是否大于圓角半徑的兩倍不滿足就跳過或者減小半徑。問題三導(dǎo)出 STEP 后文件打不開。十有八九是單位或者編碼問題。先確認(rèn)導(dǎo)出時(shí)單位設(shè)置正確再檢查文件路徑里有沒有中文或特殊字符。有些老版本的 CAD 軟件對(duì) UTF-8 路徑支持不好換成純英文路徑就能解決。5.2 URDF 導(dǎo)入仿真環(huán)境的常見坑URDF 導(dǎo)入 CoppeliaSim 或者 Gazebo 時(shí)最常見的問題是 mesh 路徑不對(duì)。URDF 里的filename可以是相對(duì)路徑也可以是絕對(duì)路徑但不同仿真器對(duì)相對(duì)路徑的解析基準(zhǔn)不一樣。CoppeliaSim 通常相對(duì)于 URDF 文件所在目錄Gazebo 則相對(duì)于某個(gè)模型包路徑。我的做法是統(tǒng)一用package://前綴然后在仿真環(huán)境里配置好包路徑映射。如果嫌麻煩直接用絕對(duì)路徑也行但換機(jī)器就得改。另一個(gè)坑是關(guān)節(jié)軸向。URDF 里關(guān)節(jié)的axis是相對(duì)于 joint 坐標(biāo)系的不是相對(duì)于世界坐標(biāo)系。如果你定義了一個(gè)繞 Z 軸旋轉(zhuǎn)的關(guān)節(jié)但 joint 坐標(biāo)系本身被旋轉(zhuǎn)過那實(shí)際轉(zhuǎn)軸就不是世界 Z 軸了。這個(gè)在簡單模型里不容易發(fā)現(xiàn)一旦模型復(fù)雜起來運(yùn)動(dòng)就會(huì)變得很奇怪。排查方法是把 URDF 導(dǎo)入后手動(dòng)拖一下關(guān)節(jié)看運(yùn)動(dòng)方向是否符合預(yù)期。5.3 G-code 打印失敗的排查清單現(xiàn)象可能原因排查方法第一層不粘平臺(tái)溫度低/調(diào)平不準(zhǔn)提高 bed 溫度重新調(diào)平中途斷層耗材卡住/溫度波動(dòng)檢查送絲機(jī)構(gòu)穩(wěn)定熱端溫度尺寸偏大材料收縮/步進(jìn)校準(zhǔn)校準(zhǔn) E 步調(diào)整收縮補(bǔ)償表面粗糙層高太大/速度太快降低層高和打印速度孔洞堵死填充重疊/網(wǎng)格問題檢查 STL 流形性調(diào)整填充重疊率這張表是我自己打印失敗多次之后總結(jié)的基本上覆蓋了八成以上的常見問題。其中“孔洞堵死”這個(gè)特別隱蔽因?yàn)槟P涂雌饋頉]問題切片預(yù)覽也正常但打出來孔就是實(shí)的。后來發(fā)現(xiàn)是 STL 網(wǎng)格在孔的位置有微小破面切片引擎把孔當(dāng)成了實(shí)體。用trimesh的repair功能修一下就好了。5.4 語言理解層的避坑心得語言理解這塊最大的坑是“過度自信”。模型對(duì)模糊描述會(huì)給出一個(gè)看起來很確定的答案但實(shí)際上它是在猜。比如“打幾個(gè)孔”它可能默認(rèn)打四個(gè)但用戶心里想的是六個(gè)。我的做法是在輸出 JSON 里加一個(gè)assumptions數(shù)組把所有猜測(cè)都列出來生成后顯示給用戶確認(rèn)。這個(gè)做法看起來麻煩但比事后返工強(qiáng)得多。另一個(gè)坑是單位混用。用戶可能說“長 8 厘米”也可能說“長 80 毫米”還可能說“長 8 公分”。這些都得映射到統(tǒng)一的毫米單位。我維護(hù)了一個(gè)單位映射表覆蓋厘米、毫米、米、英寸、公分這些常見說法。英寸轉(zhuǎn)毫米是 25.4這個(gè)系數(shù)一定要記準(zhǔn)不然差之毫厘謬以千里。6. 工具選型與擴(kuò)展思路6.1 幾何內(nèi)核的對(duì)比與選擇OpenCASCADE 是功能最全的但學(xué)習(xí)曲線陡。CadQuery 封裝了它用起來舒服很多。FreeCAD 的 Part 模塊也是基于 OpenCASCADE但它的腳本接口更偏向于操作文檔對(duì)象不如 CadQuery 直接。如果你要做的是建筑或土木方向的模型那可能更適合用 Blender 的腳本或者 IfcOpenShell。選哪個(gè)內(nèi)核取決于你的幾何復(fù)雜度和團(tuán)隊(duì)的技術(shù)棧。我的建議是機(jī)械零件用 CadQuery建筑用 IfcOpenShell可視化用 trimesh 或 Blender。6.2 從 text-to-cad 到 text-to-cam 的延伸text-to-cad 的下一步自然是 text-to-cam。既然語言能描述幾何那也能描述加工策略。比如“先粗銑再精銑粗銑留 0.5 余量精銑轉(zhuǎn)速 8000”這些完全可以結(jié)構(gòu)化后喂給 CAM 引擎。FreeCAD 的 Path 工作臺(tái)支持腳本化生成刀路理論上可以和 text-to-cad 的 JSON 對(duì)接。我試過一個(gè)簡單的例子從 JSON 讀取零件尺寸和加工參數(shù)自動(dòng)生成一個(gè)平面銑削的 G-code。雖然離實(shí)用還有距離但方向是通的。6.3 批量處理與自動(dòng)化集成如果你有一堆相似的零件要處理text-to-cad 的批量能力就體現(xiàn)出來了。把每個(gè)零件的描述寫成一行文字批量轉(zhuǎn)成 JSON再批量生成模型和 G-code。我用這個(gè)方式處理過一批支架類零件二十多個(gè)變體從描述到 G-code 全部自動(dòng)完成只花了不到十分鐘。如果手動(dòng)建模一個(gè)下午都搞不定。批量處理的關(guān)鍵是模板要足夠通用參數(shù)要足夠靈活。如果每個(gè)零件都要改代碼那就失去自動(dòng)化的意義了。7. 我個(gè)人在實(shí)際操作中的幾點(diǎn)體會(huì)這套東西我斷斷續(xù)續(xù)折騰了大半年最大的體會(huì)是不要追求一步到位。一開始我想做一個(gè)“萬能”的 text-to-cad 系統(tǒng)什么都能生成結(jié)果什么都做不好。后來把范圍縮到“板類零件帶孔”反而穩(wěn)定了。先在一個(gè)窄領(lǐng)域里做到能用再慢慢擴(kuò)展比一開始就鋪大攤子靠譜得多。第二個(gè)體會(huì)是校驗(yàn)比生成更重要。生成一個(gè)模型不難難的是保證它是對(duì)的。我現(xiàn)在花在校驗(yàn)上的時(shí)間比生成還多實(shí)體有效性檢查、尺寸范圍檢查、單位一致性檢查、網(wǎng)格流形性檢查。這些檢查看起來繁瑣但能擋住絕大多數(shù)低級(jí)錯(cuò)誤。沒有校驗(yàn)的自動(dòng)化就是在批量制造垃圾。第三個(gè)體會(huì)是保留人工干預(yù)的入口。全自動(dòng)聽起來很酷但實(shí)際用的時(shí)候用戶總會(huì)有一些系統(tǒng)理解不了的需求。這時(shí)候如果能方便地手動(dòng)改參數(shù)、改代碼體驗(yàn)會(huì)好很多。我的做法是生成的 JSON 和 Python 腳本都保留下來用戶可以直接編輯后重新生成。這樣系統(tǒng)是“輔助”而不是“替代”接受度會(huì)高很多。最后分享一個(gè)小技巧如果你也在做類似的東西建議把每次生成的輸入描述、中間 JSON、輸出文件和校驗(yàn)結(jié)果都存下來。攢夠幾百條之后你會(huì)發(fā)現(xiàn)哪些描述容易理解錯(cuò)、哪些參數(shù)經(jīng)常需要調(diào)整。這些數(shù)據(jù)是優(yōu)化系統(tǒng)的金礦比拍腦袋想規(guī)則有用得多。我現(xiàn)在就有一個(gè)這樣的日志庫每次遇到新的描述方式就加一條慢慢地把覆蓋率提上去了。