text-to-cad 实战:从自然语言到 STEP/URDF/G-code 的完整流水线

发布时间:2026/10/8 9:15:46
text-to-cad 实战:从自然语言到 STEP/URDF/G-code 的完整流水线 1. 从一句话到三维模型text-to-cad 到底在解决什么问题第一次听到 text-to-cad 这个词很多人脑子里浮现的画面大概是对着电脑说一句给我画个法兰盘屏幕上就自动长出一个带螺栓孔的实体。这个想象不算离谱但真正落地的时候它解决的问题比省几次鼠标点击要深得多。传统 CAD 工作流的本质是人肉翻译需求方用自然语言描述一个零件工程师在脑子里把它翻译成尺寸、约束、特征树再用手在软件里一步步建模。这个链条里最贵的不是画图本身而是理解需求和把需求转成几何这两步。text-to-cad 想干的就是把这两步尽可能自动化——输入一段文字描述输出一个可用的三维模型文件通常是STEP这类中性格式或者带装配关系的URDF再往下甚至能生成G-code送去加工。它适合谁我梳理下来大概是三类人。第一类是做快速原型的产品和硬件工程师需要在一小时内把脑子里的想法变成能看、能算、能打印的模型而不是花半天开软件调草图。第二类是做仿真和机器人的人他们经常需要批量生成结构相似的模型比如一堆不同尺寸的支架手动建模纯属浪费生命。第三类是想入门 CAD 但被复杂界面劝退的新手用自然语言先跑通描述—生成—导出的闭环比一上来就啃草图约束友好得多。但这里必须先泼一盆冷水text-to-cad 目前不是替代 CAD 工程师的工具它更像一个几何草稿生成器。它擅长的是结构相对规整、参数化特征明显的零件——板、轴、支架、法兰、简单壳体。遇到复杂曲面、自由造型、精密配合公差它给的结果往往只能当参考最后还得人工修。理解这个边界比学会用某个具体工具更重要因为边界决定了你该在什么场景下用它以及什么时候该果断放弃它回去手搓。我自己的判断是text-to-cad 的价值不在于生成得多完美而在于把从想法到第一个可验证模型的时间压缩到分钟级。这个时间差才是它真正的生产力。2. 拆解 text-to-cad 的技术链路文字是怎么变成实体的要真正用好一个工具得先知道它内部大概在干什么。text-to-cad 听起来是一个动作实际上是好几段流水线拼起来的每一段都有它自己的坑。2.1 自然语言到结构化参数的转换第一步是把一个 100mm 长、50mm 宽、10mm 厚四角带 M6 通孔的铝板这种描述解析成机器能处理的结构化数据。这里的关键不是听懂中文而是抽取几何意图长度、宽度、厚度是尺寸参数四角是位置约束M6 通孔是特征类型加标准件引用。这一步现在主流做法是让大语言模型做意图识别和参数抽取输出一段结构化的 JSON 或者类似 DSL 的中间表示。我实测下来模型对尺寸特征位置这种显式描述识别得相当准但一旦描述里出现模糊词——比如稍微倒个角孔别太靠边——它就开始瞎猜。所以第一条实操经验就是给 text-to-cad 的描述要像写给一个完全不懂你行业但极其听话的实习生所有尺寸给数字所有位置给参照所有特征给标准。2.2 参数化建模内核的调用拿到结构化参数后系统需要真正把几何造出来。这一步通常不是让 AI 直接画而是调用一个参数化建模内核比如基于 OpenCASCADE 这类几何内核用代码常见的是 CadQuery 或 build123d 这类 Python 库把参数翻译成建模脚本再执行生成实体。为什么绕这一圈因为直接让神经网络输出网格顶点得到的模型往往拓扑混乱、无法参数化修改、导出 STEP 还会丢面。而走参数→脚本→内核这条路生成的是真正的 B-rep 实体能导出干净的 STEP能被后续 CAD 软件正常打开和编辑。这是 text-to-cad 能不能用于正经工程的分水岭。2.3 导出格式的选择逻辑生成实体之后导出成什么格式取决于你下一步要干嘛。我把常见格式和适用场景整理成一张表这个表我在项目里反复用到直接抄就行格式本质典型用途注意事项STEP中性 B-rep 实体跨软件交换、CAM 加工、存档优先选 AP214/AP242兼容性最好STL三角网格3D 打印、快速预览无参数、无单位精度靠网格密度URDF带关节的机器人描述机器人仿真、运动学需要额外定义 link/joint 层级G-code机床/打印机指令直接加工依赖具体设备和后处理配置IGES老式中性格式兼容老系统曲面易碎能不用就不用提示如果你的目标是生成后还要在 CAD 里继续改那 STEP 是唯一稳妥的选择。STL 一旦导出参数就全丢了改一个孔位都得重新生成。2.4 从模型到 URDF 和 G-code 的延伸热词里出现了 URDF 和 G-code说明很多人关心的不只是生成一个零件而是生成能进仿真、能进加工的东西。URDF 这条路本质是在几何之上再叠一层运动学结构哪个是基座 link哪个是关节 joint旋转轴在哪父子关系怎么连。text-to-cad 生成的往往是单个零件要变成 URDF还得人工或脚本补上关节定义。G-code 这条路更直接模型生成后走切片或 CAM 后处理。这里最容易翻车的是坐标系和单位。我见过太多案例模型本身没问题但因为生成时单位是米、切片软件默认毫米结果零件被放大一千倍。所以从 text-to-cad 出来的模型进加工链路前第一件事永远是核对单位和坐标系朝向。3. 动手搭一条最小可用的 text-to-cad 流水线光讲原理没意思我把自己跑通的一条最小流水线完整拆出来。这套方案不依赖任何特定商业软件核心是 Python 生态跑通之后你可以按需替换任意环节。3.1 环境准备与依赖选择基础环境就是 Python 3.10 以上核心依赖是参数化建模库。我选 CadQuery 作为建模内核原因是它 API 清晰、社区活跃、导出 STEP 稳定而且天然适合被脚本批量调用——这正是 text-to-cad 需要的特性。pip install cadquery pip install openai # 或任意你用来做意图解析的模型 SDK如果你不想依赖云端模型做意图解析也可以用本地的规则解析先跑通流程等流程稳了再换成模型。我的建议是先用规则跑通再上模型否则一旦出问题你分不清是解析错了还是建模错了。3.2 用规则解析先跑通闭环先写一个最土的版本用正则从描述里抠数字。比如描述是长 100 宽 50 厚 10 的板四角 M6 通孔就抽出 100、50、10 和孔径。import re import cadquery as cq def parse_plate(desc): nums list(map(float, re.findall(r\d\.?\d*, desc))) length, width, thickness nums[0], nums[1], nums[2] hole_d 6.0 # M6 通孔直径按 6.6 预留这里先给标称 return length, width, thickness, hole_d def build_plate(length, width, thickness, hole_d): margin hole_d # 孔中心距边距离 plate ( cq.Workplane(XY) .box(length, width, thickness) .faces(Z).workplane() .rect(length - 2*margin, width - 2*margin, forConstructionTrue) .vertices() .hole(hole_d) ) return plate desc 长 100 宽 50 厚 10 的板四角 M6 通孔 l, w, t, d parse_plate(desc) model build_plate(l, w, t, d) cq.exporters.export(model, plate.step)这段代码跑通你就有了一个能用的 text-to-cad 雏形。它很笨但闭环是完整的文字进STEP 出。3.3 把解析层换成大模型规则版跑通后把parse_plate换成模型调用。核心是设计一个好的提示词让模型输出固定结构的 JSONimport json from openai import OpenAI client OpenAI() PROMPT 你是一个 CAD 参数解析器。把用户描述转成 JSON字段固定为 length, width, thickness, hole_diameter, hole_count, material。 只输出 JSON不要解释。单位统一为毫米。 def parse_with_llm(desc): resp client.chat.completions.create( modelgpt-4o-mini, messages[ {role: system, content: PROMPT}, {role: user, content: desc}, ], response_format{type: json_object}, ) return json.loads(resp.choices[0].message.content)这里有个关键细节一定要用 JSON 模式或强制结构化输出。我早期没加约束模型时不时在 JSON 前后加一句好的这是解析结果导致json.loads直接崩。加了response_format之后稳定性提升非常明显。3.4 批量生成与参数扫描text-to-cad 真正爽的地方是批量。比如你要生成 20 个不同长度的支架做仿真对比手搓是不可能的脚本几秒钟搞定for length in range(80, 180, 10): model build_plate(length, 50, 10, 6.6) cq.exporters.export(model, fplate_{length}.step)这套批量能力配合后面的 URDF 生成就是机器人参数化建模的雏形。我做过一个项目需要生成上百个不同臂长的连杆做运动学校核用这套流程半天就搞定了换成手动建模至少一周。4. 那些文档不会告诉你的坑从 STEP 到 URDF 的实战排错流程跑通只是开始真正折磨人的是各种看起来没问题但就是不对的故障。这一节我把踩过的坑按排查链路完整还原你可以直接对照复现。4.1 STEP 导出后打不开或丢面最常见的症状STEP 文件生成了但用 CAD 打开是空的或者少了几张面。根因通常有三个。第一是建模时产生了非流形几何比如两个实体只靠一条边接触导出时内核无法判定内外。第二是单位不一致有的内核默认米导出时没做转换。第三是导出精度设置过低曲面被简化到无法闭合。排查顺序我固定成这样先用 CadQuery 自带的model.val().isValid()检查实体有效性再确认建模时所有布尔运算的结果都是单一实体最后检查导出参数。我一般会在导出前加一句断言assert model.val().isValid(), 实体无效先修几何再导出这一步能挡掉八成导出后打不开的问题。4.2 URDF 导入仿真环境后模型乱飞热词里有urdf导入coppeliasim这个场景我太熟了。URDF 导入后模型乱飞、关节错位、整体翻转几乎都出在坐标系约定上。URDF 规定每个 link 的坐标系原点在它自己的参考点上joint 的 origin 是相对父 link 的变换。如果你从 text-to-cad 生成的零件直接塞进 URDF而没重新定义 link 原点那 joint 的旋转轴就会偏到莫名其妙的位置。我的做法是几何归几何运动学归运动学。text-to-cad 只负责生成零件几何link 原点和 joint 轴在 URDF 里单独定义两者解耦。这样即使几何重新生成运动学结构也不用动。link namearm visual geometry mesh filenamearm.stl scale0.001 0.001 0.001/ /geometry /visual /link joint nameshoulder typerevolute parent linkbase/ child linkarm/ origin xyz0 0 0.05 rpy0 0 0/ axis xyz0 1 0/ /joint注意那个scale0.001 0.001 0.001——如果你的 STL 是毫米单位而仿真环境按米处理不加这个缩放模型会大一千倍。这个坑我踩过不止一次。4.3 G-code 生成前的单位与朝向核对从模型到 G-code中间隔着切片或 CAM。这里最隐蔽的坑是Z 轴朝向。text-to-cad 生成的模型Z 轴正方向可能是上也可能是厚度方向取决于建模时的草图平面选择。如果切片软件假设 Z 向上而你的模型 Z 是厚度方向打出来的东西就是躺着的。我的固定动作是导出前统一把模型摆到Z 向上、底面在 Z0的标准姿态。这一步用 CadQuery 的translate和rotate几行就能搞定但能省掉后面无数次重新切片。4.4 批量生成时的命名与版本混乱批量生成最容易失控的是文件管理。plate_1.step到plate_100.step过两天你根本不知道哪个对应哪组参数。我的做法是把关键参数编进文件名比如plate_L100_W50_T10_H6.6.step再配一个 CSV 记录每次生成的完整参数和用途。这个习惯看起来土但在需要回溯这个模型到底是哪版参数的时候能救命。5. 让 text-to-cad 真正好用的描述技巧与参数约定工具再好描述写得烂出来的东西也烂。这一节讲的是怎么把话说清楚这是 text-to-cad 使用中回报率最高的技能。5.1 描述模板把模糊需求变成可执行指令我总结了一个描述模板基本覆盖了大部分规则零件[整体形状] [主尺寸三向] [特征列表类型/尺寸/位置] [材料/工艺] [单位]举个例子对比一下两种写法差的写法做一个安装板上面开几个孔好的写法矩形板长 120 宽 80 厚 8四角各一个直径 6.6 的通孔孔中心距边 10材料 6061 铝单位毫米第二种写法模型几乎不会出错。第一种你只能祈祷。5.2 尺寸与公差的表达方式text-to-cad 目前对公差的理解很弱。你写M6 通孔它可能给你 6.0也可能给 6.6。我的经验是直接给最终尺寸不要给标准件代号让它猜。需要 M6 螺栓穿过就写直径 6.6 通孔需要过盈配合就写直径 5.8 孔配 6.0 轴。把工程判断留给自己把执行留给工具。5.3 特征命名与后续可编辑性如果你希望生成的模型后续还能改那在描述里就要给特征起名字比如底板加强筋安装孔组。有些 text-to-cad 工具会把这些名字保留到特征树里后续修改时你能直接定位。这个细节很多人忽略但当你需要改第 7 个孔的位置时有名字和没名字的差别就是几分钟和半小时。5.4 常见描述歧义与规避我整理了几个高频歧义点歧义描述可能被理解成建议写法倒个角圆角或倒角尺寸随机边缘 R2 圆角孔靠边一点位置不确定孔中心距边 10mm厚一点无参照厚度改为 12mm对称对称轴不明关于 X 轴对称把这些歧义提前消掉比事后修模型省事得多。6. 从零件到装配text-to-cad 在机器人与加工场景的延伸单个零件只是起点。text-to-cad 真正有意思的延伸是往装配、仿真、加工三个方向走。6.1 多零件装配的描述策略描述一个装配体比描述单个零件难得多因为多了相对位置和配合关系。我的策略是分而治之先分别生成每个零件再用脚本按约束装配。比如一个简单的两连杆机构先 text-to-cad 生成 base 和 arm 两个零件再用 CadQuery 的Assembly按坐标装配。assy ( cq.Assembly() .add(base, namebase) .add(arm, namearm, loccq.Location(cq.Vector(0, 0, 50))) ) assy.save(assembly.step)这样每个零件仍然可以独立重新生成装配关系单独维护互不干扰。6.2 生成 URDF 时的 link 与 joint 划分从装配体到 URDF核心工作是划分 link 和 joint。原则很简单每个独立运动的刚体是一个 link两个 link 之间的运动约束是一个 joint。text-to-cad 生成的几何按这个原则切分再补上 joint 的轴和限位就能进仿真。这里有个经验link 的视觉几何和碰撞几何最好分开。视觉几何用精细的 STL碰撞几何用简化后的凸包或包围盒这样仿真速度会快很多。text-to-cad 生成的精细模型直接当碰撞体仿真会卡到怀疑人生。6.3 加工链路从模型到 G-code 的最后一公里如果你的目标是加工那 text-to-cad 生成的模型只是毛坯。接下来要走 CAM定义刀具、走刀策略、后处理。这一步目前 text-to-cad 帮不上太多但前面把模型和单位理顺了CAM 环节会顺很多。我的建议是text-to-cad 负责快速得到正确几何CAM 负责把几何变成加工指令两者边界清晰不要指望一个工具全包。6.4 参数化模板的沉淀跑通几次之后你会发现很多零件结构是重复的只是尺寸不同。这时候就该把描述和建模脚本沉淀成模板。比如带四角孔的矩形板就是一个模板参数是长宽厚和孔径。下次直接填参数连描述都不用写。这一步是从用工具到建工具的跃迁也是 text-to-cad 在团队里真正产生复利的地方。7. 我在这条路上踩过的几个真实教训最后分享几个纯个人经验都是文档里不会写、但实际会疼的。第一个教训不要一上来就追求全自动。我最初想做一个输入一句话直接输出可加工 G-code的全自动流水线结果每个环节的误差累积起来最后出来的东西完全不能用。后来改成半自动——text-to-cad 生成几何人工确认后再进下一步——反而效率更高。自动化不是目的可靠才是。第二个教训单位问题值得单独写一个检查函数。我现在的每个项目里都有一个check_units()在导出前强制核对单位、坐标系朝向、模型包围盒尺寸是否在合理范围。这个函数帮我挡掉了至少十次模型大一千倍的事故。第三个教训保留每次生成的原始描述和参数。text-to-cad 的随机性比想象中大同样的描述两次生成可能有细微差别。把描述、参数、生成时间、模型文件一起存档出问题时才能回溯。我用一个简单的 SQLite 表就搞定了字段是desc, params_json, file_path, created_at成本极低价值极高。第四个教训别迷信模型该手搓就手搓。text-to-cad 适合规整零件遇到复杂曲面、异形结构硬用只会浪费时间。判断标准很简单如果你自己都说不清楚这个形状的参数那工具更说不清楚。这时候老老实实打开 CAD 手搓才是最快的路。这套东西我用了大半年从最初的新鲜感到中间的踩坑期再到现在把它当成一个稳定的几何草稿机来用。它的定位越来越清晰不是替代谁而是把从想法到第一个可验证模型的时间从小时级压到分钟级。这个时间差就是它全部的价值。