☰
text-to-cad 实战:从自然语言到 STEP 与 URDF 的几何生成链路
2026/10/8 5:20:03 网站建设 项目流程

1. 从一句话到三维模型:text-to-cad 到底在解决什么问题

第一次听到 "text-to-cad" 这个词,很多人脑子里浮现的画面大概是:对着电脑说一句"给我画个法兰盘",屏幕上就自动长出一个带螺栓孔的零件。这个想象不算离谱,但真正落地的时候,它解决的问题比"省几下鼠标"要深刻得多。

传统 CAD 工作流的起点是人的手。你得先想清楚尺寸、特征、约束关系,然后在 SolidWorks、Fusion 360、中望 CAD 这类软件里一步步拉伸、旋转、倒角。一个中等复杂度的零件,熟练工程师也要花上几十分钟到几个小时。而 text-to-cad 想做的事情,是把"自然语言描述"直接映射成"可用的几何模型文件",中间那些重复性的建模动作交给程序去完成。

它真正服务的场景其实很具体。比如参数化零件库的批量生成——你需要 200 个不同孔径、不同厚度的垫片,与其一个个画,不如写一段描述让程序批量吐出来。再比如教学场景,学生用文字描述一个几何体,系统立刻给出三维结果,反馈闭环极短。还有快速原型阶段,工程师脑子里有个模糊构想,先用文字把它"倒"成一个粗糙模型看看比例对不对,比直接开软件建模快得多。

这里必须先把一个概念掰清楚:text-to-cad 输出的"CAD"到底是什么格式。这直接决定了它能干什么、不能干什么。常见的输出目标有这么几类:

输出格式本质典型用途是否可直接编辑
STEP (.step/.stp)边界表示(B-rep)实体模型跨软件交换、CNC 加工是,主流 CAD 均可导入
STL (.stl)三角网格3D 打印、快速预览否,只能当网格处理
URDF机器人描述文件(含几何+关节)机器人仿真、运动学部分,偏配置
G-code加工路径指令数控机床、3D 打印执行否,是执行指令
SCAD/脚本参数化源码程序化建模是,改代码即改模型

看懂这张表,你就明白为什么 text-to-cad 不是一个单一功能,而是一条从"语言"到"多种下游产物"的转换链。STEP 是给工程师和加工用的,STL 是给打印机用的,URDF 是给机器人仿真用的,G-code 是给机床用的。同一个文字描述,可能同时要吐出好几种格式。

我个人的判断是:text-to-cad 短期内不会取代 CAD 工程师,但它会极大改变"建模的入口"。以前入口是软件界面,以后入口可能是一段描述、一个表格、甚至一句语音。真正值钱的能力,从"会点按钮"变成了"能把需求描述清楚,并且知道描述背后的几何约束"。

2. 拆解 text-to-cad 的技术链路:语言是怎么变成几何的

2.1 大模型负责"翻译",几何内核负责"落地"

很多人误以为 text-to-cad 是"AI 直接画出模型"。实际上主流做法是两段式:第一段把自然语言翻译成一种中间表示,第二段用几何内核把中间表示变成真正的实体。

中间表示最常见的是代码。比如 OpenSCAD 的脚本语言,或者 CadQuery 的 Python API。为什么选代码而不是直接生成网格?因为代码是可参数化、可复用、可版本管理的。你让模型生成一段 CadQuery 代码,改个参数就能重新生成,这比生成一个死网格有价值得多。

import cadquery as cq # 一个带中心孔和四个角孔的矩形板 result = ( cq.Workplane("XY") .box(80, 60, 8) # 长80 宽60 厚8 .faces(">Z").workplane() .hole(20) # 中心通孔直径20 .rect(60, 40, forConstruction=True) .vertices() .hole(6) # 四角孔直径6 ) cq.exporters.export(result, "plate.step")

上面这段代码就是典型的"中间表示"。大模型的任务,是把"一块 80x60x8 的板,中间一个 20 的孔,四角各一个 6 的孔"翻译成这段代码。翻译对了,几何内核(这里是 OpenCASCADE)就能算出精确的 B-rep 实体,导出成 STEP。

2.2 为什么几何内核不能省

有人会问:既然大模型这么强,直接让它输出 STL 网格不行吗?不行,原因有两个。

第一,网格没有"特征"概念。STL 里只有一堆三角形,你没法告诉它"把这个孔改成 25"。而 B-rep 实体保留了面、边、孔这些拓扑信息,改参数就是改参数。

第二,精度问题。网格是近似,曲面被切成小三角,圆孔变成多边形。对于 3D 打印勉强够用,对于要上机床加工的零件,公差根本过不了关。STEP 走的是精确数学曲面,这才是工程可用的基础。

所以一条靠谱的 text-to-cad 链路,必然是"语言模型 + 几何内核"的组合。语言模型负责理解意图、生成参数化脚本,几何内核负责精确建模和格式导出。缺了内核,输出就是玩具;缺了语言模型,输入就得靠人手写代码。

2.3 从 STEP 到 URDF 和 G-code 的二次转换

模型建出来只是第一步。如果你的目标是机器人仿真,还得把几何转成 URDF。URDF 本质是个 XML,描述连杆(link)和关节(joint),几何部分可以引用 STL 或直接内嵌。

<robot name="simple_arm"> <link name="base_link"> <visual> <geometry> <mesh filename="base.stl" scale="1 1 1"/> </geometry> </visual> </link> <joint name="joint1" type="revolute"> <parent link="base_link"/> <child link="arm_link"/> <axis xyz="0 0 1"/> <limit lower="-1.57" upper="1.57" effort="10" velocity="1"/> </joint> </robot>

这里有个容易踩的坑:URDF 里的几何通常用 STL 而不是 STEP。因为仿真引擎(如 CoppeliaSim、Gazebo)对网格支持好,对 B-rep 支持差。所以流程往往是 STEP 建好精确模型,再转成 STL 喂给 URDF。转换时要注意单位——STEP 常用毫米,而很多仿真环境默认米,scale 写错会导致模型大一千倍,看起来像消失了一样。

至于 G-code,那是更下游的事。它不关心你的模型是不是实体,只关心刀具怎么走。从 STEP 到 G-code 一般要经过 CAM 软件生成刀路,text-to-cad 直接吐 G-code 的场景目前多见于简单的 3D 打印切片,复杂加工还是得靠专业 CAM。

3. 动手搭一条最小可用的 text-to-cad 流水线

3.1 环境准备:别一上来就装全家桶

我见过太多人一激动就把 SolidWorks、Fusion、FreeCAD、OpenSCAD 全装一遍,结果环境冲突、许可证报错、C++ 运行库缺失,光装软件就耗掉一整天。搭 text-to-cad 流水线,环境要"够用就好"。

最小组合是这样:Python 环境 + CadQuery(几何内核)+ 一个大模型 API(负责翻译)。CadQuery 基于 OpenCASCADE,装起来相对干净:

# 建议用 conda 建独立环境,避免和系统 Python 打架 conda create -n t2cad python=3.10 conda activate t2cad conda install -c conda-forge cadquery

用 conda 而不是 pip 装 CadQuery,是因为它依赖的 OCCT 库在 pip 下经常编译失败,conda-forge 有预编译包,省心。这一步我踩过坑:直接用 pip install cadquery 在 Windows 上大概率卡在编译阶段,报一堆 C++ 头文件找不到的错误。

提示:如果你只是想快速验证想法,也可以先用 OpenSCAD。它体积小、依赖少,缺点是脚本语言表达力弱一些,复杂模型写起来啰嗦。

3.2 让大模型稳定输出可执行脚本的三个技巧

直接对模型说"帮我生成一个法兰盘的 CadQuery 代码",十有八九会得到一段跑不起来的代码——要么 API 名字记错,要么参数顺序反了。要让输出稳定,得做三件事。

第一,给模型喂 API 文档片段。把 CadQuery 常用方法的签名贴进提示词,模型就不会瞎编。比如明确告诉它box(length, width, height)的参数顺序,它就不会写成box(width, length, height)。

第二,要求它先输出参数表,再输出代码。让模型把"孔径 20、板厚 8"这些关键尺寸单独列出来,你一眼就能核对,错了也好改。

第三,强制它做自检。在提示词里加一句"生成代码后,请逐行检查 API 调用是否符合 CadQuery 语法,指出任何不确定的地方"。实测下来,加了这句之后,代码一次跑通率能从三成提到七成左右。

# 一个典型的提示词骨架 prompt = """ 你是 CadQuery 专家。请根据以下描述生成 Python 代码: 描述:{user_input} 要求: 1. 先列出所有关键尺寸参数 2. 使用 cadquery 2.x 语法 3. 最后导出为 STEP 文件 4. 生成后自检 API 调用是否正确 可用 API 参考: - Workplane("XY").box(l, w, h) - .faces(">Z").workplane().hole(d) - cq.exporters.export(obj, "out.step") """

3.3 跑通第一个闭环:从文字到 STEP 文件

把上面几块拼起来,一个最小闭环就成型了。流程是:用户输入文字 → 大模型生成 CadQuery 代码 → 本地执行代码 → 导出 STEP → 用任意 CAD 软件打开验证。

import subprocess def text_to_step(user_input): code = call_llm(prompt.format(user_input=user_input)) # 把生成的代码写到临时文件执行 with open("gen_model.py", "w", encoding="utf-8") as f: f.write(code) result = subprocess.run( ["python", "gen_model.py"], capture_output=True, text=True ) if result.returncode != 0: # 把报错回喂给模型让它修 fixed = call_llm(f"这段代码报错了:{result.stderr}\n请修复:\n{code}") with open("gen_model.py", "w", encoding="utf-8") as f: f.write(fixed) subprocess.run(["python", "gen_model.py"]) return "model.step"

这个"报错回喂"的机制非常关键。模型第一次生成的代码几乎不可能完美,但把错误信息丢回去让它改,通常两三轮就能收敛。这比你自己去 debug 快得多,因为几何 API 的报错信息往往很晦涩,模型反而更擅长处理。

验证环节别偷懒。生成的 STEP 一定要用真实 CAD 软件打开看一眼。我遇到过模型生成的代码语法全对、能导出文件,但几何是空的情况——比如布尔运算把整个实体减没了。光看代码看不出来,必须打开模型确认。

4. 实测中最容易翻车的几个地方

4.1 单位混乱:毫米和米的千年之争

这是 text-to-cad 里最高频的坑,没有之一。CAD 领域习惯用毫米,机器人仿真和很多物理引擎默认用米。你在描述里说"一个 100 的立方体",模型默认按毫米生成,导出 STEP 没问题;但一旦转成 URDF 喂给仿真环境,模型可能大了一千倍,或者小得看不见。

我的做法是:在整条流水线的入口就强制声明单位,并且在每个转换环节都显式检查 scale。URDF 里的<mesh scale="0.001 0.001 0.001"/>就是把毫米转成米的常见写法。别指望每个工具都自动帮你换算,它们不会。

4.2 布尔运算失败:几何内核的脾气

几何内核做布尔运算(并、交、差)时,对输入很挑剔。两个面如果恰好重合,或者相切,运算就可能失败或者产生破面。这在文字描述里很难提前发现,因为用户不会说"注意让两个面不要重合"。

应对办法有两个。一是让模型生成代码时加入微小的偏移量,比如孔的位置不要正好落在边缘上,留 0.01 的余量。二是在代码里加异常捕获,布尔失败时自动调整参数重试。

try: result = base.cut(hole) except Exception as e: # 稍微移动孔位再试 result = base.cut(hole.translate((0.01, 0, 0)))

4.3 模型"看起来对"但不可加工

这是最隐蔽的坑。模型在屏幕上看着挺像那么回事,但实际拿去加工会发现:壁太薄、有倒扣、刀具进不去。text-to-cad 只保证几何成立,不保证工艺可行。

所以如果你的目标是真实制造,生成模型后必须过一遍可制造性检查。简单零件可以人工看,复杂零件建议用专门的 DFM(面向制造的设计)工具扫一遍。别让一个漂亮的模型骗了你,加工师傅看到会摇头的。

常见翻车点表现应对
单位混乱模型大/小一千倍入口声明单位,转换处查 scale
布尔失败报错或破面留微小余量,加异常重试
不可加工壁薄、倒扣生成后过 DFM 检查
特征丢失导出后孔没了用 STEP 而非 STL 交换
参数写反长宽高颠倒提示词里给 API 签名

5. 把 text-to-cad 接进真实工作流的几种姿势

5.1 批量参数化:一张表格生成一堆零件

text-to-cad 最实用的场景不是生成单个复杂零件,而是批量生成一系列相似零件。比如你有张 Excel 表,列着 50 种规格的垫片,与其手动画 50 次,不如写个循环。

import pandas as pd specs = pd.read_excel("gaskets.xlsx") for _, row in specs.iterrows(): model = ( cq.Workplane("XY") .circle(row["outer_d"] / 2) .extrude(row["thickness"]) .faces(">Z").workplane() .hole(row["inner_d"]) ) cq.exporters.export(model, f"gasket_{row['id']}.step")

这种场景下,text-to-cad 的价值不在"AI 有多聪明",而在于把"描述"和"生成"解耦了。描述可以来自表格、来自数据库、来自用户表单,生成逻辑统一。这才是工程化的用法。

5.2 和现有 CAD 软件配合,而不是取代它

别想着用 text-to-cad 完全替代 SolidWorks 或中望 CAD。更现实的姿势是:用它做"第一版草模",然后导入专业软件精修。STEP 格式在这里就是桥梁,几乎所有主流 CAD 都能无缝导入。

我自己的流程是:文字描述 → 生成 STEP → 导入 CAD 软件 → 加约束、加工程图、加公差。前面 70% 的重复劳动交给程序,后面 30% 需要工程判断的部分留给人。这个分工目前最舒服。

5.3 机器人仿真场景:STEP 转 URDF 的完整链路

做机器人仿真的朋友会关心 STEP 到 URDF 怎么走。完整链路是:text-to-cad 生成各连杆的 STEP → 转成 STL → 写 URDF 引用 STL → 在仿真环境里组装。

转换工具可以用 FreeCAD 的命令行,或者 Python 的 trimesh 库。关键是每个连杆的坐标系要对齐,URDF 里的 joint origin 要和几何的实际位置匹配。这一步纯靠文字描述很难搞对,通常需要生成后在仿真环境里手动微调 joint 的位置参数。

注意:URDF 导入 CoppeliaSim 这类环境时,如果模型不显示,先查两件事——单位 scale 对不对,mesh 路径是不是相对路径写错了。这两个原因占了九成。

6. 我对 text-to-cad 的一点真实看法

折腾这套东西大半年,最大的感受是:它现在的能力边界,卡在"描述精度"上,而不是"生成能力"上。模型能生成的几何复杂度其实够用了,真正难的是人怎么把脑子里的三维构想,用没有歧义的语言说清楚。

"一个带孔的板"——孔多大?几个?在哪?通孔还是盲孔?这些信息人觉得"不言自明",但对程序来说全是缺失。所以用好 text-to-cad 的前提,是你自己得先把需求想清楚、写明白。这反而倒逼了一种更严谨的工程思维。

另一个体会是,别追求"一句话生成完美模型"。把它当成一个"快速草模生成器"和"批量零件工厂",心态就对了。它帮你干掉的是重复劳动,不是工程判断。那些需要经验、需要权衡、需要和加工师傅扯皮的部分,还是得人来。

最后分享一个我常用的小技巧:把常用的零件描述模板存下来,比如"法兰盘模板""支架模板",每次改几个参数就能复用。这比每次从零描述快得多,也让输出更稳定。text-to-cad 的尽头,其实是你自己积累的一套"描述资产"。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询