1. 从一句话到三维模型:text-to-cad 到底在解决什么问题
第一次听到 text-to-cad 这个词,我的反应是:这不就是把自然语言变成 CAD 模型吗?听起来像是给工程师省事的工具,但真正动手做过几个项目之后才发现,它要解决的远不止“省事”这么简单。
传统 CAD 工作流的起点是什么?是人打开 SolidWorks、Fusion 360 或者中望 CAD,然后从草图开始,一条线一条线地画,一个尺寸一个尺寸地标。这个过程对于有经验的工程师来说不算难,但问题是:从“脑子里有一个想法”到“屏幕上有一个可用的三维模型”,中间隔着一道非常高的操作门槛。你得熟悉软件界面、掌握建模命令、理解约束关系、知道怎么导出不同格式。一个简单的法兰盘,熟手可能十分钟搞定,新手可能折腾一下午还画不出来。
text-to-cad 的核心思路就是把这层门槛打掉。你用自然语言描述你想要的东西——“一个直径 80mm、厚度 10mm 的法兰盘,中心有直径 30mm 的通孔,周围均匀分布 6 个直径 8mm 的螺栓孔”——系统解析这段描述,自动生成对应的三维几何模型,并且能导出成 STEP、URDF、G-code 等下游可用的格式。
这件事为什么现在变得可行了?两个原因。一是大语言模型对结构化信息的理解能力上来了,能把一段自然语言拆解成“几何体类型 + 尺寸参数 + 空间关系”这样的结构化数据。二是参数化建模本身就有很强的程序化特征,CAD 的内核(比如 OpenCASCADE)提供了完整的 API,只要你能把自然语言转成正确的 API 调用序列,模型就能自动生成。
适合谁来关注这个方向?我梳理了一下,大概三类人最需要:
- 机械工程师和产品设计师:手头有大量重复性的建模任务,想通过自动化提效
- 机器人方向的开发者:需要快速生成 URDF 模型用于仿真,但不想手动写 XML
- 做 CAD 二次开发的人:想在自己的工具链里集成自然语言建模能力
下面我会从整体设计思路、核心技术细节、实操流程、常见问题几个维度,把 text-to-cad 这个方向拆开来讲。内容会涉及 STEP、URDF、G-code 这三种典型输出格式的处理逻辑,也会给出可以直接参考的代码方案。
2. 整体架构设计:为什么这样搭,而不是那样搭
2.1 三种技术路线的取舍分析
做 text-to-cad,摆在面前的第一道选择题就是:用什么方式把自然语言变成几何模型?我调研和实践下来,主流路线有三条,各有各的适用场景。
第一条路线是基于模板匹配。提前准备好一批参数化模板(法兰、齿轮、支架、壳体等),用户输入自然语言后,系统识别出对应的模板类型,再抽取尺寸参数填入模板。这条路线实现简单、生成结果稳定,但缺点是覆盖范围有限,遇到模板库之外的形状就无能为力了。
第二条路线是基于代码生成。让大语言模型直接生成 CAD 脚本代码(比如 OpenSCAD 脚本、CadQuery 的 Python 代码),然后执行代码得到模型。这条路线灵活度最高,理论上能生成任意形状,但对模型的代码能力要求高,而且生成的代码可能报错,需要一套健壮的容错机制。
第三条路线是基于几何原语组合。把自然语言解析成一系列几何操作(拉伸、旋转、布尔运算等)的序列,然后逐步执行。这条路线介于前两者之间,灵活度和稳定性比较均衡。
我最终选择的方案是以代码生成为主、模板匹配为辅的混合架构。原因很直接:纯模板匹配太死板,纯代码生成太飘。混合方案的做法是,先判断用户的描述是否命中已知模板(比如“法兰盘”“齿轮”这类标准件),命中就走模板快速生成;没命中就切换到代码生成模式,让模型输出 CadQuery 或 OpenSCAD 代码。
提示:选择 CadQuery 而不是直接调 OpenCASCADE 的 C++ API,主要是因为 Python 生态的迭代速度更快,而且大语言模型对 Python 代码的生成质量明显高于 C++。
2.2 输出格式的设计考量
text-to-cad 生成模型之后,往哪里输出?这取决于下游用来干什么。我梳理了三种最典型的输出格式及其适用场景:
| 输出格式 | 适用场景 | 核心特点 | 生成难度 |
|---|---|---|---|
| STEP | 通用三维交换、CNC 加工 | 精确保留 B-Rep 几何信息 | 中 |
| URDF | 机器人仿真、运动学建模 | 带关节和链接的层级结构 | 高 |
| G-code | 3D 打印、CNC 加工路径 | 刀具轨迹指令序列 | 中高 |
STEP 是最“标准”的输出。它是 ISO 10303 标准定义的几何交换格式,几乎所有的 CAD 软件都能读写。用 CadQuery 生成模型后,一行代码就能导出 STEP 文件。难点在于确保导出的几何是有效的实体(solid),而不是一堆散乱的曲面。
URDF 的输出就复杂多了。URDF 本质上是描述机器人运动学结构的 XML 格式,它关心的不只是几何形状,还有链接(link)之间的关节(joint)关系、坐标系变换、惯性参数等。从自然语言生成 URDF,需要模型不仅理解“形状”,还要理解“结构”——哪个部件是父链接,哪个是子链接,关节类型是旋转还是平移,旋转轴朝哪个方向。
G-code 是另一个维度的挑战。它不是几何模型,而是加工路径。从三维模型到 G-code,中间需要经过切片(3D 打印)或 CAM 刀路规划(CNC 加工)。text-to-cad 在这个环节的角色,更多是生成模型后调用切片软件或 CAM 引擎来完成后续转换。
2.3 系统整体数据流
整个系统的数据流可以这样理解:用户输入自然语言描述,经过意图识别和参数抽取,得到结构化的建模指令;建模引擎根据指令生成三维模型;后处理模块根据目标格式进行转换和导出。
具体来说,意图识别层负责判断用户想要什么类型的模型(标准件还是自定义形状),参数抽取层负责从描述中提取尺寸、数量、位置关系等数值信息,建模执行层负责调用 CadQuery 或 OpenSCAD 生成几何体,格式转换层负责导出 STEP、URDF 或触发 G-code 生成流程。
这个架构的好处是每一层都可以独立替换和升级。比如你后面想换一个更强的语言模型来做意图识别,只需要替换第一层,后面的建模逻辑完全不用动。
3. 核心技术细节:从自然语言到几何体的关键环节
3.1 自然语言解析与参数抽取
这一步是整个流程的入口,也是最容易出问题的地方。用户说“一个 80 毫米直径的法兰盘”,模型需要准确提取出“法兰盘”这个物体类型和“80mm”这个直径参数。但用户也可能说“直径 8 厘米”,或者“半径 40mm”,甚至“大概拳头那么大”。后一种情况就需要做单位换算或者模糊推理。
我在实践中总结了一套参数抽取的提示词模板,效果比较稳定。核心思路是让模型输出结构化的 JSON,而不是自由文本。比如:
EXTRACT_PROMPT = """ 你是一个 CAD 参数抽取助手。请从用户的描述中提取以下信息,以 JSON 格式返回: - object_type: 物体类型(如 flange, gear, bracket, shaft 等) - dimensions: 尺寸参数字典(如 diameter, thickness, hole_count 等) - units: 单位(默认 mm) - constraints: 特殊约束条件 用户描述:{user_input} """这样做的好处是,后续的建模代码可以直接消费 JSON 数据,不需要再去解析自然语言。实测下来,对于包含明确尺寸参数的描述,抽取准确率能到 90% 以上。对于模糊描述,就需要加一层交互确认——让用户确认抽取结果是否正确,再继续建模。
注意:单位换算是高频踩坑点。我遇到过用户说“4 英寸”,模型直接当成 4mm 处理的情况。建议在参数抽取阶段就统一转换成毫米,并在返回结果中明确标注原始单位和转换后的值。
3.2 基于 CadQuery 的建模代码生成
CadQuery 是我目前最推荐的 Python 参数化建模库。它的 API 设计很直观,代码可读性强,而且大语言模型对它的生成质量相当不错。举个例子,生成一个法兰盘的 CadQuery 代码如下:
import cadquery as cq # 参数定义 outer_dia = 80.0 # 外径 mm inner_dia = 30.0 # 中心孔直径 mm thickness = 10.0 # 厚度 mm bolt_dia = 8.0 # 螺栓孔直径 mm bolt_count = 6 # 螺栓孔数量 bolt_circle_dia = 60.0 # 螺栓孔分布圆直径 mm # 创建法兰盘 result = ( cq.Workplane("XY") .circle(outer_dia / 2) .extrude(thickness) .faces(">Z") .workplane() .hole(inner_dia) .faces(">Z") .workplane() .polarArray(bolt_circle_dia / 2, 0, 360, bolt_count) .hole(bolt_dia) ) # 导出 STEP cq.exporters.export(result, "flange.step")这段代码的逻辑很清晰:先在 XY 平面上画一个外圆,拉伸成圆柱体;然后在顶面打中心孔;最后用极坐标阵列的方式打一圈螺栓孔。每一步操作都对应一个明确的几何意图。
让大语言模型生成这类代码时,关键是在提示词里给出足够的示例和约束。我通常会在系统提示词里包含两到三个完整的 CadQuery 示例,覆盖拉伸、旋转、布尔运算等基本操作。这样模型生成的代码成功率会高很多。
3.3 URDF 生成的额外复杂度
如果目标输出是 URDF,事情就复杂了一个量级。URDF 不只是一个几何描述文件,它描述的是一个运动学树结构。每个 link 有自己的视觉几何、碰撞几何和惯性参数,每个 joint 有类型、父链接、子链接、旋转轴和位置变换。
从自然语言生成 URDF,需要模型理解“结构关系”。比如用户说“一个两轮差速机器人,底盘长 30cm 宽 20cm,两个驱动轮直径 10cm 安装在底盘两侧”,模型需要推断出:base_link 是底盘,left_wheel 和 right_wheel 是两个子链接,它们通过 continuous 类型的 joint 连接到底盘,旋转轴是 Y 轴方向。
我处理这个问题的方式是分两步走:第一步先用自然语言生成一个结构描述(JSON 格式),明确列出所有的 link 和 joint;第二步再根据结构描述生成 URDF XML。这样做的好处是,结构描述比直接生成 XML 更容易验证和调试。
# 结构描述示例 robot_structure = { "links": [ {"name": "base_link", "geometry": {"type": "box", "size": [0.3, 0.2, 0.1]}}, {"name": "left_wheel", "geometry": {"type": "cylinder", "radius": 0.05, "length": 0.03}}, {"name": "right_wheel", "geometry": {"type": "cylinder", "radius": 0.05, "length": 0.03}} ], "joints": [ {"name": "left_wheel_joint", "type": "continuous", "parent": "base_link", "child": "left_wheel", "axis": [0, 1, 0], "origin": [0, 0.115, 0]}, {"name": "right_wheel_joint", "type": "continuous", "parent": "base_link", "child": "right_wheel", "axis": [0, 1, 0], "origin": [0, -0.115, 0]} ] }有了这个结构描述,生成 URDF XML 就是纯粹的模板填充工作,几乎不会出错。而且这个 JSON 结构本身也很容易让用户确认和修改。
3.4 G-code 生成的链路设计
G-code 的生成链路和 STEP、URDF 有本质区别。STEP 和 URDF 是“模型即终点”,而 G-code 是“模型是中间产物”。完整的链路是:自然语言 → 三维模型 → 切片/刀路规划 → G-code。
对于 3D 打印场景,我通常的做法是生成 STL 文件后,调用 CuraEngine 或 PrusaSlicer 的命令行接口来完成切片。对于 CNC 加工场景,情况更复杂,需要根据刀具参数、材料类型、加工策略来生成刀路,这块目前自动化程度还比较有限。
一个比较实用的折中方案是:text-to-cad 负责生成三维模型和推荐的加工参数(层高、填充率、打印速度等),然后调用切片软件的命令行工具完成 G-code 生成。这样既发挥了自然语言建模的优势,又利用了成熟的切片引擎。
# 使用 PrusaSlicer 命令行切片示例 prusa-slicer --export-gcode \ --layer-height 0.2 \ --fill-density 20% \ --support-material \ -o output.gcode \ input.stl提示:G-code 生成环节的参数非常多,建议在 text-to-cad 系统中只暴露最常用的几个参数(层高、填充率、支撑开关),其余参数使用切片软件的默认值或预设配置文件。
4. 实操全流程:从零搭建一个 text-to-cad 原型
4.1 环境准备与依赖安装
先把环境搭起来。我推荐用 Python 3.10 以上的版本,因为 CadQuery 对 Python 版本有一定要求。核心依赖就两个:CadQuery 和 OpenAI 的 API 客户端(或者你用的任何大语言模型接口)。
# 创建虚拟环境 python -m venv text2cad-env source text2cad-env/bin/activate # Linux/Mac # text2cad-env\Scripts\activate # Windows # 安装核心依赖 pip install cadquery pip install openai pip install trimesh # 用于 STL 处理CadQuery 的安装在某些平台上可能会遇到编译问题,特别是 Windows 环境。如果pip install cadquery失败,可以尝试用 conda 安装:
conda install -c conda-forge cadquery安装完成后,跑一个简单的测试确认环境正常:
import cadquery as cq box = cq.Workplane("XY").box(10, 10, 10) cq.exporters.export(box, "test_box.step") print("环境正常,STEP 文件已导出")4.2 自然语言解析模块实现
解析模块的核心是构造一个好的提示词,让大语言模型输出结构化的建模指令。我实际使用的提示词经过多次迭代,下面这个版本的效果比较稳定:
import json from openai import OpenAI client = OpenAI(api_key="your-api-key") SYSTEM_PROMPT = """你是一个 CAD 建模指令解析器。用户会用自然语言描述一个三维模型, 你需要将其解析为结构化的 JSON 指令。 输出格式要求: { "object_type": "模型类型", "dimensions": {"参数名": 数值, ...}, "units": "mm", "features": ["特征1", "特征2", ...], "modeling_steps": ["步骤1描述", "步骤2描述", ...] } 注意事项: 1. 所有尺寸统一转换为毫米 2. 如果用户描述模糊,在 dimensions 中给出合理的默认值 3. modeling_steps 要按建模顺序排列 """ def parse_description(user_input): response = client.chat.completions.create( model="gpt-4", messages=[ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": user_input} ], temperature=0.1 ) return json.loads(response.choices[0].message.content)这个模块的输出是一个 JSON 对象,包含了建模所需的全部信息。temperature 设为 0.1 是为了让输出更稳定,减少随机性。
4.3 建模执行与格式导出
拿到解析结果后,下一步是生成 CadQuery 代码并执行。我采用的方式是让大语言模型根据 JSON 指令生成代码,然后在沙箱环境中执行。
CODE_GEN_PROMPT = """根据以下建模指令,生成 CadQuery Python 代码。 要求: 1. 代码必须包含参数定义部分,参数值从指令中读取 2. 使用 cq.Workplane 链式调用 3. 最后导出为 STEP 文件,文件名为 output.step 4. 只输出代码,不要输出解释 建模指令: {instruction} """ def generate_cadquery_code(instruction): response = client.chat.completions.create( model="gpt-4", messages=[ {"role": "system", "content": CODE_GEN_PROMPT.format( instruction=json.dumps(instruction, ensure_ascii=False) )}, {"role": "user", "content": "请生成代码"} ], temperature=0.1 ) return response.choices[0].message.content执行生成的代码时,一定要放在 try-except 块里,并且设置超时限制。我遇到过模型生成的代码进入死循环的情况,没有超时保护的话整个服务就卡死了。
import subprocess import tempfile def execute_cadquery_code(code, timeout=30): with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f: f.write(code) f.flush() try: result = subprocess.run( ['python', f.name], capture_output=True, text=True, timeout=timeout ) if result.returncode == 0: return True, result.stdout else: return False, result.stderr except subprocess.TimeoutExpired: return False, "代码执行超时"4.4 URDF 导出的完整实现
URDF 的导出流程和 STEP 有所不同。我的做法是先生成结构描述 JSON,再转换成 URDF XML。下面是一个完整的转换函数:
def json_to_urdf(structure): links_xml = [] joints_xml = [] for link in structure["links"]: geom = link["geometry"] if geom["type"] == "box": size = " ".join(str(s) for s in geom["size"]) visual = f'<box size="{size}"/>' elif geom["type"] == "cylinder": visual = f'<cylinder radius="{geom["radius"]}" length="{geom["length"]}"/>' else: visual = '<sphere radius="0.05"/>' links_xml.append(f''' <link name="{link["name"]}"> <visual> <geometry>{visual}</geometry> </visual> <collision> <geometry>{visual}</geometry> </collision> </link>''') for joint in structure["joints"]: axis = " ".join(str(a) for a in joint["axis"]) origin = " ".join(str(o) for o in joint["origin"]) joints_xml.append(f''' <joint name="{joint["name"]}" type="{joint["type"]}"> <parent link="{joint["parent"]}"/> <child link="{joint["child"]}"/> <axis xyz="{axis}"/> <origin xyz="{origin}" rpy="0 0 0"/> </joint>''') urdf = f'''<?xml version="1.0"?> <robot name="generated_robot"> {"".join(links_xml)} {"".join(joints_xml)} </robot>''' return urdf生成的 URDF 文件可以直接导入 CoppeliaSim 或者 Gazebo 进行仿真验证。导入 CoppeliaSim 的时候要注意,URDF 中的 mesh 文件路径需要是相对路径或者绝对路径,如果用了 package:// 协议,CoppeliaSim 可能无法识别。
4.5 完整调用示例
把上面的模块串起来,一个完整的调用流程是这样的:
def text_to_cad(user_input, output_format="step"): # 第一步:解析自然语言 instruction = parse_description(user_input) print(f"解析结果:{json.dumps(instruction, ensure_ascii=False, indent=2)}") # 第二步:根据输出格式选择处理路径 if output_format == "step": code = generate_cadquery_code(instruction) success, msg = execute_cadquery_code(code) if success: print("STEP 文件生成成功") else: print(f"生成失败:{msg}") elif output_format == "urdf": # URDF 需要先生成结构描述 structure = parse_robot_structure(user_input) urdf_content = json_to_urdf(structure) with open("output.urdf", "w") as f: f.write(urdf_content) print("URDF 文件生成成功") elif output_format == "gcode": # 先生成 STL,再调用切片引擎 code = generate_cadquery_code(instruction) # 修改导出格式为 STL code = code.replace(".step", ".stl") success, msg = execute_cadquery_code(code) if success: subprocess.run([ "prusa-slicer", "--export-gcode", "--layer-height", "0.2", "-o", "output.gcode", "output.stl" ]) print("G-code 生成成功") # 测试 text_to_cad("一个直径80mm厚度10mm的法兰盘,中心有30mm通孔,周围6个8mm螺栓孔")实测下来,对于结构清晰、参数明确的描述,整个流程从输入到生成 STEP 文件大约需要 15 到 30 秒,其中大部分时间花在大语言模型的推理上。CadQuery 的建模执行通常在一秒以内。
5. 常见问题与排查技巧实录
5.1 模型生成失败的高频原因
在实际使用中,模型生成失败是最常见的问题。我把踩过的坑整理成了一张速查表:
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| 代码执行报错 | 模型生成的 API 调用不正确 | 查看 stderr 输出 | 在提示词中增加 API 示例 |
| 几何体为空 | 布尔运算结果为空集 | 检查各步骤的中间结果 | 调整运算顺序或参数 |
| STEP 导出失败 | 几何不是有效实体 | 用.val().isValid()检查 | 添加.clean()或修复几何 |
| URDF 导入失败 | XML 格式错误或路径问题 | 用 xmllint 验证 XML | 检查 mesh 路径和标签闭合 |
| 尺寸明显不对 | 单位换算错误 | 检查解析结果中的 units | 统一转换为毫米 |
| 生成超时 | 代码逻辑复杂或死循环 | 查看执行时间 | 设置超时限制,简化建模步骤 |
其中“几何体为空”这个问题最隐蔽。比如用户要求“在一个圆柱体上打一个比它本身还大的孔”,布尔差运算的结果就是空集。CadQuery 不会报错,但导出的 STEP 文件是空的。我的做法是在导出前加一步验证:
result = ... # 建模结果 if result.val().Volume() < 1e-6: raise ValueError("生成的几何体体积为零,请检查建模参数")5.2 提升生成成功率的实用技巧
经过大量测试,我总结了几个显著提升成功率的方法。
第一个技巧是在提示词中提供完整的示例代码。大语言模型对代码的生成质量高度依赖于上下文中的示例。我会在系统提示词里放两到三个覆盖不同建模操作的 CadQuery 示例,包括拉伸、旋转、布尔运算、阵列等。加上示例之后,代码首次执行成功率从大约 60% 提升到了 85% 以上。
第二个技巧是分步生成而不是一步到位。对于复杂模型,让模型一次性生成完整代码容易出错。更好的做法是先让模型生成建模步骤的文字描述,确认无误后再逐步生成代码。比如一个带法兰的轴,可以先确认“第一步创建轴体,第二步创建法兰盘,第三步布尔并集”,然后再生成代码。
第三个技巧是建立常见模型的模板库。对于法兰、齿轮、支架这类高频模型,直接使用预定义的参数化模板,不走代码生成路线。模板的可靠性是 100%,而且生成速度更快。只有模板库覆盖不到的模型才走代码生成。
注意:模板库的维护成本不低。每增加一个模板,都需要定义参数接口、编写模板代码、测试边界条件。建议只把最高频的 10 到 20 种模型纳入模板库。
5.3 URDF 导入仿真环境的踩坑记录
URDF 生成出来只是第一步,能成功导入仿真环境才是终点。我在 CoppeliaSim 和 Gazebo 上都踩过不少坑,这里分享几个典型问题。
坐标系不一致是最常见的问题。URDF 使用的坐标系约定和某些仿真软件不完全一样。比如 URDF 中 Z 轴朝上,但有些机器人仿真场景默认 Y 轴朝上。导入之后机器人可能是躺着的。解决办法是在 URDF 的根 link 上加一个旋转,或者在仿真软件中调整导入设置。
惯性参数缺失是另一个高频问题。URDF 要求每个 link 都有惯性矩阵,但自然语言描述中通常不会包含这些信息。我的做法是根据几何形状和默认密度自动计算惯性参数。对于简单几何体,惯性矩阵有解析解:
def box_inertia(mass, x, y, z): """计算长方体的惯性矩阵""" ixx = mass * (y**2 + z**2) / 12.0 iyy = mass * (x**2 + z**2) / 12.0 izz = mass * (x**2 + y**2) / 12.0 return f""" <inertia ixx="{ixx}" ixy="0" ixz="0" iyy="{iyy}" iyz="0" izz="{izz}"/> """mesh 文件路径也经常出问题。如果 URDF 中引用了 STL 或 DAE 文件,路径必须是仿真软件能访问到的。我通常把 mesh 文件和 URDF 放在同一个目录下,用相对路径引用,这样移植性最好。
5.4 G-code 生成的质量控制
G-code 的质量直接决定打印或加工的结果。text-to-cad 生成的模型只是起点,切片参数的选择同样关键。我整理了几个核心参数的推荐值:
| 参数 | 推荐值 | 说明 |
|---|---|---|
| 层高 | 0.2mm | 精度和速度的平衡点 |
| 填充率 | 20% | 一般用途足够,承重件可提高到 40% |
| 打印速度 | 50mm/s | 大多数 FDM 打印机的稳定速度 |
| 支撑 | 自动生成 | 有悬垂结构时开启 |
| 底板附着 | 裙边 | 比 raft 省材料,比 brim 易剥离 |
对于 CNC 加工场景,G-code 的生成要复杂得多。需要根据刀具直径、材料硬度、切削深度来计算进给速度和主轴转速。这块目前我还没有做到完全自动化,通常是在 text-to-cad 生成模型后,导出 STEP 文件到专业的 CAM 软件中做刀路规划。
提示:如果只是做 3D 打印的快速验证,建议在 text-to-cad 系统中直接集成 PrusaSlicer 的命令行接口,用预设配置文件来生成 G-code。这样用户只需要选择“打印质量”(草稿/标准/精细),系统自动映射到对应的参数组合。
6. 几个值得关注的扩展方向
6.1 批量生成与参数扫描
text-to-cad 的一个天然优势是支持批量生成。比如你需要一系列不同直径的法兰盘,从 50mm 到 200mm,每隔 10mm 一个。用传统 CAD 你得手动改参数、重新导出,用 text-to-cad 只需要写一个循环:
for dia in range(50, 201, 10): desc = f"直径{dia}mm厚度10mm的法兰盘,中心孔直径{dia*0.375}mm,6个直径8mm螺栓孔" text_to_cad(desc, output_format="step")这种参数扫描在优化设计、生成训练数据、做设计空间探索的时候特别有用。我之前做过一个项目,需要生成 500 个不同参数的支架模型用于有限元分析,用 text-to-cad 批量生成只花了不到一个小时。
6.2 与 CAD 软件的联动
生成的 STEP 文件可以直接导入到中望 CAD、SolidWorks 等软件中做后续编辑。我实测下来,CadQuery 导出的 STEP 文件在中望 CAD 中的兼容性很好,实体、曲面、边线都能正确识别。
如果你需要做更复杂的操作,比如 CAD 图纸合并、批量修改,可以结合 Python 的 CAD 自动化库来实现。比如用ezdxf处理 DXF 文件,用pyautocad操作 AutoCAD 的 COM 接口。这些工具和 text-to-cad 配合起来,能覆盖从模型生成到图纸输出的完整链路。
6.3 模型质量自动验证
生成模型之后,自动验证几何有效性是一个值得投入的方向。除了前面提到的体积检查,还可以做壁厚分析、干涉检查、最小特征尺寸检查等。这些验证步骤能大幅减少“生成了但不能用”的情况。
def validate_model(workplane, min_wall_thickness=1.0): """基本的模型验证""" solid = workplane.val() if not solid.isValid(): return False, "几何无效" if solid.Volume() < 1e-6: return False, "体积为零" bbox = solid.BoundingBox() if min(bbox.xlen, bbox.ylen, bbox.zlen) < min_wall_thickness: return False, f"最小尺寸小于{min_wall_thickness}mm" return True, "验证通过"这个验证函数可以在每次生成后自动运行,把不合格的模型拦截下来,避免下游拿到无效文件。
6.4 本地化部署的考量
如果你对数据隐私有要求,或者不想依赖云端 API,可以考虑本地部署大语言模型。目前 7B 到 13B 参数量的开源模型在代码生成任务上已经有一定可用性,配合量化技术可以在消费级显卡上运行。不过实测下来,本地模型在 CadQuery 代码生成的准确率上还是明显低于云端的大模型,复杂模型的首次成功率可能只有 50% 到 60%。一个折中方案是本地模型负责参数抽取和简单模型生成,复杂模型仍然走云端 API。
我在实际项目中的体会是,text-to-cad 这个方向目前最适合的场景是快速原型验证和批量参数化生成。它还不能完全替代人工建模,特别是在处理复杂曲面、装配体、工程图纸这些任务时,人的经验仍然不可替代。但对于那些“脑子里有想法,想快速看到三维结果”的场景,它已经能提供实实在在的效率提升了。
最后分享一个小技巧:如果你在生成 URDF 时遇到 CoppeliaSim 导入后模型位置不对的问题,先检查 URDF 中每个 joint 的 origin 设置。很多时候问题出在 origin 的 rpy 参数上,默认的 “0 0 0” 并不总是正确的。可以先用一个简单的两轮机器人模型做测试,确认坐标系约定后再处理复杂模型。