尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

text-to-cad 实战:从自然语言到 CAD 模型的程序化建模流水线

text-to-cad 实战:从自然语言到 CAD 模型的程序化建模流水线 1. 从一段文字到三维模型text-to-cad 到底在解决什么问题第一次听到 “text-to-cad” 这个词很多人脑子里浮现的可能是“对着软件说一句话模型就自己长出来了”。这个理解方向没错但真正落到工程实践里它要解决的核心问题其实更具体把自然语言描述或结构化文本自动转换成 CAD 软件能识别的几何模型文件常见的输出格式包括 STEP、URDF、G-code 等。这件事的价值在于传统 CAD 建模依赖人工在图形界面里一步步拉伸、旋转、布尔运算一个中等复杂度的零件可能耗费几十分钟到几个小时而 text-to-cad 试图把“描述需求”和“生成几何”之间的鸿沟用程序填平。我最初接触这个方向是因为手头有一批参数化零件需要反复修改尺寸。每次改一个孔径都要打开 CAD 软件、找到对应特征、重新标注、再导出。后来我尝试用脚本来驱动建模再后来开始研究如何让文本直接映射到几何参数。实测下来text-to-cad 并不是要取代 CAD 工程师而是把重复性、规则性的建模工作自动化让人把精力放在真正需要判断力的地方。这篇文章适合三类人看一是经常需要批量生成或修改 CAD 模型的工程师二是做机器人仿真、需要快速产出 URDF 模型的开发者三是想了解文本驱动设计这一技术方向的爱好者。我会从整体设计思路讲起然后拆解核心细节、实操过程、常见问题最后分享一些踩坑经验。全文基于我在实际项目中的做法涉及具体参数和代码的地方都会给出可复现的方案。2. 整体设计思路为什么这样拆解 text-to-cad2.1 核心链路的四个环节把 text-to-cad 拆开看它本质上是一条流水线文本输入 → 语义解析 → 几何参数映射 → 模型文件输出。每个环节都有不同的技术选型和取舍。文本输入环节可以是纯自然语言比如“一个长 50mm、宽 30mm、高 20mm 的方块中心有一个直径 10mm 的通孔”也可以是结构化文本比如 JSON、YAML 或自定义 DSL。纯自然语言灵活但歧义多结构化文本精确但需要用户学习格式。我在实际项目中倾向于混合方案用自然语言做高层描述用结构化字段做精确参数补充。语义解析环节核心是把文本里的实体、尺寸、位置关系、约束条件提取出来。这里可以用规则引擎正则表达式加关键词匹配也可以用大语言模型做意图识别。规则引擎稳定、可预测但覆盖不了复杂表达大语言模型灵活但输出不稳定需要加校验层。我的做法是先用规则引擎处理 80% 的常见模式剩下的用模型兜底并且所有输出都必须通过参数合法性检查。几何参数映射环节是把解析出的语义转换成 CAD 内核能理解的参数。比如“通孔”对应的是圆柱体加布尔减运算“倒角”对应的是边缘处理操作。这一步需要你对目标 CAD 内核的 API 比较熟悉知道哪些操作支持参数化、哪些容易失败。模型文件输出环节根据用途选择格式。STEP 适合通用交换URDF 适合机器人仿真G-code 适合加工制造。不同格式对几何的要求不一样比如 URDF 通常要求模型是凸体或简单组合体G-code 则关注刀具路径而不是实体本身。2.2 为什么选择程序化建模而不是直接生成网格很多人会问为什么不直接用文本生成 STL 或 OBJ 网格那样不是更简单吗我的经验是网格模型虽然容易生成但后续编辑和参数化非常困难。你拿到一个 STL 文件想改一个孔的直径几乎等于重新建模。而 STEP 或 URDF 保留了几何特征和参数关系改一个数值就能重新生成整个模型。对于需要迭代设计的场景程序化建模的优势非常明显。另一个考虑是精度。网格模型用三角面片逼近曲面精度受面片数量限制而 CAD 内核用解析几何表示曲面精度是数学意义上的精确。对于配合件、运动副这些对精度敏感的场景必须用 CAD 格式。2.3 工具选型的逻辑我试过几种方案FreeCAD 的 Python API、OpenSCAD、CadQuery、以及一些商业 CAD 的脚本接口。最终在 text-to-cad 项目里主要用 CadQuery原因是它的 API 设计比较符合直觉链式调用写起来像在描述几何关系而且底层基于 OpenCASCADE输出的 STEP 文件质量很好。OpenSCAD 虽然也是程序化建模但它的 CSG 表示在复杂模型上容易遇到性能问题而且输出的网格格式居多。FreeCAD 功能全但 API 比较冗长调试起来不够顺手。CadQuery 在表达力和简洁性之间找到了不错的平衡点。对于 URDF 输出我通常先用 CadQuery 生成 STEP再用转换工具转成 URDF 的网格和碰撞体。G-code 则是在 STEP 基础上用切片软件或 CAM 模块生成。提示工具选型没有绝对的对错关键是看你的输出格式需求和团队的技术栈。如果团队已经在用 FreeCAD强行换 CadQuery 反而增加学习成本。3. 核心细节解析文本到几何的映射规则3.1 实体识别与尺寸提取文本里的实体通常对应基本几何体方块、圆柱、球、圆锥、圆环。尺寸提取的关键是识别数值和单位。我遇到过的坑包括用户写“50”没写单位默认按毫米处理还是按米处理我的做法是强制要求单位或者在系统配置里设默认单位并在输出时标注。尺寸的表达方式也很多样“长 50 宽 30 高 20”、“50x30x20”、“长度为 50mm宽度为 30mm高度为 20mm”。规则引擎需要覆盖这些常见模式。我一般会写一组正则表达式按优先级匹配匹配不到再交给模型处理。位置关系的表达更复杂“在中心”、“距离左边缘 10mm”、“与底面平齐”。这些需要转换成坐标值。我的做法是定义一个参考坐标系把相对位置转换成绝对坐标。比如“中心”默认是包围盒中心“左边缘”是 X 轴最小值位置。3.2 布尔运算与特征操作CAD 建模的核心操作是布尔运算并集、差集、交集。文本里的“打一个孔”对应差集“凸台”对应并集“相交部分”对应交集。特征操作包括倒角、圆角、抽壳、阵列等。这里有个容易忽略的细节布尔运算的顺序会影响结果。比如先打孔再倒角和先倒角再打孔最终几何可能不同。我在解析文本时会尽量保持用户描述的顺序如果顺序不明确就按“先加后减”的原则处理。另一个坑是特征操作的失败处理。倒角半径过大、抽壳厚度超过实体尺寸都会导致操作失败。我的做法是在执行前做参数检查比如倒角半径必须小于相邻边的最短长度抽壳厚度必须小于最小壁厚。3.3 参数化与约束表达text-to-cad 的真正威力在于参数化。文本里可以定义变量和关系比如“孔的数量为 N沿 X 轴均匀分布间距为 D”。解析后生成一个参数化模型改 N 或 D 就能自动更新。约束表达包括尺寸约束如“长度等于宽度的两倍”、几何约束如“两个面平行”、位置约束如“孔位于中心线上”。这些约束在 CAD 内核里通常通过表达式或参数关联实现。CadQuery 支持在代码里用 Python 变量和表达式所以映射起来比较自然。我通常会把用户输入的参数整理成一个字典然后在建模脚本里引用这些参数。这样既方便调试也方便后续批量替换。3.4 输出格式的适配STEP 输出相对直接CadQuery 的exportStep方法就能搞定。需要注意的是单位STEP 文件默认单位是毫米如果输入是英寸需要转换。URDF 输出复杂一些。URDF 描述的是机器人的连杆和关节需要把 CAD 模型拆分成多个连杆定义关节类型和运动范围。我的做法是如果用户描述的是一个整体零件就输出单个连杆如果描述的是装配体就按运动关系拆分。碰撞体通常用简化几何如包围盒或圆柱代替精确网格以提高仿真效率。G-code 输出需要 CAM 处理包括刀具选择、切削参数、路径规划。这部分我通常不直接生成而是输出 STEP 后导入 CAM 软件处理。如果一定要自动生成可以用 FreeCAD 的 Path 模块或 pyCAM 这类库。4. 实操过程从零搭建一个 text-to-cad 流水线4.1 环境准备与依赖安装我用的技术栈是 Python 3.10 CadQuery 2.4 正则表达式 可选的 LLM 接口。安装 CadQuery 最省事的方式是用 condaconda create -n text2cad python3.10 conda activate text2cad conda install -c conda-forge cadquery如果不用 conda也可以用 pip 安装但 CadQuery 依赖 OpenCASCADEpip 安装有时会遇到编译问题。我试过在 Ubuntu 和 Windows 上都用 conda比较稳。其他依赖包括re正则、json结构化输出、argparse命令行参数。如果要用 LLM 做语义解析还需要安装对应的 SDK。注意CadQuery 的版本更新比较快不同版本的 API 可能有差异。建议锁定一个稳定版本比如 2.4避免代码突然跑不起来。4.2 文本解析模块的实现先定义一个解析函数输入是文本字符串输出是结构化的几何描述字典。我通常按以下步骤处理预处理去除多余空格、统一单位表达、把中文标点转成英文标点。实体识别用正则匹配“方块”、“圆柱”、“孔”等关键词。尺寸提取匹配数值加单位的模式转换成毫米。位置提取匹配“中心”、“边缘”、“距离”等模式转换成坐标。操作提取匹配“打孔”、“倒角”、“阵列”等操作。举个例子输入“一个长 50mm、宽 30mm、高 20mm 的方块中心有一个直径 10mm 的通孔”解析结果大概是{ base: {type: box, length: 50, width: 30, height: 20}, features: [ {type: hole, diameter: 10, position: center, through: True} ] }这个字典就是后续建模的输入。4.3 几何生成模块的实现用 CadQuery 根据解析结果生成模型。核心代码如下import cadquery as cq def build_model(desc): base desc[base] if base[type] box: model cq.Workplane(XY).box(base[length], base[width], base[height]) elif base[type] cylinder: model cq.Workplane(XY).cylinder(base[height], base[radius]) for feat in desc[features]: if feat[type] hole: model model.faces(Z).workplane().hole(feat[diameter]) elif feat[type] fillet: model model.edges().fillet(feat[radius]) return model这段代码的关键点是工作平面的选择。faces(Z)表示选择 Z 轴正方向的面workplane()在该面上建立新的工作平面hole()打孔。如果孔不在中心需要用center()或moveTo()调整位置。4.4 输出与验证生成模型后导出 STEPcq.exporters.export(model, output.step)验证环节很重要。我通常会做三件事一是检查模型体积是否合理二是检查包围盒尺寸是否与输入一致三是用 CAD 软件打开确认几何正确。自动化验证可以用 CadQuery 的val().Volume()和val().BoundingBox()方法。如果输出 URDF还需要定义连杆和关节。我一般用urdfpy或yourdfpy库来生成 URDF 文件把 STEP 转成 STL 作为视觉网格用简化几何作为碰撞体。4.5 批量处理与参数扫描text-to-cad 的一个典型应用是批量生成不同参数的模型。比如生成一系列不同孔径的方块用于测试或展示。我的做法是把参数写成列表循环调用建模函数for d in [5, 10, 15, 20]: desc {base: {type: box, length: 50, width: 30, height: 20}, features: [{type: hole, diameter: d, position: center, through: True}]} model build_model(desc) cq.exporters.export(model, foutput_d{d}.step)这样几分钟就能生成几十个模型比手动建模快得多。5. 常见问题与排查技巧实录5.1 解析失败文本表达超出规则覆盖范围这是最常见的问题。用户说“打个洞”规则里只写了“打孔”就匹配不上。我的做法是维护一个同义词表把常见口语表达映射到标准术语。比如“洞”、“眼”、“穿孔”都映射到“孔”。如果同义词表也覆盖不了就交给 LLM 兜底但 LLM 的输出必须经过格式校验。另一个技巧是给用户提供反馈。解析失败时告诉用户哪部分没识别出来建议换一种说法。这样用户会逐渐学会用系统能理解的表达方式。5.2 几何操作失败布尔运算或特征操作报错布尔运算失败通常是因为两个实体没有相交或者相交区域太小导致数值不稳定。我的排查步骤是先单独显示两个实体确认它们的位置关系然后检查尺寸是否合理比如孔径是否大于零、是否小于基体尺寸最后尝试调整容差或简化几何。倒角失败常见原因是半径过大。比如一个 10mm 厚的板倒角半径 8mm 可能就会失败因为相邻边不够长。我的经验是倒角半径不要超过最小边长的三分之一。5.3 输出文件异常STEP 打开后几何缺失或变形STEP 文件的问题通常出在导出设置上。CadQuery 的exportStep默认精度够用但如果模型特别大或特别小可能需要调整。我遇到过一次导出后圆柱变成多边形原因是模型尺寸是微米级导出精度没跟上。解决办法是缩放模型到毫米级再导出。URDF 的问题通常是坐标系不对。URDF 要求每个连杆有自己的坐标系关节定义在两个连杆之间。如果坐标系搞错模型在仿真里会飞出去。我的做法是用check_urdf工具验证或者在 RViz 里可视化确认。5.4 性能问题大批量生成时速度慢CadQuery 单次建模通常几百毫秒到几秒但批量生成几百个模型时累计时间就很可观。优化方法包括复用 Workplane 对象、减少不必要的布尔运算、用多进程并行。我试过用multiprocessing并行生成速度提升明显但要注意 CadQuery 不是线程安全的必须用进程而不是线程。5.5 常见问题速查表问题现象可能原因排查方法解决方案解析结果为空文本表达不在规则内打印解析中间结果补充同义词或启用 LLM 兜底布尔运算失败实体不相交或容差问题单独显示实体调整位置或增大相交区域倒角失败半径过大检查相邻边长度减小半径至边长三分之一以下STEP 导出几何异常精度设置不当用 CAD 软件打开检查调整导出精度或缩放模型URDF 仿真异常坐标系或关节定义错误用 check_urdf 验证重新定义连杆坐标系批量生成速度慢单线程串行计时各环节耗时多进程并行或优化建模逻辑提示排查问题时先把中间结果打印出来。很多时候问题出在解析环节而不是建模环节。我踩过的坑里有一半是解析错了导致后续全错。6. 实操心得与避坑经验6.1 从简单场景开始逐步扩展我一开始就想做一个能理解任意描述的 text-to-cad 系统结果发现复杂度爆炸。后来调整为先支持几种基本几何体和常见操作把这条链路跑通再逐步增加实体类型和操作类型。这样每加一个功能都能快速验证不会因为一个问题卡住整个项目。6.2 参数校验比建模本身更重要建模代码写起来不难难的是保证输入参数合法。比如孔径不能为负、倒角半径不能超过壁厚、阵列数量不能太大导致内存溢出。我在建模函数入口加了一层校验所有参数先过一遍检查不合法就报错并提示原因。这样避免了很多莫名其妙的失败。6.3 保留中间结果便于调试解析结果、建模参数、导出设置这些中间数据我都会保存下来。出问题时可以快速定位是哪一步错了。我通常把解析结果存成 JSON建模脚本读 JSON 执行。这样解析和建模解耦调试时也可以手动改 JSON 测试建模逻辑。6.4 版本控制与回归测试text-to-cad 的代码和普通软件一样需要版本控制。我用的 Git每次修改解析规则或建模逻辑都提交。另外我建了一组测试用例覆盖常见输入和边界情况每次修改后跑一遍确保没有破坏已有功能。这个习惯帮我避免了好几次“改一个 bug 引入两个新 bug”的情况。6.5 与现有工作流集成text-to-cad 生成的模型最终要进入现有工作流。比如生成的 STEP 要导入 CAD 软件做后续处理生成的 URDF 要导入仿真环境。我在项目里预留了接口可以配置输出路径、文件命名规则、后处理脚本。这样生成的模型能直接进入下一步不需要手动搬运。7. 扩展方向text-to-cad 还能怎么用7.1 与参数化设计库结合如果团队有标准件库或常用结构库可以把 text-to-cad 和这些库结合。用户描述“一个 M6 螺栓孔”系统自动从库里调用标准孔特征。这样既保证规范性又提高效率。7.2 与仿真流程联动生成模型后自动导入仿真软件做分析比如结构强度、热传导、流体分析。这需要 text-to-cad 输出仿真软件能识别的格式并且自动设置边界条件和材料参数。我试过用 CadQuery 生成模型后导入 CalculiX 做简单分析流程是通的但自动化程度还不够高。7.3 与制造流程对接对于加工场景text-to-cad 可以输出 G-code 或加工工艺文件。这需要集成 CAM 功能考虑刀具、夹具、切削参数。目前我主要输出 STEP后续 CAM 处理还是用专业软件。如果要做全自动可以用 FreeCAD 的 Path 模块或开源的 CAM 库。7.4 多模态输入除了文本还可以支持草图、表格、甚至语音输入。比如用户画一个草图系统识别几何关系后生成参数化模型。或者用户填一个参数表系统批量生成模型。这些扩展方向都有实际需求但实现复杂度也更高。我在实际项目里最大的体会是text-to-cad 不是一个纯技术问题它需要理解用户的表达习惯、CAD 建模的规律、以及下游工作流的需求。技术只是工具真正有价值的是把这三者串起来。如果你也在做类似的事情建议先从一个小场景切入跑通后再扩展。不要一开始就追求大而全那样很容易卡住。
返回列表