news 2026/10/27 10:18:24

text-to-cad 实战:从自然语言到 STEP/DXF/URDF 的几何内核链路

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
text-to-cad 实战:从自然语言到 STEP/DXF/URDF 的几何内核链路

1. 从一段文字到可制造模型:text-to-cad 到底在解决什么问题

把"用嘴画图"这件事说清楚,得先承认一个现实:绝大多数工程师每天花在建模上的时间,有相当一部分是重复劳动。画一个法兰、一根轴、一块带孔安装板,尺寸不同但拓扑结构几乎一样,鼠标点来点去半小时就没了。text-to-cad 这个方向之所以最近被反复提起,本质上就是冲着这类"结构固定、参数变化"的零件来的——你用自然语言描述需求,程序把它翻译成参数化的 CAD 实体,最后导出成 STEP、DXF 或者 URDF 这类下游能直接吃的格式。

它不是一个"AI 帮你从零设计一台发动机"的魔法,而是一条文本意图 → 结构化参数 → 几何内核建模 → 标准格式导出的流水线。理解这条流水线的每一环,比会调某个具体工具重要得多。因为工具会换,几何内核的脾气不会变。

适合读这篇内容的人大概分三类:一是做机械设计、夹具工装、钣金展开的工程师,想把手头重复建模自动化;二是做机器人仿真的同学,需要批量生成 URDF 里的连杆几何;三是写脚本的开发者,想搞清楚怎么把大模型的输出接到真实的 CAD 内核上,而不是停在"生成一段看起来像代码的东西"。

关键词里出现的 STEP、URDF、DXF 其实对应了三个完全不同的下游场景,这一点很多人一开始会混淆。STEP 是通用三维实体交换格式,给机械加工和装配用;DXF 是二维图纸和激光切割、线切割的通用语言;URDF 是机器人描述格式,里面既有几何也有运动学树。text-to-cad 要落地,必须明确自己输出的是哪一种,因为三者的建模约束、精度要求、坐标系约定完全不同。下面我会把这条链路拆开讲,包括几何内核怎么选、参数怎么校验、导出时哪些坑最容易翻车。

2. 文本到几何的翻译层:为什么不能直接让大模型吐坐标

2.1 大模型擅长的是意图,不是几何精度

很多人第一反应是让大模型直接输出一串顶点坐标或者一段 OpenSCAD 代码。我试过,短零件还行,稍微复杂一点就开始胡编——孔的位置对不上,圆角半径和板厚打架,导出的实体甚至是自相交的。原因很简单:大模型的强项是理解"我要一块 100×60×8 的板,四角各一个 M6 通孔,孔中心距边 12mm"这种语义和约束,它不擅长在连续空间里保证几何自洽。

所以正确的分工是:大模型负责把自然语言解析成一份结构化的参数清单(JSON 或 YAML),几何内核负责根据这份清单真正把实体算出来。中间这层解析,才是 text-to-cad 真正的技术核心。

一份合格的中间参数清单大概长这样:

{ "part_type": "mounting_plate", "length": 100.0, "width": 60.0, "thickness": 8.0, "holes": [ {"type": "through", "diameter": 6.6, "x": 12.0, "y": 12.0}, {"type": "through", "diameter": 6.6, "x": 88.0, "y": 12.0}, {"type": "through", "diameter": 6.6, "x": 12.0, "y": 48.0}, {"type": "through", "diameter": 6.6, "x": 88.0, "y": 48.0} ], "fillets": {"corner_radius": 3.0}, "units": "mm" }

注意这里 M6 通孔我写的是 6.6 而不是 6.0。这是机械行业的常识:M6 螺栓的公称直径是 6mm,但通孔要留间隙,标准间隙孔是 6.6mm(中等装配)。如果让大模型直接生成,它十有八九给你写 6.0,装都装不进去。这类行业默认规则必须写进解析层的提示词或者后处理规则里,不能指望模型自己懂。

2.2 参数校验层:把错误挡在建模之前

参数清单出来之后,别急着丢给内核。先过一遍校验,这一步能省掉大量调试时间。我一般会检查这几类:

  • 尺寸合理性:长宽厚是否为正,孔直径是否小于板宽,孔中心到边的距离是否大于孔径的一半加最小壁厚。
  • 约束冲突:圆角半径是否超过最短边的一半,否则倒角会失败。
  • 单位一致性:全部统一到毫米,避免出现英寸混进来的情况。
  • 特征干涉:两个孔是否重叠,孔是否落在圆角区域里。

这些校验用纯 Python 就能写,不需要几何内核参与。好处是报错信息清晰——"孔中心距边 3mm 小于最小壁厚 4mm",比内核抛出的"boolean operation failed"有用一百倍。

提示:把校验规则做成可配置的规则表,不同零件类型挂不同的规则集。钣金件的规则和机加工件完全不同,混在一起会互相误伤。

2.3 提示词工程在 CAD 场景的特殊性

给大模型写提示词,在 CAD 场景下和写文案是两码事。核心是把行业默认值显式化。比如"倒角"这个词,机加工里可能是 0.5×45°,钣金里可能是 R 角,注塑件里又是拔模。你不说清楚,模型就随机选一个。

我的做法是维护一份"术语映射表",把用户口语里的词映射到标准参数:

用户说法标准解析默认值
打个孔through_hole直径按螺栓规格查表
倒个角chamfer0.5mm × 45°
圆角filletR3
沉头孔countersink按螺栓头角度 90°
攻丝tapped_hole按螺纹规格

这张表是 text-to-cad 项目里最值钱的东西之一,因为它把模糊的自然语言锚定到了确定的工程参数上。表越细,输出越稳。

3. 几何内核选型:OpenCASCADE、CadQuery 还是直接调商业内核

3.1 三种主流路线的真实差异

文本解析完了,得有个东西真正把实体算出来。这一步的选择直接决定了项目的天花板。目前主流就三条路:

第一条是 OpenCASCADE(OCCT),开源三维几何内核里的老大哥,功能全,B-Rep 实体、布尔运算、倒角圆角、STEP 导入导出都支持。缺点是 API 偏底层,C++ 写起来啰嗦,学习曲线陡。适合对几何精度要求高、需要深度定制的场景。

第二条是 CadQuery,它其实是 OCCT 的 Python 封装,用链式 API 描述建模过程,写起来像在写 Python 而不是在调内核。比如一块带孔板:

import cadquery as cq result = ( cq.Workplane("XY") .box(100, 60, 8) .faces(">Z").workplane() .rect(76, 36, forConstruction=True) .vertices() .hole(6.6) .edges("|Z").fillet(3.0) ) cq.exporters.export(result, "plate.step")

这段代码的可读性非常好,而且它天然就是参数化的——把数字换成变量,text-to-cad 的解析层直接填参数就行。对绝大多数项目,CadQuery 是性价比最高的选择。

第三条是调商业内核,比如通过某些 CAD 软件的 API 驱动建模。优点是精度和功能有保障,缺点是依赖特定软件环境、授权成本高、自动化部署麻烦。除非你本来就在那个生态里,否则不建议作为首选。

3.2 为什么我最终倾向 CadQuery 而不是裸写 OCCT

裸写 OCCT 的坑在于,光是创建一个带孔的板,你就要处理 TopoDS_Shape、BRepPrimAPI、BRepAlgoAPI 这一堆类,代码量是 CadQuery 的五到十倍,而且一旦出错,堆栈信息基本看不懂。CadQuery 把这些封装掉了,同时保留了导出 STEP、STL、DXF 的能力。

更重要的是,CadQuery 的建模逻辑是声明式的,这跟 text-to-cad 的"参数清单 → 实体"思路天然契合。解析层输出 JSON,中间层把 JSON 映射成 CadQuery 的链式调用,几何层负责算,职责清晰。

当然 CadQuery 也有短板:复杂曲面、放样、扫掠这些高级特征支持不如原生 OCCT 完整,遇到特别复杂的零件还是得下沉到 OCCT。但对 text-to-cad 主要面向的"规则零件"场景,够用了。

3.3 内核能力边界:哪些零件不适合走这条路

得诚实地说,text-to-cad 不是万能的。以下几类零件,目前阶段硬上就是自找麻烦:

  • 自由曲面件:汽车覆盖件、消费电子外壳这种,靠文字描述根本说不清,得靠草图加曲面建模。
  • 高度依赖装配关系的件:一个零件的形状取决于它和另外五个零件的配合,这种上下文文字很难完整表达。
  • 拓扑结构随参数突变的件:参数稍微一变,特征数量就变了,这种参数化本身就难写。

认清边界,把精力放在"结构固定、参数变化"的零件上,项目成功率会高很多。法兰、轴套、安装板、支架、简单的齿轮、钣金展开件,这些才是 text-to-cad 的主战场。

4. 三种导出格式的实战差异:STEP、DXF、URDF 各管一段

4.1 STEP:机械加工和装配的通用语言

STEP(.step / .stp)是三维实体交换的事实标准,几乎所有的 CAD 软件都能读。text-to-cad 导出 STEP 时,有几个细节必须注意。

第一是单位。STEP 文件头里会写明单位,但不同内核默认值不一样。OCCT 默认是毫米,但如果你从别的地方导入过模型,可能被改成米。导出前一定要显式设置单位,否则下游打开发现零件大了 1000 倍。

第二是精度。STEP 支持 B-Rep 精确表示,导出时有个线性偏差(linear deflection)参数,值越小曲面越精细但文件越大。对平面为主的零件,这个参数影响不大;对带圆柱面的零件,建议设到 0.01mm 级别。

第三是坐标系。导出时零件的原点在哪、朝向如何,直接影响下游装配。我的习惯是让零件的第一特征基准面落在 XY 平面,Z 轴朝上,原点放在零件的几何中心或者一个明确的基准角上,并在文件名或元数据里注明。

# 导出 STEP 时显式控制精度和单位 cq.exporters.export( result, "plate.step", tolerance=0.01, angularTolerance=0.1 )

4.2 DXF:二维图纸和切割下料的通道

DXF 是二维格式,很多人以为从三维模型"投影"一下就行,实际上坑不少。text-to-cad 生成 DXF 主要有两个用途:一是出二维工程图给加工厂,二是给激光切割、线切割、等离子切割做下料图。

下料图的关键是轮廓必须闭合且无自相交。三维实体投影到二维后,经常出现重叠线、微小间隙、重复顶点,切割机读到这种图直接报错。所以导出 DXF 后,通常还要做一轮清理:合并重合点、删除重复线段、检查闭合性。

# 从 CadQuery 的二维工作平面导出 DXF cq.exporters.export( result.faces(">Z").wires(), "plate_profile.dxf" )

如果是钣金展开件,还要考虑折弯扣除(bend deduction)。展开长度不是简单的边长相加,得按材料厚度、折弯半径、折弯角度查表扣减。这块规则因材料和工艺而异,必须做成可配置的参数,不能写死。

4.3 URDF:机器人仿真里的几何与运动学

URDF 是机器人描述格式,它和 STEP、DXF 的本质区别在于:URDF 描述的不只是几何,还有连杆之间的运动学关系。一个 URDF 文件里,每个 link 有视觉几何(visual)、碰撞几何(collision)、惯性参数(inertial),joint 定义了父子 link 怎么连接、绕哪个轴转、转动范围多少。

text-to-cad 生成 URDF 时,几何部分通常导出成 STL 或 DAE,然后在 URDF 里引用:

<link name="base_link"> <visual> <geometry> <mesh filename="base_link.stl" scale="1 1 1"/> </geometry> <origin xyz="0 0 0" rpy="0 0 0"/> </visual> <collision> <geometry> <mesh filename="base_link.stl"/> </geometry> </collision> <inertial> <mass value="1.5"/> <inertia ixx="0.001" ixy="0" ixz="0" iyy="0.002" iyz="0" izz="0.002"/> </inertial> </link>

这里最容易翻车的是惯性参数。很多人随便填个质量就完事,结果仿真里机器人抖得像筛糠。惯性张量必须根据实际几何和质量分布算,CadQuery 生成的实体可以调 OCCT 的质量属性接口拿到体积和质心,再乘以密度得到质量和惯性矩。

另一个坑是坐标系约定。URDF 里 Z 轴朝上,但很多 CAD 软件默认 Y 轴朝上。导出前必须做坐标变换,否则导入仿真环境后机器人是躺着的。这个变换矩阵要写死在导出流程里,别指望手动改。

格式维度主要用途关键注意点
STEP三维加工、装配、跨软件交换单位、精度、坐标系
DXF二维图纸、切割下料轮廓闭合、折弯扣除
URDF三维+运动学机器人仿真惯性参数、坐标约定

5. 把整条链路串起来:一个可复现的最小实现

5.1 项目结构设计

讲了这么多原理,得给一个能跑起来的东西。下面这套结构是我实际用过的,不依赖任何商业软件,纯 Python 生态:

text-to-cad/ ├── parser/ │ ├── llm_parser.py # 自然语言 → JSON 参数 │ └── schema.json # 参数清单的 schema 定义 ├── validator/ │ └── rules.py # 参数校验规则 ├── builder/ │ ├── plate.py # 各类零件的建模函数 │ ├── flange.py │ └── shaft.py ├── exporter/ │ ├── step_export.py │ ├── dxf_export.py │ └── urdf_export.py └── main.py # 串起整条链路

核心思路是按零件类型分模块。每种零件有自己的参数 schema、校验规则和建模函数。新增一种零件,就是加一个模块,不动其他代码。这种结构在零件种类多起来之后优势非常明显。

5.2 从一句话到 STEP 文件的完整流程

假设用户输入:"做一块 120×80×10 的安装板,四角 M8 通孔,孔中心距边 15mm,四角 R5 圆角。"

第一步,解析层把它变成 JSON:

{ "part_type": "mounting_plate", "length": 120.0, "width": 80.0, "thickness": 10.0, "hole_spec": "M8", "hole_edge_distance": 15.0, "corner_radius": 5.0 }

注意这里我没有直接给孔直径,而是给了"M8"这个规格。解析层内部有一张螺栓规格表,M8 对应的通孔直径是 9.0mm(中等装配)。这样用户用行业语言描述,系统自动补全工程参数。

第二步,校验层检查:孔中心距边 15mm,孔径 9mm,半孔 4.5mm,壁厚余量 15-4.5=10.5mm,大于最小壁厚要求,通过。圆角 R5,最短边 80mm,R5 远小于 40mm,通过。

第三步,建模层调用 CadQuery:

def build_mounting_plate(p): plate = cq.Workplane("XY").box(p["length"], p["width"], p["thickness"]) d = p["hole_edge_distance"] hole_d = BOLT_TABLE[p["hole_spec"]]["clearance"] plate = ( plate.faces(">Z").workplane() .rect(p["length"] - 2*d, p["width"] - 2*d, forConstruction=True) .vertices() .hole(hole_d) .edges("|Z").fillet(p["corner_radius"]) ) return plate

第四步,导出 STEP,显式指定精度和单位。

整条链路跑下来,从输入文字到拿到 STEP 文件,几秒钟的事。对比手动建模,效率提升是数量级的。

5.3 批量生成:text-to-cad 真正的价值所在

单个零件自动化,省的时间有限。text-to-cad 真正的杀手锏是批量。比如你有一张 Excel 表,列了 50 种规格的法兰,每个规格的孔径、螺栓数、法兰外径都不同。手动建模要一整天,用这套流程,读表、循环、导出,几分钟搞定。

import pandas as pd df = pd.read_excel("flange_specs.xlsx") for _, row in df.iterrows(): params = row.to_dict() if not validate_flange(params): print(f"跳过 {params['part_no']}:参数校验失败") continue model = build_flange(params) cq.exporters.export(model, f"output/{params['part_no']}.step")

这里有个经验:批量任务一定要做失败隔离。某个零件参数有问题,不能让整个批次崩掉。用 try-except 包住单个零件的处理,记录失败原因,继续跑下一个。跑完统一看失败清单,比中途崩溃重跑高效得多。

6. 踩过的坑与参数调优经验

6.1 倒角和圆角失败:几何内核最常见的报错

倒角(chamfer)和圆角(fillet)是几何内核最容易失败的操作,没有之一。失败原因通常有几类:

  • 半径过大:圆角半径超过了相邻面的尺寸,内核算不出来。比如 10mm 厚的板要倒 R8 的角,两边加起来 16mm 超过厚度,必失败。
  • 相邻特征干涉:圆角区域和孔、槽重叠,内核无法确定边界。
  • 微小边:模型上存在长度接近零的边,倒角时数值不稳定。

我的处理策略是先校验再建模,把能预判的失败挡在前面。对于无法预判的,用 try-except 捕获,失败时自动降低圆角半径重试,并记录日志。实测下来,自动降级重试能救回大部分边缘情况。

注意:圆角操作尽量放在建模流程的最后。先做孔、槽这些特征,最后统一倒圆角,能减少干涉。如果先倒角再打孔,孔穿过圆角区域时经常出问题。

6.2 单位混乱:一个让零件大一千倍的隐形杀手

单位问题我踩过不止一次。CadQuery 默认毫米,但如果你从 STL 导入一个模型,STL 本身不带单位信息,内核可能按默认值解释。更隐蔽的是,有些解析层输出的 JSON 里,用户说的是"10 厘米",模型直接当 10 毫米处理,零件小十倍。

解决办法是在参数清单里强制带单位字段,解析层负责把所有输入统一换算成毫米。校验层再检查一遍数值范围——一个安装板长度 0.1mm 或者 10000mm,明显不正常,直接报警。

6.3 URDF 惯性参数:仿真抖动的元凶

前面提过 URDF 的惯性参数,这里展开说。惯性张量是个 3×3 对称矩阵,六个独立分量。对于规则几何,可以用公式算,比如长方体绕中心轴的转动惯量是 m(a²+b²)/12。但如果是复杂形状,手算不现实。

CadQuery 基于 OCCT,可以拿到实体的体积和质心,但惯性矩需要额外计算。一个实用做法是把实体离散成三角网格,用网格的体积分算惯性张量。或者更简单,用包围盒近似——对仿真精度要求不高的场景,用包围盒的惯性参数够用了。

关键是别填零。惯性张量全填零,仿真求解器会直接报奇异矩阵错误,或者算出无穷大的加速度。哪怕用包围盒近似,也比填零强。

6.4 大模型输出的不确定性怎么压住

大模型每次输出可能不一样,这对工程应用是致命的。同一个需求,今天生成 6.6 的孔,明天生成 6.0,下游加工就乱了。

压制不确定性的手段有几个:一是降低温度参数,让输出更确定;二是用 schema 约束输出格式,强制模型按固定结构返回;三是后处理归一化,把模型输出映射到标准值。比如孔直径,不管模型给什么,都按螺栓规格表重新查一遍,用标准值覆盖。

最后一道防线是人工确认。对关键零件,生成参数清单后让工程师过一眼再建模。全自动适合大批量规则件,关键件还是得有人把关。

7. 这套东西后续还能往哪走

把 text-to-cad 跑通之后,能扩展的方向不少。往上游走,可以接 PLM 或 ERP 系统,从物料清单直接驱动建模;往下游走,可以接 CAM 软件,自动生成加工刀路;往横向走,可以加装配约束求解,让多个零件自动装配到位。

我个人最看好的一个方向是和参数化设计库结合。现在很多企业有自己的标准件库、通用件库,把这些库和 text-to-cad 打通,用户说一句"用标准法兰 DN50",系统直接从库里调参数建模,一致性和复用率都能上去。

另一个实用方向是反向解析。给一张二维图纸或者一个现有 STEP 文件,反推出参数清单,然后就能批量改参数生成系列件。这个在改型设计里特别有用——老产品改个尺寸,不用重新建模,改参数就行。

技术选型上,如果你的团队 Python 基础好,CadQuery 是首选;如果对几何精度有极致要求,或者要处理复杂曲面,那就得下沉到 OCCT 甚至考虑商业内核。没有银弹,看场景。

最后分享一个我自己的习惯:每做一个新零件类型,先手动在 CAD 软件里建一遍,把每一步操作和参数记下来,再翻译成代码。这样写出来的建模函数,逻辑和人工操作一致,出问题时也容易对照排查。跳过这一步直接写代码,往往会在几何细节上反复栽跟头。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/18 10:24:03

HTTP/2帧解析利器:hyperframe核心机制与排障实践

做 HTTP/2 抓包、协议调试或者自己动手写代理网关的人&#xff0c;早晚都会撞上 python-hyper 这套生态。这套代码里专门负责帧结构解析的&#xff0c;就是 Hyperframes 项目&#xff0c;在 Python 侧包名通常写作hyperframe。它解决的问题非常纯粹&#xff1a;把 HTTP/2 连接里…

作者头像 李华
网站建设 2026/10/27 10:17:16

Android Studio Panda安装配置与Gradle踩坑全指南

做安卓开发这些年&#xff0c;每次换电脑或者给新同事配开发环境&#xff0c;最让人头大的永远是第一步——装Android Studio。上周我刚好搜了一下版本更新&#xff0c;发现Google稳定通道已经悄悄更新到了Android Studio Panda 1 | 2025.3.1 Patch 1。按我自己的习惯&#xff…

作者头像 李华
网站建设 2026/10/12 14:19:49

从零搭建大模型上下文管理系统:context-mode实战指南

如果你最近在折腾 AI 编程助手或者大模型应用&#xff0c;肯定没少听到 context-mode 这个词。我最早被这个词搞晕&#xff0c;是在连续两个项目里分别撞上同一个问题&#xff1a;和 AI 聊了三十分钟之后&#xff0c;它开始忘记最初的需求&#xff1b;把一份项目文档喂进去之…

作者头像 李华
网站建设 2026/10/27 10:17:50

ponytail插件与ponytail skill实战:轻量级开发工作流增强指南

1. 从“ponytail”这个热词说起&#xff1a;它到底是什么 第一次看到“ponytail”这个词挂在热搜上的时候&#xff0c;我下意识以为是某个发型教程火了。马尾辫嘛&#xff0c;谁不会扎。但点进去一看&#xff0c;讨论的压根不是美发&#xff0c;而是一套在开发圈子里悄悄传开的…

作者头像 李华
网站建设 2026/10/12 4:45:14

Superpowers:四件套AI编程工具链的协同原理与实战部署

1. “Superpowers”不是超能力&#xff0c;而是开发者工具链的隐喻式命名 你搜“superpowers”&#xff0c;第一反应可能是漫威电影里那些炫酷的异能——但在这个语境下&#xff0c;它压根不指代任何玄学能力&#xff0c;而是2024年开发者圈里悄然流行起来的一套 智能编程辅助…

作者头像 李华
网站建设 2026/10/14 2:06:58

Superpowers 安装配置指南:打造高效开发工作流

1. 从“superpowers”这个标题说起&#xff1a;它到底是什么 第一次看到“superpowers”这个词&#xff0c;很多人脑子里蹦出来的可能是超级英雄电影里的超能力&#xff0c;或者某个游戏里的技能系统。但如果你是在技术社区、开源项目或者工具链的语境下看到它&#xff0c;那它…

作者头像 李华