1. 从一句话到三维模型:text-to-cad 到底在解决什么问题
第一次听到 “text-to-cad” 这个词,很多人脑子里浮现的画面大概是:对着电脑说一句“给我画个齿轮”,然后屏幕上就自动蹦出一个可以旋转、可以导出、可以加工的 3D 模型。这个想象不算离谱,但也不完全准确。准确地说,text-to-cad 是一类把自然语言描述转换成 CAD 可识别几何数据的技术方案统称,它的输出通常不是某个私有格式的工程图,而是 STEP、URDF、G-code 这类下游工具链真正能“吃进去”的中间或最终格式。
我在实际项目里接触这个方向,最初是因为一个很具体的痛点:团队里做机械结构的人手有限,但需求方每天能提几十条修改意见,比如“把法兰盘外径加大 5 毫米”“这个支架的安装孔改成腰形孔”“给机械臂加一个末端夹爪的简化模型”。这些需求本身不复杂,可每一条都要在 CAD 软件里手动改一遍,改完还要导出 STEP 给仿真、导出 URDF 给机器人仿真环境、导出 G-code 给加工。重复劳动多,出错概率也高。text-to-cad 要解决的,正是从“人话”到“工程数据”之间那段又长又碎的转换链路。
它适合谁来参考?如果你是完全没碰过 CAD 的小白,这篇文章能帮你理解整个链路是怎么跑通的,不至于被 STEP、URDF、G-code 这些缩写吓退;如果你是有经验的机械工程师或机器人方向开发者,文章里关于参数化建模、格式转换、批量处理的细节,应该能直接拿去改造成自己的工具。我不会只讲概念,重点会放在怎么落地、怎么避坑、怎么把一条自然语言描述稳定地变成可用的模型文件。
需要先说明一点:text-to-cad 目前并不是“一句话生成任意复杂装配体”的魔法。它更擅长的是参数化、规则明确、结构相对标准的零件或简单装配。比如法兰、支架、齿轮、导轨、夹爪、简单外壳。真正复杂的曲面、自由造型、多零件干涉配合,仍然需要人工介入。认清这个边界,后面的方案设计才不会跑偏。
2. 整体方案设计:为什么是“文本解析 + 参数化模板 + 多格式导出”
2.1 核心思路拆解
把 text-to-cad 拆开看,它其实是一条流水线,而不是一个单点技术。我习惯把它分成四层:
- 输入层:自然语言描述,可能来自聊天记录、需求文档、语音转写文本。
- 解析层:从文本里抽取关键参数,比如尺寸、数量、位置、孔位、材料、公差。
- 建模层:用参数驱动几何生成,通常基于参数化模板或脚本化建模。
- 导出层:把生成的模型转成 STEP、URDF、G-code 等目标格式。
这四层里,解析层和建模层是决定成败的关键。很多人一上来就想用大模型直接生成 CAD 文件,结果发现模型输出的坐标、尺寸、拓扑关系经常自相矛盾。更稳的做法是:让语言模型负责“理解意图和抽取参数”,让确定性的参数化脚本负责“生成几何”。这样既利用了语言模型的灵活性,又保证了几何的严谨性。
2.2 为什么选参数化模板而不是纯生成
纯生成路线听起来很酷,但实际落地时会遇到几个硬问题。第一,几何合法性难保证,生成的实体可能自相交、面不闭合、法线方向错误。第二,参数不可追溯,改一个尺寸可能整个模型崩掉。第三,下游格式转换容易失败,STEP 对拓扑一致性要求很高,URDF 对惯量和坐标系有额外要求。
参数化模板的思路是:预先为常见零件类型写好建模脚本,文本只负责填充参数。比如一个“带孔法兰”模板,接收外径、内径、厚度、孔数、孔直径、孔分布圆直径这几个参数,就能稳定生成模型。文本解析只需要把“外径 120,内径 60,厚 10,6 个直径 8 的孔,分布圆 90”抽出来,剩下的交给脚本。这样做的好处是结果可复现、可批量、可版本管理,出错也容易定位。
2.3 格式选型:STEP、URDF、G-code 各自扮演什么角色
这三个格式经常被混在一起讨论,但它们的用途完全不同。我用一个表格说清楚:
| 格式 | 主要用途 | 关键特点 | 常见下游工具 |
|---|---|---|---|
| STEP | 通用三维模型交换 | 保留精确 B-rep 几何,跨 CAD 平台 | 各类 CAD 软件、仿真软件 |
| URDF | 机器人描述 | 描述连杆、关节、惯量、碰撞体 | 机器人仿真与规划环境 |
| G-code | 加工指令 | 刀具路径、速度、进给 | 数控机床、3D 打印机 |
text-to-cad 的输出往往需要同时覆盖这三类。比如做一个机械臂末端夹爪,STEP 给结构工程师确认外形,URDF 给机器人仿真环境做运动学验证,G-code 给加工中心做实际切削。同一份参数,导出三种格式,这才是 text-to-cad 真正的效率价值。
2.4 技术栈选择与理由
我实际用过的组合是:Python 做主力语言,CadQuery 或 build123d 做参数化建模,FreeCAD 做格式转换兜底,语言模型做文本解析。选 Python 是因为生态成熟,CAD 相关的库多,和机器人工具链衔接也方便。CadQuery 的优势是代码即模型,天然适合参数化,导出 STEP 很稳。build123d 更接近 OpenCASCADE 的底层能力,复杂操作更灵活。
语言模型这块,我倾向于用结构化输出的方式,让它返回 JSON,而不是直接返回代码。JSON 里包含零件类型和参数字典,再由本地脚本校验参数范围、生成模型。这样即使模型偶尔抽错参数,也能在生成前被拦截。
注意:不要让语言模型直接生成可执行的建模代码并直接运行。模型生成的代码可能包含危险操作或错误几何逻辑,必须经过人工审核或沙箱校验。
3. 核心细节解析:文本解析、参数校验与建模脚本
3.1 文本解析:怎么把“人话”变成结构化参数
文本解析是整条链路里最“软”的一环,也是最容易出问题的一环。我的经验是,不要指望一次解析就完美,而是设计成“抽取 + 追问 + 校验”的循环。
先定义好每种零件类型的参数模式。比如法兰:
{ "part_type": "flange", "params": { "outer_diameter": 120, "inner_diameter": 60, "thickness": 10, "hole_count": 6, "hole_diameter": 8, "hole_circle_diameter": 90 } }然后让语言模型从文本里填这个结构。提示词里要明确单位、默认值、必填项。比如“如果文本没提厚度,默认取 10 毫米”“孔数必须是整数”“外径必须大于内径”。这些规则写进提示词,能大幅降低解析错误率。
实际文本往往很口语:“那个法兰盘外圈做到 120 左右,中间孔 60,厚度跟之前一样,打 6 个 8 个的孔,分布圆 90”。这里“跟之前一样”就需要上下文记忆,或者从历史记录里取默认值。我的做法是维护一个参数上下文,每次解析时把最近一次同类型零件的参数带上,让模型做增量修改。
3.2 参数校验:生成前的最后一道闸
参数校验看起来简单,但漏掉一步就可能生成废模型。我总结了几条必查项:
- 尺寸范围:外径不能小于内径,厚度不能为负,孔直径不能大于壁厚能承受的范围。
- 几何可行性:孔分布圆直径必须小于外径减去孔半径,否则孔会切到边缘。
- 单位一致性:文本里可能混用毫米和厘米,解析后统一转成毫米。
- 数量合理性:孔数过多会导致建模时间暴涨,一般超过 200 个孔就要提醒用户确认。
这些校验用普通 Python 函数就能做,不需要语言模型参与。校验失败时,返回明确的错误信息,比如“孔分布圆直径 90 加上孔半径 4 等于 94,超过外径半径 60,请调整”。这样用户能直接改,而不是拿到一个坏模型再回头排查。
3.3 建模脚本:以法兰为例的完整实现
下面是我实际用过的 CadQuery 法兰建模脚本简化版:
import cadquery as cq def build_flange(outer_d, inner_d, thickness, hole_count, hole_d, hole_circle_d): # 基础圆盘 flange = ( cq.Workplane("XY") .circle(outer_d / 2) .extrude(thickness) ) # 中心孔 flange = flange.faces(">Z").workplane().hole(inner_d) # 分布孔 if hole_count > 0: flange = ( flange.faces(">Z").workplane() .polarArray(hole_circle_d / 2, 0, 360, hole_count) .hole(hole_d) ) return flange这段代码的逻辑很直白:先拉伸一个圆盘,再打中心孔,再沿圆周阵列打孔。CadQuery 的polarArray会自动处理角度分布,省去手动算坐标的麻烦。生成后导出 STEP:
result = build_flange(120, 60, 10, 6, 8, 90) cq.exporters.export(result, "flange.step")实测下来,这个脚本生成一个带 6 孔的法兰不到一秒,STEP 文件大小在几十 KB 级别,导入各类 CAD 软件都能正常识别。
3.4 URDF 导出:机器人场景的额外要求
如果这个法兰要作为机器人连杆的一部分,就需要导出 URDF。URDF 不只是几何,还要定义连杆坐标系、质量、惯量、碰撞体。几何部分可以从 CadQuery 模型转成 mesh,再写进 URDF 的<visual>和<collision>标签。惯量可以简化计算,或者用近似公式估算。
一个常见的坑是坐标系原点。CAD 模型的原点可能在法兰中心,但 URDF 里连杆原点可能在安装面。如果不做变换,导入机器人仿真环境后模型位置会偏。我的做法是在建模时就约定好原点位置,或者在导出时加一个变换矩阵。
3.5 G-code 生成:从模型到刀路
G-code 不是 text-to-cad 的直接输出,通常需要经过 CAM 环节。简单零件可以用 FreeCAD 的 Path 工作台生成,或者用 Python 调用 OpenCAMLib 之类的库。关键参数包括刀具直径、切削深度、进给速度、主轴转速。这些参数往往不在文本描述里,需要根据材料和工作条件补全。
我的经验是,text-to-cad 到 G-code 这一步不要追求全自动。自动生成的刀路可以作为初稿,但必须经过人工检查,尤其是涉及安全关键的加工。文本描述里如果没提材料,默认按铝合金给参数,但要在输出里标注“假设材料为铝合金,请根据实际材料调整”。
4. 实操过程:从零搭建一条可复现的 text-to-cad 流水线
4.1 环境准备与依赖安装
先说明,这里的环境搭建以 Python 为主,不涉及任何不合规的网络工具。所有依赖都来自公开的包管理渠道。
第一步,创建虚拟环境:
python -m venv text2cad_env source text2cad_env/bin/activate # Windows 用 text2cad_env\Scripts\activate第二步,安装核心库:
pip install cadquery build123dCadQuery 的安装在不同平台上略有差异,如果遇到编译问题,可以先用 conda 装:
conda install -c conda-forge cadquery第三步,安装格式转换和辅助库:
pip install numpy trimesh pyyamltrimesh 用来处理 mesh 和 URDF 里的几何引用,numpy 做数值计算,pyyaml 读写配置文件。
4.2 目录结构设计
我习惯把项目组织成下面这样:
text2cad/ ├── configs/ │ └── part_schemas.yaml ├── parsers/ │ └── text_parser.py ├── builders/ │ ├── flange_builder.py │ ├── bracket_builder.py │ └── gear_builder.py ├── exporters/ │ ├── step_exporter.py │ ├── urdf_exporter.py │ └── gcode_exporter.py ├── validators/ │ └── param_validator.py └── main.py这样分层的好处是,新增零件类型只需要加一个 builder,解析和导出逻辑复用。参数模式放在 YAML 里,改规则不用动代码。
4.3 参数模式定义示例
part_schemas.yaml里定义法兰的参数模式:
flange: required: - outer_diameter - inner_diameter - thickness optional: hole_count: default: 0 hole_diameter: default: 6 hole_circle_diameter: default: null constraints: - outer_diameter > inner_diameter - thickness > 0 - hole_count >= 0解析器读取这个模式,生成提示词,校验返回值。这样新增零件类型时,只需要改 YAML,不用改解析器代码。
4.4 完整调用流程
main.py里的主流程大致是:
from parsers.text_parser import parse_text from validators.param_validator import validate from builders.flange_builder import build_flange from exporters.step_exporter import export_step text = "外径120,内径60,厚10,6个直径8的孔,分布圆90" params = parse_text(text, part_type="flange") validate(params, part_type="flange") model = build_flange(**params) export_step(model, "output/flange.step")每一步都有明确的输入输出,出错时能快速定位是解析错了、校验拦住了,还是建模失败。
4.5 批量处理:一次生成多个变体
实际工作中经常需要生成一系列变体,比如外径从 100 到 200,步长 10。这时候可以用循环:
for od in range(100, 210, 10): params = {"outer_diameter": od, "inner_diameter": od/2, "thickness": 10, "hole_count": 6, "hole_diameter": 8, "hole_circle_diameter": od*0.75} model = build_flange(**params) export_step(model, f"output/flange_od{od}.step")批量生成时要注意文件命名和版本管理,避免覆盖。我一般会在文件名里带上关键参数和时间戳。
4.6 与现有 CAD 工作流的衔接
text-to-cad 生成的 STEP 文件可以直接导入各类 CAD 软件继续编辑。如果团队用的是中望 CAD 或类似工具,导入后可以继续做工程图、标注、装配。对于需要合并图纸的场景,可以把多个 STEP 导入同一个装配文件,再统一导出。
如果后续要做 CAD 转 PDF 出图,可以在 CAD 软件里完成,也可以用 Python 调用相关库批量转换。这一步的关键是图层和线型要提前规范,否则批量出图时线宽会乱。
5. 常见问题与排查技巧实录
5.1 解析结果不稳定怎么办
这是最常见的问题。同一句话,模型可能这次抽对了,下次抽错了。我的应对策略有三个:第一,固定提示词模板,把参数模式、单位、默认值写死,减少模型自由发挥。第二,加 few-shot 示例,在提示词里放两三个正确解析的例子。第三,加后置校验,解析结果先过一遍规则,不合法就重新解析或报错。
如果文本特别模糊,比如“做个差不多大的”,那就不要硬解析,直接返回追问:“请提供外径、内径、厚度等具体尺寸”。宁可多问一句,不要生成错模型。
5.2 生成的 STEP 导入后显示异常
有时候 STEP 文件能生成,但导入 CAD 软件后显示破面或缺失。常见原因有:几何自相交、面法线方向不一致、单位设置错误。排查方法是先用 FreeCAD 打开检查,看是否有报错。如果模型本身没问题,可能是导出时的精度设置太低,可以调高tolerance参数。
另一个坑是坐标系。不同软件对 STEP 的坐标系约定可能不同,导入后模型方向不对。解决办法是在导出时明确指定坐标系,或者在导入后手动调整。
5.3 URDF 导入仿真环境后模型位置偏移
这个问题我踩过好几次。根本原因通常是 URDF 里的<origin>标签和实际几何原点不一致。排查步骤:先单独打开 mesh 文件确认原点位置,再检查 URDF 里 visual 和 collision 的 origin 设置。如果 mesh 原点在法兰中心,而 URDF 希望原点在安装面,就需要在 origin 里加平移。
还有一个容易忽略的点是单位。URDF 默认用米,而 CAD 模型常用毫米。如果直接引用毫米单位的 mesh,模型会放大 1000 倍。导出时要么把 mesh 缩放到米,要么在 URDF 里加 scale。
5.4 G-code 加工出来尺寸不对
G-code 尺寸偏差通常来自几个方面:刀具半径补偿没开、切削深度设置错误、材料回弹。text-to-cad 生成的 G-code 只是初稿,必须结合实际机床和刀具做校准。我的建议是先用便宜材料试切,确认尺寸后再上正式材料。
5.5 常见问题速查表
| 问题现象 | 可能原因 | 排查方向 | 解决建议 |
|---|---|---|---|
| 解析参数缺失 | 文本太模糊 | 检查提示词和示例 | 增加追问环节 |
| 模型生成失败 | 参数越界 | 查看校验日志 | 调整参数或模板 |
| STEP 导入破面 | 几何不合法 | 用 FreeCAD 检查 | 提高导出精度 |
| URDF 位置偏移 | 原点不一致 | 对比 mesh 和 URDF | 调整 origin 或缩放 |
| G-code 尺寸偏差 | 刀具补偿 | 检查 CAM 设置 | 试切校准 |
| 批量生成覆盖文件 | 命名冲突 | 检查文件名规则 | 加参数和时间戳 |
5.6 几个独家避坑技巧
第一,参数默认值要保守。比如孔直径默认取 6 毫米而不是 10 毫米,因为小孔改大容易,大孔改小可能影响结构。第二,每次生成都留日志,记录输入文本、解析参数、生成文件路径,出问题能回溯。第三,模板不要写太复杂,一个模板只做一类零件,复杂装配用多个模板组合。第四,定期清理输出目录,批量生成很容易堆出几百个文件,找起来头疼。
6. 影响范围与扩展方向:text-to-cad 能走多远
6.1 对个人和小团队的价值
对个人开发者和小团队来说,text-to-cad 最大的价值是降低重复劳动。以前改一个尺寸要打开 CAD 软件、找到对应特征、修改、导出,现在一条命令就能批量完成。尤其是做参数化系列产品,比如不同规格的法兰、支架、夹具,效率提升非常明显。
6.2 对机器人开发流程的影响
机器人方向对 URDF 的需求很频繁。每次改连杆尺寸,都要重新导出 URDF 并调整惯量。text-to-cad 可以把这一步自动化,改参数后直接生成新的 URDF,导入仿真环境验证。这样迭代速度会快很多。
6.3 与批量修改、图纸合并的结合
热词里提到的“python 批量对 cad 修改”“cad 图纸合并”,其实和 text-to-cad 是同一类需求的不同侧面。批量修改可以用脚本遍历文件、改参数、重新导出;图纸合并可以用脚本把多个模型导入同一装配。这些都可以纳入 text-to-cad 的工具链,形成一套完整的自动化方案。
6.4 当前局限与务实预期
必须承认,text-to-cad 目前还做不到“任意描述生成任意模型”。它擅长的是规则明确、参数化程度高的零件。遇到自由曲面、复杂装配、多物理场耦合,仍然需要人工建模。把预期放在“辅助工具”而不是“替代工程师”,心态会稳很多。
6.5 后续可以扩展的方向
如果这套流水线跑通了,后面可以往几个方向扩展:一是增加更多零件模板,覆盖常见机械件;二是接入材料库和成本估算,生成模型时顺便算重量和价格;三是和版本管理系统结合,每次生成自动提交;四是做 Web 界面,让非技术同事也能输入文本生成模型。
我在实际使用中最大的体会是,text-to-cad 的难点不在“生成”,而在“约束”。把参数范围、几何规则、格式要求约束好,生成就是水到渠成的事。反过来,如果约束没做好,生成再多模型也是废品。所以如果你准备动手做,先把参数模式和校验规则写扎实,比急着接语言模型更重要。