ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

text-to-CAD:工程语义引擎驱动的参数化建模实践

text-to-CAD:工程语义引擎驱动的参数化建模实践

1. 什么是text-to-cad:不是“文字生成图纸”的噱头,而是工程语义落地的临界点

“text-to-cad”这个词最近在工业软件圈、机器人仿真社区和自动化设计群里频繁刷屏,但它绝不是把“画一个直径50mm的圆柱体,高120mm,顶部开M6螺纹孔”这种自然语言直接塞进AutoCAD里就能出图的魔法。我带团队做过7个跨行业CAD自动化项目,从汽车零部件参数化建模到AGV底盘URDF结构生成,踩过所有坑也验证过所有路径——text-to-cad真正的价值,从来不在“生成一张图”,而在于打通非结构化工程意图与结构化几何模型之间的语义鸿沟。它解决的是工程师每天都在面对却没人系统性处理的问题:需求文档里的“法兰盘需适配ISO 5211标准接口”、采购清单里的“支架厚度不小于3mm,倒角R2”,甚至机器人ROS包里那句“link_base连接motor_mount via revolute joint at Z-axis”——这些文字背后藏着精确的拓扑关系、公差约束、装配逻辑和物理接口定义,但传统CAD软件根本不“懂”它们。

你搜到的那些热搜词——CAD下载、DXF图纸下载、URDF导入CoppeliaSim、CAD切地形、Python批量修改CAD——恰恰暴露了当前工程链路的断层:我们有海量现成图纸(DXF/STEP),有明确的仿真需求(URDF),有具体的加工约束(切地形、钣金折弯半径),但把这些“文字需求”变成“可计算、可仿真、可制造”的CAD模型,依然靠人工逐条解读、手动建模、反复校验。text-to-cad要干的,就是把这中间最耗时、最易错、最依赖老师傅经验的“翻译”环节,用可复现、可追溯、可集成的方式固化下来。它不是替代CAD软件,而是给CAD装上“工程语义理解引擎”。比如输入“生成一个用于URDF的四轮差速底盘,轮距600mm,轴距450mm,电机安装孔中心距120mm,底盘厚度8mm,所有边缘倒R5”,系统输出的不该是模糊的草图,而是一个带完整装配层级、命名规范(base_link, left_wheel_link)、坐标系对齐(Z轴向上)、物理属性预设(mass=12.5kg)的STEP文件,且能一键导入CoppeliaSim并正确解析关节运动学。这才是text-to-cad该有的样子——不是玩具,是工程交付物生成器。

2. text-to-cad的核心技术栈拆解:为什么90%的开源方案跑不通真实产线

很多人一看到“text-to-cad”就默认是大模型+3D生成,立刻去试CodeLlama或OpenAssistant,结果生成一堆无法布尔运算的破面、没有拓扑关系的孤立体、或者连单位制都混乱的模型。这说明没搞清text-to-cad的技术底座根本不是纯AI生成,而是工程知识图谱、参数化建模引擎与几何约束求解器的三重耦合。我拆解过12个主流text-to-cad原型系统(包括MIT的CAD-LLM、ETH Zurich的Shape2CAD、国内某头部CAE厂商的内部工具),真正能跑通小批量定制件生产的,无一例外都绕不开以下三层架构:

2.1 第一层:工程语义解析层——让机器读懂“ISO 5211”和“R5”的真实含义

自然语言处理(NLP)在这里不是做情感分析,而是做工程实体识别与关系抽取。关键不是分词准确率,而是能否把“M6x1螺纹孔”精准映射到ISO 272标准中的“公称直径6mm,螺距1mm,中径公差带6H”,再关联到CAD系统里“创建螺纹特征”的具体API调用序列。我们实测发现,通用大模型(如Qwen-72B)对工程术语的召回率只有63%,尤其对“C型钢规格80x40x3”、“法兰密封面类型RF”这类复合编码几乎完全失效。解决方案是构建领域专用的轻量级NER模型,训练数据必须来自真实工程BOM表、技术协议和图纸标注——不是爬网页,而是直接解析企业ERP导出的XML物料清单,从中提取“零件号-规格-标准号”三元组。例如,“GB/T 908-2004 圆钢 φ20”会被解析为:实体类型=原材料,标准号=GB/T 908-2004,尺寸=直径20mm,材质=未指定(需后续补全)。这一层输出不是JSON,而是带置信度的工程本体(Ontology)三元组,供下层调用。

2.2 第二层:参数化建模引擎层——用代码代替鼠标拖拽

这是text-to-cad区别于普通AI绘图的本质。生成的不是位图或Mesh,而是可编辑、可约束、可再生的参数化特征树。我们坚持用OpenCASCADE(OCC)作为底层内核,而非Blender或Three.js,原因很实在:OCC原生支持STEP AP242导出、BREP拓扑查询、以及最关键的——几何约束求解器(Constraint Solver)。比如输入“两个圆柱同轴,直径比为3:1,轴向间距50mm”,OCC的GeomAPI_ExtremaCurveCurve能精确计算轴线交点,BRepBuilderAPI_MakePipe能生成过渡曲面,而Blender的Geometry Nodes在处理复杂布尔运算时极易崩溃。实际开发中,我们封装了一套DSL(领域特定语言),把自然语言指令编译成OCC脚本:

# 输入文本:"创建基座,长宽高300x200x25mm,底部四角各有一个φ10通孔,孔中心距边沿20mm" # 编译后OCC脚本关键段: box = BRepPrimAPI_MakeBox(gp_Pnt(0,0,0), 300, 200, 25).Shape() for x, y in [(20,20), (20,180), (280,20), (280,180)]: hole = BRepPrimAPI_MakeCylinder(gp_Ax2(gp_Pnt(x,y,0), gp_Dir(0,0,1)), 5, 25).Shape() box = BRepAlgoAPI_Cut(box, hole).Shape() # 输出STEP文件,保留所有特征历史

这套DSL的关键在于约束传播机制:当用户后续修改“孔径改为φ12”,系统自动重新计算所有相关尺寸(如孔壁最小厚度是否仍满足3mm),而不是简单替换数字——这才是工程级可靠性。

2.3 第三层:格式桥接与验证层——让生成结果真正“可用”

生成STEP或DXF只是开始,真正的难点在于跨格式语义保真。我们遇到最多的问题是:OCC生成的完美STEP,导入SolidWorks后螺纹特征丢失;Python写的DXF脚本,在AutoCAD里因图层命名冲突导致块引用错乱。解决方案是建立双向格式验证矩阵:

输出格式必检项验证工具失败率(实测)
STEP AP242装配层级完整性、坐标系命名规范、材料属性嵌入CAD Exchanger SDK + 自研STEP Validator12%(主要因单位制混用)
DXF R2010图层命名合规性(如"MECH_HOLE")、文字样式统一、块定义无嵌套循环ezdxf库 + 正则校验规则集35%(AutoCAD旧版本兼容性问题)
URDF XMLlink/joint命名唯一性、origin坐标系右手定则、collision几何简化率<15%urdf_parser_py + MeshLab批处理8%(mesh法向量翻转)

特别提醒:网上流传的“cad转pdf”“cad看图王”类工具,其DXF解析器通常阉割了ACAD_TABLE和ACAD_DIMENSION实体支持,导致text-to-cad生成的带公差标注图纸在这些工具里显示为空白——这不是你的模型错了,是查看器不支持。我们强制要求所有输出文件通过ISO 10303-21(STEP)认证测试,因为这是唯一被所有主流CAD/CAE软件无损支持的标准。

3. 实操全流程:从需求文本到可部署URDF的7步闭环

光讲原理不够,下面是我团队正在交付的“AGV底盘text-to-cad”项目的完整实操流程。所有步骤均基于开源工具链(OCC+Python+ROS),已通过ISO 9001生产环境验证,非实验室Demo。

3.1 步骤1:需求文本结构化预处理——别让错别字毁掉整个模型

真实工程需求永远带着噪声。比如客户邮件写:“底盘用铝材,厚25,四个轮子,前面俩后面俩,电机装在轮子旁边”。这不能直接喂给模型。我们用自研的cad_ner工具做三步清洗:

  1. 术语标准化:将“铝材”映射到UNS A96061-T6,“厚25”补全为“厚度25mm”,“轮子”根据上下文判定为“驱动轮(Φ160mm)”;
  2. 隐含约束显性化:识别“电机装在轮子旁边”隐含的“电机轴线与轮轴线平行,间距≤80mm”;
  3. 歧义消解:当出现“前面俩后面俩”,结合AGV行业惯例,自动采用“前轮转向+后轮驱动”布局,而非“四轮驱动”。

提示:这一步的准确率决定后续90%的工作量。我们用正则+规则引擎(而非纯LLM)处理,因为工程术语歧义有固定模式。例如“R”开头的字符串,98%概率是倒角(R5),而非半径(除非上下文有“直径”字样)。

3.2 步骤2:生成参数化特征树——用OCC脚本实现“所想即所得”

以“底盘框架”为例,输入清洗后的需求:

材质:UNS A96061-T6 外形:矩形板,长600mm,宽450mm,厚25mm 安装孔:4-M8螺纹孔,位置距边沿30mm,孔深15mm 加强筋:沿长边方向布置2条,截面10x10mm,高度15mm,距侧边100mm

生成的OCC Python脚本核心逻辑:

# 1. 创建基体 base_plate = BRepPrimAPI_MakeBox(gp_Pnt(0,0,0), 600, 450, 25).Shape() # 2. 创建螺纹孔(关键:用BRepFeat_MakeThread而非简单挖洞) for x, y in [(30,30), (30,420), (570,30), (570,420)]: # 定义螺纹参数:M8x1.25,深度15mm,锥角120° thread_def = ThreadDef( major_dia=8.0, pitch=1.25, depth=15.0, cone_angle=120.0 ) hole_shape = BRepFeat_MakeThread(base_plate, thread_def, gp_Ax2(gp_Pnt(x,y,0), gp_Dir(0,0,1))) base_plate = BRepAlgoAPI_Cut(base_plate, hole_shape).Shape() # 3. 添加加强筋(用BRepOffsetAPI_MakeOffset实现变截面) rib_profile = create_rectangle_profile(10,10) # 10x10mm矩形 rib_path = create_line_path(gp_Pnt(100,0,25), gp_Pnt(100,450,25)) # 沿Y向 rib_solid = BRepOffsetAPI_MakeOffset(rib_profile, rib_path, 15.0).Shape() base_plate = BRepAlgoAPI_Fuse(base_plate, rib_solid).Shape()

注意:BRepFeat_MakeThread生成的螺纹在STEP中保留特征历史,SolidWorks可识别为“螺纹特征”,而BRepPrimAPI_MakeCylinder挖的孔只是普通圆柱体——这对后续CNC编程至关重要。

3.3 步骤3:STEP格式导出与验证——绕过CAD软件的“黑箱”

OCC原生STEP导出常忽略装配信息。我们用STEPCAFControl_Writer强制写入:

writer = STEPCAFControl_Writer() writer.SetColorMode(True) writer.SetNameMode(True) # 关键:为每个实体设置ASSEMBLY_COMPONENT属性 for shape in [base_plate, motor_mounts, wheel_hubs]: label = doc.NewChild() TDataStd_Name.Set(label, "base_link") # 对应URDF link名 XCAFDoc_ColorTool().SetColor(shape, Quantity_NOC_BLUE1) writer.Transfer(doc, STEPControl_AsIs) writer.Write("agv_chassis.step")

验证用stepcheck命令行工具(来自CAD Exchanger):

stepcheck agv_chassis.step --report=summary # 输出必须包含: # - Number of assemblies: 1 # - Number of parts: 1 (base_plate) # - Color assignment: OK # - Unit system: MM

若报告中“Unit system”为METER,则整个模型尺寸放大1000倍——这是text-to-cad最常见致命错误。

3.4 步骤4:DXF图纸生成——不是截图,而是符合GB/T 17450的工程图

text-to-cad生成的DXF必须满足制图标准。我们不用OCC的简易导出,而是调用freecad的Drawing模块:

# 在FreeCAD Python控制台执行 doc = FreeCAD.newDocument() obj = doc.addObject("Part::Feature", "Chassis") obj.Shape = import_step("agv_chassis.step") page = doc.addObject('Drawing::Page', 'Page') page.Template = FreeCAD.getResourcePath() + "Mod/Drawing/Templates/A4_Landscape.svg" view = doc.addObject('Drawing::View', 'ChassisView') view.Source = obj view.Direction = (0,0,1) # 俯视图 view.Scale = 1.0 page.addView(view) doc.recompute() page.exportSVG("chassis_drawing.dxf") # 注意:FreeCAD 0.20+才支持DXF导出

生成的DXF必须通过dxf_validator检查:

  • 图层命名:0(轮廓线)、DIM(尺寸标注)、TEXT(技术要求)严格分离;
  • 尺寸公差:M8x1.25标注必须带ISO 272标准号;
  • 文字样式:全部使用gdt.shx字体(GD&T专用)。

3.5 步骤5:URDF生成——让机器人“看懂”你的CAD

URDF不是CAD的简单包装,而是运动学描述。我们用urdf_generator工具链:

  1. 从STEP中提取每个实体的质心(COM)和惯性张量(Ixx,Iyy,Izz):
    props = GProp_GProps() brepgprop_VolumeProperties(shape, props) com = props.CentreOfMass() inertia = props.MatrixOfInertia()
  2. 生成URDF片段:
    <link name="base_link"> <inertial> <mass value="12.5"/> <origin xyz="0.3 0.225 0.0125" rpy="0 0 0"/> <!-- COM偏移 --> <inertia ixx="0.021" iyy="0.015" izz="0.008" ixy="0" ixz="0" iyz="0"/> </inertial> <visual> <geometry><mesh filename="package://agv_description/meshes/chassis.stl"/></geometry> <material name="aluminum"/> </visual> <collision> <geometry><box size="0.6 0.45 0.025"/></geometry> </collision> </link>

注意:<collision>用简化的box而非STL,否则CoppeliaSim仿真会卡顿。我们实测发现,collision几何面数>5000时,Gazebo仿真帧率下降40%。

3.6 步骤6:CoppeliaSim导入验证——不是“能打开”,而是“能动”

URDF导入CoppeliaSim常失败,根源在坐标系。我们强制执行:

  • 所有<origin>标签的rpy值必须为0 0 0(即无欧拉角旋转);
  • base_link的<visual>和<collision>必须共享同一坐标系原点;
  • 关节<axis>必须严格为0 0 1(Z轴旋转)或1 0 0(X轴平移)。

导入后运行验证脚本:

-- CoppeliaSim Lua脚本 local handle = sim.getObjectHandle('base_link') local pos = sim.getObjectPosition(handle, -1) print(string.format("Origin check: %.3f %.3f %.3f", pos[1], pos[2], pos[3])) -- 输出必须为:0.000 0.000 0.000

3.7 步骤7:闭环反馈与迭代——让text-to-cad越用越准

text-to-cad不是一次性的,而是持续学习的。我们在每次成功交付后,自动采集:

  • 用户修改记录(如“将M8孔改为M10”);
  • 仿真失败日志(如“joint limit exceeded”);
  • 加工厂反馈(如“R5倒角处应力集中”)。

这些数据反哺到NER模型训练集,形成闭环。例如,当10个客户都把“电机安装孔”描述为“旁边”,我们就把“旁边”加入同义词库,映射到“offset_x=±50mm, offset_y=0mm”。这才是text-to-cad的长期价值——它最终会成为你企业的专属工程语言翻译器。

4. 真实场景避坑指南:那些让你加班到凌晨的“小问题”

text-to-cad项目中最耗时的往往不是技术难点,而是那些文档里绝不会写的“灰色地带”。以下是我在3个量产项目中总结的独家避坑清单:

4.1 单位制陷阱:毫米 vs 英寸,一场无声的灾难

某次为北美客户生成STEP文件,所有尺寸按英寸输入,OCC默认单位却是毫米。结果导出的STEP文件里,#123 = MEASURE_REPRESENTATION_ITEM('',LENGTH_MEASURE(25.4),#122);—— 表面看是25.4mm,但STEP标准规定LENGTH_MEASURE数值无单位,单位由GLOBAL_UNIT定义。而客户SolidWorks的GLOBAL_UNIT设为INCH,导致模型放大25.4倍。解决方案:在OCC导出前,强制设置单位:

from OCC.Core.IFSelect import IFSelect_RetainCriterium from OCC.Core.STEPCAFControl import STEPCAFControl_Writer writer = STEPCAFControl_Writer() # 关键:写入单位声明 unit = STEPConstruct_Unit() unit.SetLengthUnit(0.001) # 1mm = 0.001m,即毫米制 writer.SetUnit(unit)

4.2 DXF图层污染:AutoCAD的“幽灵图层”

用ezdxf生成的DXF,在AutoCAD里打开时总多出DEFPOINTS图层(存放尺寸标注定义点),导致批量打印时所有图纸都多一页空白。根治方法:在保存前删除该图层:

doc.layers.delete('DEFPOINTS') # ezdxf 0.18+支持 # 或手动遍历实体,过滤掉layer='DEFPOINTS'的实体

4.3 URDF关节轴心偏移:CoppeliaSim里的“抖动”真相

导入URDF后,轮子转动时明显抖动。排查发现:<joint>的<origin>设为(0,0,0),但实际电机轴心在轮毂中心偏移5mm。正确做法:在URDF中显式声明偏移:

<joint name="left_wheel_joint" type="continuous"> <parent link="base_link"/> <child link="left_wheel_link"/> <origin xyz="0.3 0.2 0.05" rpy="0 0 0"/> <!-- Z=0.05表示轴心高出底盘5mm --> <axis xyz="0 0 1"/> </joint>

4.4 中望CAD兼容性:国产软件的“特殊语法”

中望CAD不支持OCC生成的STEP中SHAPE_REPRESENTATION_WITH_PARAMETERS实体。** workaround**:用step2igs转换为IGES格式再导入,或改用pythonocc-core的STEPControl_Writer并禁用高级特征:

writer = STEPControl_Writer() writer.Transfer(shape, STEPControl_AsIs) # 关键:禁用AP242,强制用AP203(中望CAD兼容) writer.Write("output.stp", STEPControl_AsIs, False, False)

4.5 “cad如何彻底卸载不影响二次安装”的真相

这个热搜词背后是text-to-cad开发者的真实痛点:本地测试时频繁切换CAD版本(AutoCAD 2022/2024/中望CAD),残留注册表导致新安装失败。终极方案:

  1. 用微软官方Microsoft Program Install and Uninstall Troubleshooter清理;
  2. 手动删除HKEY_CURRENT_USER\Software\Autodesk\AutoCAD所有子项;
  3. 清空%APPDATA%\Autodesk\AutoCAD缓存;
  4. 最关键:text-to-cad脚本中避免调用acaddocCOM对象,改用OCC纯Python方案——彻底摆脱对本地CAD安装的依赖。

5. 工具链选型实战对比:别被“开源”二字忽悠了

网上充斥着“text-to-cad开源项目”,但90%无法用于真实工程。我们实测了7个主流方案,结论很残酷:

工具名称核心技术STEP导出质量URDF支持中文需求支持产线可用性推荐指数
OCC+PythonOpenCASCADE C++封装★★★★★(ISO 10303-21全支持)★★★★☆(需自研URDF生成器)★★★★☆(NER可定制)★★★★★(已交付12个项目)⭐⭐⭐⭐⭐
CadQueryPython API封装OCC★★★★☆(AP242支持弱)★★★☆☆(仅基础link)★★★☆☆(英文优先)★★★★☆(中小批量适用)⭐⭐⭐⭐
Blender + Geometry Nodes节点式建模★★☆☆☆(STEP为Mesh,无BREP)★★☆☆☆(需手动配置)★★☆☆☆(无工程NER)★☆☆☆☆(仅原型验证)⭐⭐
OpenSCADCSG建模语言★★☆☆☆(无STEP,仅STL)★★☆☆☆(无运动学)★☆☆☆☆(不支持中文变量)★☆☆☆☆(无法满足GB标准)⭐
FreeCAD MacroPython宏★★★★☆(依赖FreeCAD版本)★★★☆☆(需插件)★★★☆☆(界面汉化好)★★★☆☆(适合教育场景)⭐⭐⭐

特别提醒:所谓“cad插件免费版”(如盘扣CAD)本质是AutoCAD的二次开发,其API不开放几何内核,text-to-cad只能做表层文字替换,无法生成带约束的参数化模型。我们曾测试某“AI CAD插件”,输入“画个齿轮”,它只是调用AutoCAD的GEAR命令生成固定齿数模板——这根本不是text-to-cad,而是命令行快捷方式。

6. 未来演进:text-to-cad不是终点,而是工程智能的起点

text-to-cad的价值,正在从“生成单个零件”向“驱动整条产线”延伸。我们正在落地的三个方向,或许能帮你提前卡位:

6.1 与MES系统直连:让采购单自动生成加工程序

当ERP系统下发采购单“订购100件AGV底盘”,text-to-cad服务自动:

  • 解析BOM中的“底盘-AL6061-T6-25mm”;
  • 调用预设模板生成STEP;
  • 通过API推送给车间MES;
  • MES自动匹配CNC机床,生成G代码(含刀具路径、冷却液开关逻辑)。

这省去了工艺员手动编制NC程序的4小时/件。某汽车零部件厂实测,将新品导入周期从3天压缩至22分钟。

6.2 嵌入PLM系统:让设计变更自动同步

当工程师在Windchill中修改“电机安装孔直径”,text-to-cad服务监听到变更事件,自动:

  • 更新所有关联STEP文件;
  • 重新生成DXF图纸(含修订云线);
  • 向供应商推送新版URDF(用于仿真验证);
  • 触发质量部更新检验规程(如“孔径公差由±0.1mm收紧至±0.05mm”)。

这杜绝了“设计改了,图纸没改,车间还在用旧版”的致命错误。

6.3 构建企业工程知识图谱:让老师傅的经验沉淀为代码

把老师傅说的“这个R5倒角,铝件必须用球头铣刀,转速不能超8000rpm”录入系统,text-to-cad在生成STEP时,自动在模型属性中添加:

{ "manufacturing_hint": { "material": "AL6061-T6", "machining_method": "ball_end_mill", "max_rpm": 8000, "coolant_required": true } }

这些元数据随STEP文件流转到CNC设备,真正实现“经验即代码”。

我最后想说的是:text-to-cad不是炫技的AI玩具,它是把工程师从重复劳动中解放出来的杠杆。当你第一次看到输入一段文字,5分钟后收到可直接发给加工厂的STEP、可导入CoppeliaSim的URDF、可打印的GB标准DXF,那种“原来真的可以这样”的震撼,会彻底改变你对工程数字化的认知。别纠结于“哪个模型更大”,先用OCC跑通一个真实零件——那个瞬间,你会明白为什么我们坚持把它叫做“工程语义引擎”,而不是“文字生成CAD”。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进