首页 / 资讯中心 / 文章详情

text-to-cad 实战:从文本到 DXF/STEP/URDF 的自动化建模指南

text-to-cad 实战:从文本到 DXF/STEP/URDF 的自动化建模指南 ★ FEATURED ARTICLE
1. 从一句话到三维模型text-to-cad 到底在解决什么问题第一次听到 “text-to-cad” 这个词很多人脑子里蹦出来的画面可能是对着电脑说一句“给我画个法兰盘”屏幕上就自动生成一张工程图。这个想象方向没错但真正的落地形态比“语音画图”要务实得多。text-to-cad 的核心是把自然语言描述或结构化文本转换成 CAD 软件能够识别和编辑的几何模型文件常见的输出格式包括 STEP、DXF、URDF 等。它解决的不是“替代设计师”而是“把重复性建模劳动自动化”。我最早接触这个方向是因为手头有一批参数化零件需要批量出图。每个零件的差别只有几个尺寸但要在 CAD 里一个个改草图、拉伸、倒角一天下来眼睛都花了。后来我尝试用脚本读取表格里的参数自动生成 DXF 轮廓再导入 CAD 做后续处理。这套思路其实就是 text-to-cad 的雏形——用文本承载设计意图用程序驱动几何生成。它适合什么人如果你是会写一点 Python 的工程师、需要批量处理图纸的工艺员、做机器人仿真需要生成 URDF 的开发者或者单纯想从“手工点鼠标建模”升级到“脚本化建模”的 CAD 使用者这个方向都值得花时间研究。它不要求你是计算机专业出身但需要你愿意理解“几何描述语言”和“CAD 文件结构”这两件事。目前 text-to-cad 的典型应用场景有这么几类一是参数化标准件库的批量生成比如螺栓、法兰、型材截面二是机器人领域的 URDF 模型快速搭建用文本描述连杆尺寸和关节位置三是二维图纸的自动化绘制比如根据坐标点生成 DXF 轮廓用于激光切割四是概念阶段的快速几何验证把文字描述转成 STEP 模型先看大体形状对不对再进 CAD 精修。注意text-to-cad 不是“AI 一键出图”那种营销概念。它更像是一套“文本到几何”的翻译规则你需要定义清楚文本的语法、几何的生成逻辑、以及输出文件的格式规范。做得好不好取决于你对 CAD 几何内核和文件格式的理解深度。2. 核心思路拆解文本如何变成几何2.1 三种主流技术路线对比把文本变成 CAD 模型目前有三条比较成熟的路子各有各的适用场景和坑。路线核心原理输出格式适合场景上手难度参数化脚本驱动用 Python 等语言调用 CAD 的 API按参数生成几何STEP、DXF、原生格式标准件批量生成、参数化建模中等几何描述语言解析定义一套文本语法解析后映射为几何图元DXF、SVG二维轮廓、切割图纸较低模板替换法预置 CAD 模板文件用文本替换其中的参数变量原生格式、STEP系列化产品改型较低我个人的经验是如果你要做三维实体参数化脚本驱动最稳如果只是二维轮廓几何描述语言解析更快如果公司已经有成熟的模板体系模板替换法落地成本最低。三条路线不是互斥的实际项目里经常混着用。2.2 为什么 STEP 和 DXF 是两大核心输出格式热词里反复出现 STEP 和 DXF这不是偶然。STEP 是三维实体交换的事实标准几乎所有主流 CAD 软件都能读写它记录的是 B-rep边界表示几何包含完整的曲面和实体信息。你用脚本生成的 STEP 文件丢进 SolidWorks、中望 CAD、Fusion 360 里都能打开继续编辑。DXF 则是二维图纸和轮廓数据的通用格式激光切割、线切割、钣金展开这些工序基本都认 DXF。它的结构比 STEP 简单得多本质上是“图层 图元”的集合图元包括直线、圆弧、多段线、文字等。用 Python 的ezdxf库就能直接写 DXF不需要装 CAD 软件。URDF 则是机器人领域的专用格式全称是 Unified Robot Description Format。它用 XML 描述机器人的连杆、关节、坐标系和碰撞体。热词里“urdf导入coppeliasim”说明很多人是在做仿真时遇到这个需求的。URDF 本身不包含复杂曲面主要是用基本几何体立方体、圆柱、球和网格文件来近似机器人结构。提示如果你生成的 STEP 模型要在 CAD 里做后续特征操作注意检查曲面的连续性和实体的封闭性。脚本生成的几何经常出现“面没缝合”或“实体不封闭”的问题导入后会变成曲面片而不是实体。2.3 文本描述的结构化设计text-to-cad 能不能用好关键看你的文本描述设计得够不够“机器友好”。纯自然语言比如“画一个直径 50 毫米、厚度 10 毫米的圆盘”对人来说很直观但对程序来说歧义太多。更靠谱的做法是设计一套结构化文本格式比如 JSON 或 YAML{ type: flange, outer_diameter: 100, inner_diameter: 50, thickness: 10, bolt_holes: { count: 6, diameter: 8, pcd: 75 } }这种格式的好处是字段名明确、单位统一、嵌套结构清晰。程序解析时不需要做自然语言理解直接按字段取值就行。如果你确实想用自然语言建议至少加上关键词提取和参数映射这一层把“直径 50”映射到diameter: 50把“厚度 10”映射到thickness: 10。我试过用正则表达式从中文描述里提取尺寸参数对于格式比较固定的输入比如“外径100 内径50 厚10 6个直径8的孔 节圆75”提取准确率能到 90% 以上。但一旦描述方式变化比如“100外径50内径厚度10mm均布6个8mm孔”规则就要重新写。所以结构化文本是正路自然语言是辅助。3. 实操环境搭建与工具选型3.1 Python 生态里的 CAD 工具链做 text-to-cadPython 是目前最顺手的选择。几个核心库你得知道ezdxf读写 DXF 文件的首选API 设计得很直观文档也全。画直线、圆弧、多段线、标注、图层管理都支持。cadquery基于 OpenCASCADE 的参数化建模库用 Python 代码描述三维实体输出 STEP、STL 等格式。语法接近自然语言学习曲线平缓。build123dcadquery 的“精神续作”API 更现代支持上下文管理器和代数模式两种写法。numpy做几何计算时离不开坐标变换、向量运算、矩阵操作都靠它。trimesh处理网格文件STL、OBJ的利器做 URDF 的碰撞体简化时会用到。安装这些库不算复杂但cadquery 和 build123d 依赖 OpenCASCADE 的底层库在 Windows 上偶尔会遇到编译问题。我的建议是直接用 conda 装 cadquery能省掉很多依赖麻烦conda create -n text2cad python3.10 conda activate text2cad conda install -c conda-forge cadquery pip install ezdxf numpy trimesh如果你不想折腾环境也可以直接用FreeCAD 的 Python 控制台它内置了 OpenCASCADE 和 Draft 模块能直接写脚本生成几何。缺点是 FreeCAD 的 API 文档不如 cadquery 友好很多用法要靠翻源码和论坛。3.2 二维 DXF 生成的最小可用示例先从一个最简单的例子入手用 ezdxf 画一个带螺栓孔的法兰盘二维轮廓。import ezdxf import math doc ezdxf.new(R2010) msp doc.modelspace() outer_r 50 inner_r 25 bolt_count 6 bolt_r 4 pcd_r 37.5 # 画外圆和内圆 msp.add_circle((0, 0), outer_r) msp.add_circle((0, 0), inner_r) # 画螺栓孔 for i in range(bolt_count): angle 2 * math.pi * i / bolt_count x pcd_r * math.cos(angle) y pcd_r * math.sin(angle) msp.add_circle((x, y), bolt_r) doc.saveas(flange.dxf)这段代码跑完你会得到一个flange.dxf文件用任何 CAD 软件都能打开。关键点在于所有尺寸都是变量改几个数字就能生成不同规格的法兰。这就是 text-to-cad 的基本形态——文本代码驱动几何。注意ezdxf 默认的 DXF 版本是 R2010兼容性比较好。如果你要发给用老版本 CAD 的同事可以改成R2000。另外DXF 里的圆是用圆心和半径定义的但有些激光切割机只认多段线这时候需要用add_lwpolyline把圆离散成多段线。3.3 三维 STEP 生成的 cadquery 示例二维轮廓只能算“图纸自动化”真正体现 text-to-cad 价值的是三维实体。用 cadquery 生成一个法兰盘实体import cadquery as cq outer_d 100 inner_d 50 thickness 10 bolt_count 6 bolt_d 8 pcd 75 result ( cq.Workplane(XY) .circle(outer_d / 2) .circle(inner_d / 2) .extrude(thickness) .faces(Z) .workplane() .polarArray(pcd / 2, 0, 360, bolt_count) .hole(bolt_d) ) cq.exporters.export(result, flange.step)这段代码的逻辑很清晰在 XY 平面上画两个同心圆拉伸成环然后在顶面上用极坐标阵列打孔。cadquery 的链式调用让几何构建过程读起来像一句话这也是它比直接调 OpenCASCADE API 友好的地方。生成的 STEP 文件可以用中望 CAD、SolidWorks 等软件打开也能直接丢进切片软件做 3D 打印。如果你要做 URDF可以把 STEP 转成 STL再用 trimesh 简化网格最后写进 URDF 的collision和visual标签里。4. 完整实操流程从参数表到批量 DXF 图纸4.1 需求场景与数据准备假设你接到一个任务有一批钣金件需要激光切割每个零件的轮廓形状相同但长宽和孔位不同。工艺员给了你一张 Excel 表里面有 20 个规格的尺寸参数。你要做的是根据这张表批量生成 20 个 DXF 文件每个文件对应一个规格。Excel 表的结构大概是这样零件编号长度宽度孔1_X孔1_Y孔2_X孔2_Y孔直径P0012001002020180808P00225012025252259510........................这种表在制造业很常见手工画图的话20 个规格至少要半天。用脚本做写好模板后跑一遍只要几秒钟。4.2 脚本实现与关键细节我用 pandas 读 Excel用 ezdxf 画图核心代码如下import pandas as pd import ezdxf df pd.read_excel(parts.xlsx) for _, row in df.iterrows(): doc ezdxf.new(R2010) msp doc.modelspace() length row[长度] width row[宽度] hole_d row[孔直径] # 画外轮廓矩形 msp.add_lwpolyline([ (0, 0), (length, 0), (length, width), (0, width), (0, 0) ]) # 画两个孔 msp.add_circle((row[孔1_X], row[孔1_Y]), hole_d / 2) msp.add_circle((row[孔2_X], row[孔2_Y]), hole_d / 2) doc.saveas(foutput/{row[零件编号]}.dxf)这段代码有几个细节值得说第一外轮廓用add_lwpolyline而不是四条add_line。多段线在激光切割里更友好因为切割路径是连续的不需要抬刀。而且多段线可以设置闭合标志避免首尾点重复。第二孔的坐标是绝对坐标。如果你的 Excel 里给的是相对坐标需要先做坐标变换。我一般会在脚本里加一个判断如果坐标值小于长度和宽度就认为是绝对坐标如果出现负数就认为是相对某个基准点的偏移。第三输出目录要提前创建。doc.saveas不会自动建目录如果output/不存在会报错。加一行os.makedirs(output, exist_okTrue)就能解决。提示批量生成 DXF 时建议在文件名里带上关键尺寸比如P001_200x100.dxf。这样后期核对时不用打开文件就能知道规格省很多事。4.3 从 DXF 到 STEP 的进阶处理二维 DXF 只能满足切割需求如果你要做三维装配验证还需要把 DXF 轮廓拉伸成实体。这一步可以用 FreeCAD 的 Python 脚本做也可以用 cadquery 重新构建几何。我一般倾向于在 cadquery 里重新构建而不是从 DXF 导入。原因是 DXF 导入后经常出现线段不连续、圆弧方向错误等问题修复起来比重新画还麻烦。重新构建的好处是几何干净、参数可控而且可以直接输出 STEP。如果你确实需要从 DXF 转 STEPFreeCAD 的Draft和Part模块可以做到import FreeCAD import Draft import Part shape Draft.import_dxf(input.dxf) wire Draft.makeWire(shape) face Part.Face(wire) solid face.extrude(FreeCAD.Vector(0, 0, 10)) Part.export([solid], output.step)这段代码在 FreeCAD 的 Python 控制台里能跑但对 DXF 的图层和闭合性有要求。如果 DXF 里的轮廓没有闭合Part.Face会失败。所以批量处理前最好先用 ezdxf 检查一下多段线的闭合标志。5. URDF 生成与机器人仿真对接5.1 URDF 的文本结构解析URDF 本质上是 XML描述的是机器人连杆和关节的树状结构。一个最简单的两连杆机械臂 URDF 长这样robot namearm link namebase_link visual geometry cylinder radius0.05 length0.1/ /geometry /visual /link link namelink1 visual geometry box size0.3 0.05 0.05/ /geometry /visual /link joint namejoint1 typerevolute parent linkbase_link/ child linklink1/ origin xyz0 0 0.1 rpy0 0 0/ axis xyz0 0 1/ limit lower-1.57 upper1.57 effort10 velocity1/ /joint /robot关键字段是origin和axis。origin定义子连杆坐标系相对于父连杆的位置和姿态axis定义关节的旋转轴。这两个字段搞错了机器人在仿真里就会“散架”或者“乱转”。热词里“urdf导入coppeliasim”说明很多人是在 CoppeliaSim 里做仿真。CoppeliaSim 对 URDF 的支持还算友好但有几个坑一是网格文件的路径问题URDF 里引用的 STL 文件必须用相对路径而且要和 URDF 文件放在同一个目录下二是关节类型CoppeliaSim 对continuous类型的关节支持最好revolute需要设置好上下限。5.2 用脚本生成 URDF 的实操方法手工写 URDF 对于简单机器人还行一旦连杆数量超过 5 个手写就容易出错。用 Python 脚本生成 URDF 是更靠谱的做法。我一般用jinja2模板引擎先写一个 URDF 模板再用参数填充。模板文件robot.urdf.j2robot name{{ robot_name }} {% for link in links %} link name{{ link.name }} visual geometry box size{{ link.size }}/ /geometry /visual /link {% endfor %} {% for joint in joints %} joint name{{ joint.name }} type{{ joint.type }} parent link{{ joint.parent }}/ child link{{ joint.child }}/ origin xyz{{ joint.origin }} rpy{{ joint.rpy }}/ axis xyz{{ joint.axis }}/ /joint {% endfor %} /robotPython 脚本读取参数表渲染模板输出 URDF 文件。这种方式的优势是连杆尺寸和关节位置可以来自 Excel 或数据库改参数不用改模板。对于系列化机器人产品这套方法能省大量时间。注意URDF 里的单位是米和弧度不是毫米和度。如果你从 CAD 里导出的尺寸是毫米记得除以 1000。我见过有人直接把毫米写进 URDF结果机器人在仿真里大了 1000 倍找了半天才发现是单位问题。5.3 网格文件与碰撞体的处理技巧URDF 的visual和collision可以用基本几何体也可以用网格文件。基本几何体计算快但形状不精确网格文件精确但会拖慢仿真速度。我的经验是视觉用网格碰撞用简化几何体。具体做法是用 cadquery 生成精确的 STEP 模型导出 STL 作为visual然后用 trimesh 对 STL 做凸包或简化生成一个低面数的碰撞网格或者直接用包围盒作为collision。import trimesh mesh trimesh.load(link1.stl) hull mesh.convex_hull hull.export(link1_collision.stl)凸包的好处是计算快、不会出现穿透缺点是对于凹形零件会“填平”凹陷。如果你的零件有重要的凹槽可以用trimesh.decomposition做凸分解生成多个凸包组合。6. 常见问题与排查技巧实录6.1 DXF 文件打开后图形错位或缺失这是最常见的问题原因通常有三个一是单位设置不一致。ezdxf 默认的 DXF 单位是“无单位”但有些 CAD 软件会按英寸解释。解决办法是在创建 DXF 时设置$INSUNITS变量doc.header[$INSUNITS] 4 # 4 表示毫米二是图层被冻结或关闭。脚本生成的图元默认在0图层如果 CAD 当前图层被关闭图形就看不见。可以在脚本里显式创建图层并设置颜色doc.layers.add(轮廓, color7) msp.add_lwpolyline(..., dxfattribs{layer: 轮廓})三是坐标值超出视图范围。如果图形画在 (10000, 10000) 附近打开时可能显示空白。用 CAD 的“缩放全部”命令就能看到或者在脚本里把图形移到原点附近。6.2 STEP 文件导入后不是实体脚本生成的 STEP 文件导入 CAD 后有时是一堆曲面片而不是一个完整的实体。原因通常是曲面没有缝合或者实体没有封闭。cadquery 生成的实体一般是封闭的但如果你做了布尔运算比如打孔、切除可能会产生微小的缝隙。解决办法是在导出前做一次“缝合”和“修复”result result.clean()clean()会尝试合并共面的面、修复微小的缝隙。如果还不行可以用result.fix()做更彻底的修复但速度会慢一些。提示如果你用的是 FreeCAD 的 Part 模块可以用Part.Solid检查实体是否有效用Part.Shell检查曲面是否封闭。无效的实体在后续布尔运算中会出各种奇怪的问题。6.3 URDF 导入仿真环境后关节方向不对URDF 的关节方向由axis决定但轴的方向和坐标系的原点位置有关。如果origin的rpy设置不对即使axis写的是0 0 1关节也可能绕错误的轴旋转。我的排查方法是先在 URDF 里把每个连杆的visual设成不同颜色导入仿真后观察连杆的相对位置。如果某个连杆的位置明显偏了就是origin的xyz或rpy有问题。建议先用简单的方块和圆柱搭一个最小模型确认关节方向正确后再替换成精确的网格文件。另外CoppeliaSim 导入 URDF 时默认会把所有关节设为passive模式需要手动改成motor或position才能驱动。这个在 CoppeliaSim 的关节属性里改一下就行不是 URDF 的问题。6.4 批量生成时文件命名冲突或覆盖批量处理时如果两个零件的编号相同后生成的会覆盖先生成的。建议在文件名里加入时间戳或哈希值或者在脚本里加一个检查import os filename foutput/{part_id}.dxf if os.path.exists(filename): filename foutput/{part_id}_1.dxf更稳妥的做法是用零件编号 规格的组合命名比如P001_200x100.dxf。这样即使编号重复规格不同也不会覆盖。6.5 常见问题速查表问题现象可能原因排查方法解决措施DXF 打开空白图形在视图外或图层关闭缩放全部、检查图层移动图形到原点、打开图层STEP 导入是曲面实体未封闭或曲面未缝合检查实体有效性执行 clean/fix 修复URDF 关节乱转origin 或 axis 设置错误用彩色方块验证调整 rpy 和 axis批量生成覆盖文件名重复检查输出目录加入规格或时间戳尺寸差 1000 倍单位不一致检查 CAD 单位设置统一用毫米或米孔位偏移坐标系原点不同对比图纸和脚本坐标统一基准点7. 我踩过的坑与实操心得7.1 不要追求“全自动”半自动往往更实用我一开始的想法很激进能不能用自然语言处理把工艺员的描述直接转成 CAD 模型试了两个月发现准确率始终上不去。问题不在于 NLP 技术不行而在于工艺描述本身就有歧义。“打几个孔”到底是几个“均布”的起始角度是多少这些信息在人脑里是默认的但程序不知道。后来我改成“半自动”方案工艺员填一张结构化表格脚本读表格生成模型。表格的列名固定单位固定歧义就消除了。text-to-cad 的“text”不一定是自然语言结构化文本才是更可靠的输入。7.2 几何内核的坑比编程语言的坑多写 Python 脚本本身不难难的是理解几何内核的行为。比如布尔运算的顺序会影响结果倒角的半径不能大于相邻边的长度抽壳的厚度不能超过最小壁厚。这些限制在 CAD 软件里是交互式提示的但在脚本里只会抛一个异常有时候异常信息还看不懂。我的应对方法是把复杂几何拆成简单步骤每一步都做有效性检查。比如先拉伸一个方块检查是不是实体再打孔检查孔是不是穿透最后倒角检查倒角有没有失败。这样出问题时能快速定位是哪一步的几何操作有问题。7.3 版本兼容性是个隐形杀手DXF 有 R12、R2000、R2010 等多个版本STEP 有 AP203、AP214、AP242 等协议。不同 CAD 软件对版本的支持程度不一样。我遇到过用 R2010 生成的 DXF在老版本 CAD 里打不开也遇到过 AP242 的 STEP在某些软件里丢失颜色信息。现在的做法是DXF 统一用 R2000兼容性最好STEP 统一用 AP214支持颜色和图层大多数软件都认。如果客户有特殊要求再单独调整。7.4 脚本要留日志不然出了问题没法查批量生成 100 个文件如果第 57 个失败了没有日志的话你根本不知道是哪个参数出了问题。我在脚本里加了简单的日志import logging logging.basicConfig(filenamegenerate.log, levellogging.INFO) for _, row in df.iterrows(): try: # 生成逻辑 logging.info(f成功生成 {row[零件编号]}) except Exception as e: logging.error(f生成 {row[零件编号]} 失败: {e})这样跑完一遍打开日志就知道哪些成功了、哪些失败了、失败原因是什么。日志不用写得很复杂但一定要有。7.5 输出目录结构要提前规划批量生成的文件如果全堆在一个目录里找起来很痛苦。我一般按日期或批次建子目录output/ 2024-01-15/ P001_200x100.dxf P002_250x120.dxf logs/ generate_2024-01-15.log这样每次生成的成果和日志分开存放回溯的时候很方便。如果文件要发给别人直接打包整个日期目录就行。8. 这个方向还能怎么扩展text-to-cad 的边界远不止“生成 DXF 和 STEP”。往深了做有几个方向值得探索。一是和 PLM/PDM 系统对接。生成的模型自动上传到产品数据管理系统带上版本号和审批状态。这需要理解 PLM 的 API 和数据结构但一旦打通设计到生产的链路就短了很多。二是加入几何约束求解。现在的脚本生成是“参数驱动”尺寸改了模型就重建。但如果能加入约束求解比如“孔始终在边的中点”“两个面始终平行”模型的鲁棒性会更强。OpenCASCADE 有约束求解器但 Python 绑定不太完善需要花时间研究。三是用大语言模型做参数提取。虽然纯自然语言驱动 CAD 还不成熟但用 LLM 从工艺描述里提取参数是可行的。比如把“外径100内径50厚106个8mm孔均布在直径75的圆上”丢给 LLM让它输出 JSON准确率比正则表达式高很多。LLM 负责理解脚本负责生成几何这个分工比较合理。四是和 3D 打印切片软件联动。生成的 STEP 直接转 STL自动导入切片软件设置好打印参数输出 G-code。对于小批量定制化零件这条链路能省掉很多手工操作。我在实际项目里用得最多的还是“表格到 DXF”和“参数到 STEP”这两条链路。它们不炫酷但稳定、可控、容易维护。text-to-cad 的价值不在于替代设计师而在于把设计师从重复劳动里解放出来让他们有时间做真正需要创造力的工作。如果你也在做类似的事情建议先从一个小场景入手跑通一条完整链路再逐步扩展。
阅读完成 · 觉得有帮助?
咨询建站