FreeCAD Python参数化设计实战:从建模到工程图全链路自动化

FreeCAD Python参数化设计实战:从建模到工程图全链路自动化 简介本资源是一套面向机械设计初学者与FreeCAD进阶用户的Python自动化建模实践包聚焦于利用FreeCAD的参数化能力与Python脚本提升机械部件设计效率。资源包含78个文件主体为38个.fcmacro宏脚本用于一键生成齿轮、螺纹、蜂窝结构等典型机械特征、12个.py源码如dxfImportObjects、screw_maker等核心功能模块及9张PNG示意图辅以2个.fcstd模型文件和README.md等说明文档整体压缩包仅616KB轻量易用。已有151人学习下载适合希望摆脱手动建模重复劳动、掌握FreeCADPython协同开发流程的工程师与学生。用户可直接导入宏脚本批量创建标准件调用Python库实现DXF导入、曲面生成、Minkowski几何运算等高阶操作并通过配套ODS表格与LICENSE文件理解项目规范与扩展逻辑快速构建可复用的机械设计工作流。1. FreeCAD Python 不是“装个插件就出图”而是让机械设计从手动建模升级为参数驱动的工程逻辑闭环很多刚接触 FreeCAD 的机械工程师第一反应是把它当 SolidWorks 或 Fusion 360 的平替——打开软件、拉草图、挤出实体、加倒角、导出 STEP。但真正用过半年以上的人会发现一旦零件变多比如一个钣金机柜含 20 折弯件、版本迭代频繁客户第 7 次改孔位、或需批量生成系列化尺寸M4/M5/M6 螺纹孔阵列自动适配纯 GUI 操作立刻变成重复劳动黑洞。这时标题里那个不起眼的_Python_就成了分水岭它不是“在 FreeCAD 里写点脚本”而是把整个设计过程抽象成可复用、可验证、可版本管理的 Python 工程。你写的create_bracket.py不仅能生成一个支架还能接受thickness2.0, hole_dia4.2, materialAL6061作为输入自动校核最小折弯半径、调用标准件库插入螺母、输出带 BOM 表的 PDF 工程图——这才是标题中“组件等的机械设计”所指的真实工作流。适合两类人一是已掌握 FreeCAD 基础建模但卡在效率瓶颈的工程师二是有 Python 基础会def、for、import想切入机械自动化的新手。本文不讲“如何安装 FreeCAD”而是直接带你用 Python 控制 FreeCAD 内核完成真实设计任务。2. 在 FreeCAD 中启用 Python 自动化不是调用外部脚本而是嵌入式内核级控制FreeCAD 的 Python 集成不是“外部调用”而是其底层完全由 Python 绑定C/Python 混合架构。这意味着你写的代码不是启动一个新进程去操作界面而是直接与 FreeCAD 的文档对象、几何内核OpenCASCADE、求解器FEM、绘图模块TechDraw实时交互。这种深度集成带来两个关键优势一是响应速度极快毫秒级刷新模型二是能访问 GUI 界面不可见的底层数据如拓扑边的曲率、面的法向量、约束求解失败的具体原因。要启用这一能力必须确认当前 FreeCAD 安装的是支持 Python API 的完整版而非精简版或某些 Linux 发行版仓库里的阉割包。2.1 验证 Python 环境是否就绪三步定位核心路径FreeCAD 启动时会加载自身捆绑的 Python 解释器通常为 3.8–3.11该解释器独立于系统 Python。因此不能用pip install freecad不存在此包也不能用系统python3直接运行.py文件来控制 FreeCAD。正确路径是# 步骤1找到 FreeCAD 可执行文件所在目录Linux/macOS which freecad # 典型输出/usr/bin/freecad 或 /Applications/FreeCAD.app/Contents/MacOS/FreeCAD # 步骤2进入其上级目录定位 Python 解释器关键 ls -la $(dirname $(dirname $(which freecad)))/bin/python* # 典型输出/usr/lib/freecad/bin/python3.10 # 步骤3用此解释器验证 FreeCAD 模块是否可导入 /usr/lib/freecad/bin/python3.10 -c import FreeCAD; print(FreeCAD.Version()) # 成功输出类似(0.21.2, Git tag: 0.21.2, 2023/09/12 00:00:00)提示若步骤3报错ModuleNotFoundError: No module named FreeCAD说明你正在使用系统 Python而非 FreeCAD 自带的 Python。此时所有pip install都无效——必须用 FreeCAD 自带的python3.10执行后续操作。2.2 创建第一个参数化支架从草图到实体的完整 Python 流程以下代码在 FreeCAD 内部新建一个文档创建带圆角的矩形草图再拉伸为实体并设置长度、宽度、厚度为可调变量。注意所有操作均通过App.ActiveDocument和Part模块完成不依赖 GUI 点击。# create_bracket.py —— 保存为 .py 文件后在 FreeCAD 的 Python 控制台中执行 # exec(open(/path/to/create_bracket.py).read()) import FreeCAD as App import Part import Sketcher # 1. 创建新文档并激活 doc App.newDocument(BracketDesign) App.setActiveDocument(BracketDesign) App.ActiveDocument doc # 2. 创建草图对象在 XY 平面 sketch doc.addObject(Sketcher::SketchObject, BaseSketch) sketch.Support (doc.getObject(XY_Plane), []) sketch.MapMode FlatFace # 3. 添加几何矩形左下角在原点宽100mm高60mm geoList [] geoList.append(Part.LineSegment(App.Vector(0,0,0), App.Vector(100,0,0))) # 底边 geoList.append(Part.LineSegment(App.Vector(100,0,0), App.Vector(100,60,0))) # 右边 geoList.append(Part.LineSegment(App.Vector(100,60,0), App.Vector(0,60,0))) # 顶边 geoList.append(Part.LineSegment(App.Vector(0,60,0), App.Vector(0,0,0))) # 左边 sketch.addGeometry(geoList, False) # 4. 添加约束固定左下角、定义长宽尺寸 sketch.addConstraint(Sketcher.Constraint(Coincident, 0, 1, 3, 2)) # 点0-1 与 点3-2 重合左下角固定 sketch.addConstraint(Sketcher.Constraint(DistanceX, 0, 1, 0, 2, 100)) # 底边长100mm sketch.addConstraint(Sketcher.Constraint(DistanceY, 2, 1, 2, 2, 60)) # 右边高60mm # 5. 拉伸草图为实体厚度5mm pad doc.addObject(Part::Pad, Pad) pad.Profile sketch pad.Length 5.0 pad.Reversed False # 6. 为后续修改预留参数接口关键 doc.addObject(App::FeaturePython, DesignParameters) param_obj doc.DesignParameters param_obj.addProperty(App::PropertyFloat, Length, Dimensions, 总长度).Length 100.0 param_obj.addProperty(App::PropertyFloat, Width, Dimensions, 总宽度).Width 60.0 param_obj.addProperty(App::PropertyFloat, Thickness, Dimensions, 板厚).Thickness 5.0 # 7. 重建模型以应用所有变更 doc.recompute()代码逻辑与参数说明sketch.Support (doc.getObject(XY_Plane), [])明确指定草图附着在 XY 平面避免因坐标系混乱导致建模失败sketch.addConstraint(...)中的DistanceX/Y约束直接绑定数值100/60这是参数化的起点——后续可改为引用param_obj.Lengthpad.Length 5.0是硬编码值实际项目中应替换为pad.Length param_obj.Thickness实现厚度联动doc.recompute()是强制刷新命令FreeCAD 不会自动重算遗漏此步将导致模型不更新。2.3 关键配置项FreeCAD Python API 的三个必调参数FreeCAD 的 Python 接口默认行为对自动化不友好需在脚本开头显式设置以下参数否则可能遇到“模型不刷新”“约束失效”“中文路径报错”等问题参数名设置方式作用说明不设置的后果App.ConfigGet(UserParameter:BaseApp/Preferences/Mod/Part/BooleanRetainOriginal)设为True布尔运算并集/差集后保留原始体素差集操作后原主体消失无法回溯修改App.ConfigGet(UserParameter:BaseApp/Preferences/Mod/Sketcher/AutoRecompute)设为True草图修改后自动重算约束手动调用sketch.solve()易遗漏导致草图欠约束App.ConfigGet(UserParameter:BaseApp/Preferences/Mod/Part/ExportStepAsBREP)设为False导出 STEP 时使用标准 ACIS 格式设为True会导致某些 CAD 软件如 AutoCAD无法读取# 在脚本顶部添加此段紧随 import 之后 import FreeCAD as App App.ConfigSet(UserParameter:BaseApp/Preferences/Mod/Part/BooleanRetainOriginal, True) App.ConfigSet(UserParameter:BaseApp/Preferences/Mod/Sketcher/AutoRecompute, True) App.ConfigSet(UserParameter:BaseApp/Preferences/Mod/Part/ExportStepAsBREP, False)注意ConfigSet修改的是当前 FreeCAD 会话的内存配置不影响全局设置。若需永久生效需在 FreeCAD GUI 的编辑 → 参数设置 → 基础应用程序 → 首选项中手动勾选。3. 实战用 Python 批量生成系列化法兰盘含孔位阵列、材料属性、工程图机械设计中常见需求同一法兰盘结构需按不同公称直径DN50/DN80/DN100和压力等级PN16/PN25生成多个变体。手动复制粘贴草图尺寸效率极低且易出错。本节用 Python 实现全自动批量生成覆盖从建模、属性标注到 PDF 工程图输出的全链路。3.1 定义法兰盘参数表与模板逻辑首先建立参数映射关系。法兰盘的关键尺寸外径、螺栓孔中心圆直径、螺栓孔数量由 DN 和 PN 决定非线性查表。我们用字典模拟标准手册实际项目中可对接 Excel 或 SQLite 数据库# flange_params.py FLANGE_TABLE { (DN50, PN16): {OD: 165.0, PCD: 125.0, HOLE_COUNT: 4, HOLE_DIA: 18.0}, (DN50, PN25): {OD: 165.0, PCD: 125.0, HOLE_COUNT: 4, HOLE_DIA: 18.0}, (DN80, PN16): {OD: 195.0, PCD: 145.0, HOLE_COUNT: 4, HOLE_DIA: 18.0}, (DN80, PN25): {OD: 195.0, PCD: 145.0, HOLE_COUNT: 8, HOLE_DIA: 18.0}, (DN100, PN16): {OD: 215.0, PCD: 165.0, HOLE_COUNT: 8, HOLE_DIA: 18.0}, (DN100, PN25): {OD: 215.0, PCD: 165.0, HOLE_COUNT: 8, HOLE_DIA: 22.0}, } def get_flange_params(dn, pn): 根据 DN/PN 返回尺寸字典缺失时抛出异常 key (dn, pn) if key not in FLANGE_TABLE: raise ValueError(f未定义法兰参数{dn}/{pn}) return FLANGE_TABLE[key]3.2 构建带螺栓孔阵列的法兰盘实体核心难点在于螺栓孔是环形阵列需用Part.makeCylinder创建单个孔再用Part.Placement旋转复制。FreeCAD 的Part::MultiFuse可合并多个体素但更高效的方式是直接对主法兰体执行多次cut操作。# generate_flange.py import FreeCAD as App import Part import math def create_flange(dn, pn, thickness20.0, materialST37): 生成指定 DN/PN 的法兰盘返回 Part::Feature 对象 params get_flange_params(dn, pn) # 1. 创建法兰基体外径圆柱 中心孔 outer_cyl Part.makeCylinder(params[OD]/2, thickness) inner_cyl Part.makeCylinder(50.0, thickness) # 假设内孔直径50mm flange_body outer_cyl.cut(inner_cyl) # 差集得到环形体 # 2. 创建单个螺栓孔圆柱体 hole_cyl Part.makeCylinder(params[HOLE_DIA]/2, thickness 2.0) # 孔深略大于法兰厚 # 3. 环形阵列计算每个孔的旋转角度和位移 holes [] for i in range(params[HOLE_COUNT]): angle math.radians(360 * i / params[HOLE_COUNT]) # 孔中心在 PCD 圆上 x params[PCD]/2 * math.cos(angle) y params[PCD]/2 * math.sin(angle) # 创建孔的 Placement绕Z轴旋转平移 hole_placement App.Placement( App.Vector(x, y, 0), App.Rotation(App.Vector(0,0,1), 0) ) hole_cyl_placed hole_cyl.copy() hole_cyl_placed.Placement hole_placement holes.append(hole_cyl_placed) # 4. 用所有孔对法兰基体执行差集 for hole in holes: flange_body flange_body.cut(hole) # 5. 创建 FreeCAD 文档对象并赋值 doc App.ActiveDocument part_obj doc.addObject(Part::Feature, fFlange_{dn}_{pn}) part_obj.Shape flange_body part_obj.Label f{dn}-{pn} 法兰盘 # 6. 添加自定义属性材料、标准号等 part_obj.addProperty(App::PropertyString, Material, Properties, 材料).Material material part_obj.addProperty(App::PropertyString, Standard, Properties, 执行标准).Standard GB/T 9119-2010 return part_obj # 批量生成示例 if __name__ __main__: doc App.newDocument(FlangeBatch) App.setActiveDocument(FlangeBatch) variants [(DN50, PN16), (DN50, PN25), (DN80, PN16)] for dn, pn in variants: create_flange(dn, pn, thickness20.0) doc.recompute()关键技术点解析Part.makeCylinder(radius, height)是最稳定的建模原语比草图拉伸更易控制精度hole_cyl.copy()必须调用否则所有Placement会作用于同一对象导致阵列失效flange_body.cut(hole)是布尔差集FreeCAD 中cut比fuse更少出现拓扑错误part_obj.addProperty(...)添加的属性会显示在属性面板中可被工程图模块读取生成 BOM 表。3.3 自动生成带 BOM 表的 PDF 工程图FreeCAD 的 TechDraw 模块支持 Python 脚本化创建视图。以下代码为每个法兰盘生成正视图、俯视图并插入材料明细表BOM最终导出为 PDF# export_drawing.py import FreeCAD as App import TechDraw def create_drawing_for_part(part_obj, scale0.5): 为指定零件创建工程图返回 TechDraw::Page 对象 doc App.ActiveDocument # 1. 创建图纸页A3幅面 page doc.addObject(TechDraw::DrawPage, fDrawing_{part_obj.Name}) template doc.addObject(TechDraw::DrawSVGTemplate, Template) template.Template App.getResourceDir() Mod/TechDraw/Templates/A3_Landscape.svg page.Template template # 2. 创建正视图投影视图 view doc.addObject(TechDraw::DrawViewPart, fView_{part_obj.Name}_Front) view.Source part_obj view.Direction App.Vector(0,0,1) # Z轴方向投影 view.Scale scale view.X 100 view.Y 150 page.addView(view) # 3. 创建俯视图Y轴方向投影 top_view doc.addObject(TechDraw::DrawViewPart, fView_{part_obj.Name}_Top) top_view.Source part_obj top_view.Direction App.Vector(0,1,0) top_view.Scale scale top_view.X 100 top_view.Y 400 page.addView(top_view) # 4. 插入 BOM 表自动提取材料、标准号等属性 bom doc.addObject(TechDraw::DrawViewSymbol, fBOM_{part_obj.Name}) bom.Symbol f材料{part_obj.Material}\n标准{part_obj.Standard} bom.X 100 bom.Y 650 page.addView(bom) return page # 批量导出 PDF if __name__ __main__: doc App.ActiveDocument flange_parts [obj for obj in doc.Objects if obj.Name.startswith(Flange_)] for part in flange_parts: page create_drawing_for_part(part) # 导出为 PDF路径需存在 pdf_path f/tmp/{part.Name}.pdf TechDraw.export([page], pdf_path) print(f已导出{pdf_path})提示TechDraw.export()依赖系统 GhostscriptLinux 下需sudo apt install ghostscriptmacOS 用brew install ghostscript。若报错No module named TechDraw说明当前 FreeCAD 编译时未启用 TechDraw 模块检查安装包是否为完整版。4. 进阶技巧用 Python 实现 FreeCAD 中的钣金折弯展开与 K 因子校准FreeCAD 的 SheetMetal 工作台需单独安装支持钣金设计但其 K 因子决定折弯展开长度的关键参数通常需根据材料、厚度、折弯机吨位手动调整。本节教你用 Python 脚本动态计算并应用 K 因子替代人工查表。4.1 SheetMetal 工作台的 Python 控制要点SheetMetal 模块并非 FreeCAD 内置需通过Addon Manager安装。安装后其 Python API 位于SheetMetal命名空间。关键对象是SheetMetalCmd.makeBend它接受kfactor参数# sheetmetal_kfactor.py import FreeCAD as App import Part import SheetMetal def create_bent_plate(length200, width100, thickness2.0, bend_radius3.0, k_factor0.45): 创建带单次折弯的钣金件自动计算展开长度 doc App.ActiveDocument # 1. 创建平板基体长*宽*厚 plate Part.makeBox(length, width, thickness) # 2. 使用 SheetMetal 命令创建折弯沿 Y 轴方向距左端 80mm 处折弯 bend_obj SheetMetalCmd.makeBend( radiusbend_radius, kfactork_factor, lengthlength - 80, # 折弯后延伸段长度 widthwidth, thickthickness, offset0, extLen0, reliefTypeNone, reliefSize0.5, selEdgeplate.Edges[2], # 选择平板的某条边作为折弯线 flippedFalse, makeSketchTrue ) # 3. 计算理论展开长度验证 K 因数准确性 # 展开长 直边1 直边2 π * (r k*t) * (θ/180) # 此处 θ90°故展开长 (80) (length-80) π*(bend_radius k_factor*thickness)*0.5 developed_length 80 (length - 80) 3.1416 * (bend_radius k_factor * thickness) * 0.5 print(fK因子{k_factor} 时理论展开长度{developed_length:.3f} mm) return bend_obj # 示例对比不同 K 因子下的展开结果 for k in [0.3, 0.45, 0.5]: create_bent_plate(k_factork)4.2 K 因子现场校准用 Python 读取实测折弯件尺寸反推最优 K 值实际生产中K 因子需通过试折实测校准。假设你有一块实测展开料长为L_measured 198.5mm的折弯件直边80mm100mm折弯半径3mm板厚2mm可用以下脚本反解最优 K 值# calibrate_k_factor.py import numpy as np from scipy.optimize import fsolve def developed_length(k, L180, L2100, r3.0, t2.0, theta_deg90): 计算给定 K 因子的展开长度 theta_rad np.radians(theta_deg) return L1 L2 np.pi * (r k * t) * theta_rad / np.pi def error_func(k, L_measured198.5, L180, L2100, r3.0, t2.0): 误差函数计算理论展开长与实测值之差 return developed_length(k, L1, L2, r, t) - L_measured # 求解 K 因子初始猜测值 0.45 k_optimal, fsolve(error_func, 0.45) print(f实测展开长 {198.5}mm 对应的最优 K 因子{k_optimal:.4f}) # 输出校准后的折弯对象 doc App.ActiveDocument bend_obj create_bent_plate(k_factork_optimal)校准逻辑说明fsolve是 SciPy 的数值求解器用于解非线性方程developed_length(k) L_measureddeveloped_length函数严格遵循钣金展开公式确保反推结果可直接用于生产此脚本可集成到企业 MES 系统每次新模具试制后自动更新 K 因子数据库。5. 故障排查FreeCAD Python 脚本常见报错与精准定位方法FreeCAD 的 Python 错误信息常晦涩难懂如RuntimeError: Base::Exception且堆栈不指向具体行号。以下是最常遇到的三类问题及对应诊断方案全部基于 FreeCAD 内置工具无需外部调试器。5.1 “AttributeError: NoneType object has no attribute Shape” —— 对象未创建成功此错误表明你试图访问一个None对象的Shape属性根本原因是前序操作失败如addObject返回None。不要盲目重试先检查文档状态# 在调用 addObject 后立即验证 obj doc.addObject(Part::Box, MyBox) if obj is None: print(警告Part::Box 对象创建失败检查 FreeCAD 是否处于正确工作台Part 工作台) print(当前工作台, App.ActiveDocument.ActiveObject.Name if App.ActiveDocument.ActiveObject else 无) # 强制切换到 Part 工作台 Gui.activateWorkbench(PartWorkbench) obj doc.addObject(Part::Box, MyBox)5.2 “Sketcher::Solve failed” —— 草图约束冲突的快速定位当sketch.solve()失败时FreeCAD 不会告诉你哪条约束冲突。启用调试模式可获取详细日志# 在脚本开头启用 Sketcher 调试 import Sketcher Sketcher.setDebugMode(Sketcher.DebugMode.All) # 创建草图后强制求解并捕获异常 try: sketch.solve() except Exception as e: print(草图求解失败详情, str(e)) # 查看最后添加的约束索引 print(当前约束数量, len(sketch.Constraints)) print(最后3条约束, sketch.Constraints[-3:])5.3 “Part::Feature: Shape is null” —— 拓扑错误的可视化诊断布尔运算cut/fuse失败时Shape为空。此时用Part.show()将中间体素导出为 STEP用其他 CAD 软件如 FreeCAD 自身或 Onshape打开检查几何质量# 在布尔运算后添加诊断代码 result_shape body1.cut(body2) if result_shape.isNull(): print(布尔运算失败导出中间体素供检查) # 导出原始体素 Part.export([body1, body2], /tmp/debug_input.step) # 导出失败的布尔结果即使为空也能看到错误提示 try: Part.export([result_shape], /tmp/debug_result.step) except Exception as e: print(空 Shape 无法导出错误, e) raise RuntimeError(布尔运算失败请检查输入体素是否闭合)提示body1.isNull()和body1.isValid()是 FreeCAD 中判断几何有效性的黄金组合。任何涉及Part操作的脚本都应在关键节点插入这两行验证。本文还有配套的精品资源点击获取