ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

NX二次开发Python实战:如何计算包络尺寸与坯料尺寸

NX二次开发Python实战:如何计算包络尺寸与坯料尺寸 开篇先交代一个背景最近在帮注塑模团队做一套下料统计工具核心需求很简单——在NX里选中零件或打开一个prt程序自动算出这块料的长、宽、高再把结果填进BOM属性、导出下料单。听上去就是“测量体”三个字的事但真正落地的时候发现从“量一个数”到“算出一个车间能用的坯料尺寸”中间隔着坐标系、余量规则、单位换算、异常体过滤一堆细节。我选择用Python而不是C来做NX二次开发原因也很实际开发周期短、不用编译、NX从11.0版本开始就内置了Python解释器录一段Journal再改一改就能用。这篇文章是“坯料尺寸”系列的第一篇先把最核心的包络尺寸计算讲清楚后面再陆续展开毛坯块自动生成、装配体整体尺寸、通孔盲孔识别这些延伸内容。最近社区里聊NX MCP的朋友不少AI辅助写NX脚本确实能提速但如果连底层的包络计算逻辑都没掌握AI生成一堆API调用也未必能过验证。我始终觉得二次开发里最值钱的不是代码本身而是你知道“为什么用这个接口、这个数算出来能不能用”。这篇就把这块地基夯实。1. 先把“坯料尺寸”这个概念跟工程师对齐很多新手一上来就写代码结果算出来的数和车间老师傅说的“毛坯尺寸”对不上问题往往出在概念没对齐。坯料尺寸指的是零件在进入机加工之前下料阶段需要准备的原材料尺寸可能是一块板材的长宽厚可能是一根棒料的直径和长度也可能是一个锻件毛坯的外廓。它跟三维模型里实体的包围盒尺寸有强关联但绝不是同一个东西。1.1 为什么不能直接拿“测量体”的结果当坯料尺寸NX的“测量体”功能或GetBoundingBox得到的是模型几何在当前坐标系下的最大外接长方体范围它只反映几何外形完全不考虑加工工艺。车间下料不会按照“模型净尺寸”来切料至少要预留加工余量铣削要留夹持位和精加工余量磨削要留磨量线切割要留穿丝位置。另外采购标准规格板材时长宽必须按照供应商能提供的规格圆整比如你算出212.6mm车间大概率会直接按220mm甚至230mm下料因为220mm正好是一张板的整数分割尺寸。我一开始只导出了模型的长宽高车间反馈过两次“没法用”后来才把余量和圆整规则做进程序里。所以这套系列文章里说的“坯料尺寸”准确讲是模型包络尺寸 工艺余量 采购/下料圆整规则。第一篇先解决包络尺寸怎么算余量和圆整在第五部分讲。1.2 哪些项目场景真正需要程序化计算手动测量一个零件的包络尺寸一分钟内能搞定为什么还要写程序我实际遇到的需求大概有三类批量BOM刷新设计变更后几十个零件的外形尺寸全部变了下料单要重新生成手动一个个量根本不现实参数化驱动通过表达式或电子表格驱动模型尺寸每次变化都要自动更新毛坯这必然要靠二次开发而不是人工操作跨系统数据交互把NX里的外形尺寸写到属性、导出到Excel/CSV再传给ERP或MES系统手动量出来的数很难保证和模型一致。如果你也是这类需求这篇文章的脚本可以直接抄作业。如果你只是偶尔想量一个零件的尺寸那确实没必要做二次开发记住这个边界能省很多事。2. NX Python开发环境从录Journal到自己写脚本入门的最大障碍不是API不熟而是很多人不知道“NX里怎么写Python、怎么跑起来”。NX的Python支持不是外挂一个解释器而是随软件一起发布的CPython环境所以不需要你额外安装Python。所有NXOpen Python脚本本质上和录制的Journal是同一种东西只不过Journal是你手动操作时系统自动生成的代码我们自己写就是结构化、可复用的版本。2.1 版本要求与内置解释器从NX 11.0开始Siemens就提供了Python Journal功能后续1880、1926、2206、2306、2412这些版本都在持续完善。我日常主力是NX 2206和NX 2306下面的代码在这两个版本上都验证过。打开NX之后你可以在菜单栏找到Tools Journal这里面有Record、Run、Edit三个主要入口。Record是录制Run是运行某个.py文件Edit是打开最近录制的脚本。第一次接触的人我建议先做一步手动创建一个方块然后Tools Journal Record随便做几个操作停止录制再用Edit打开生成的文件看一眼。你会瞬间理解NX Python脚本的骨架长什么样开头import NXOpen和import NXOpen.UF然后Session.GetSession()拿到会话对象所有操作都从会话和Part对象出发。2.2 三种运行脚本的方式第一种Tools Journal Run选择.py文件。最常用适合已经写好的脚本运行后输出结果不修改模型。第二种File Execute NX Open。效果和Run类似我更习惯用Journal Run因为入口短。第三种在Recording状态下操作让NX自己生成代码然后保存成自己的工具。这种方式适合查API不适合正式工程因为生成的代码噪音很大。在NX 12之后的版本里还有一个非常方便的入口直接在Command Finder命令查找器里输入“Journal”也能快速定位到录制和运行入口。2.3 要不要装VS Code或PyCharm很多朋友纠结开发环境其实NX Python脚本没必要走复杂IDE。因为NX内置的解释器只存在于NX进程内部VS Code和PyCharm都不能直接“运行”NX脚本。你可以用它们来写代码、做语法高亮但执行和调试一定是在NX里完成。我个人习惯是用VS Code写代码写好后到NX里Journal Run。如果你追求更舒服的调试体验可以后续研究NX的远程调试功能但第一篇文章不建议在这里卡住。另有几个内置Python环境的特点需要提前知道不能用pip install到NX内置Python里至少在标准授权方式下很麻烦numpy、pandas这些第三方库默认不可用但csv、json、os、math这些标准库是可以import的如果你需要做复杂数学计算要么用NX自己的数学API要么把数据导出到外部用你自己的Python环境处理。这个限制在很多人第一次写NX脚本时会踩坑。比如想直接import numpy算矩阵结果报ModuleNotFoundError。我后来的做法是涉及复杂算法时先在外部用普通Python写一个独立的小工具验证再把结果通过文件传给NX脚本两边解耦。3. 计算包络尺寸的三条技术路线现在进入正题怎么用代码拿到一个体的长宽高。NX的API体系里至少有三种拿法各有优势和局限。我分别说清楚你按自己的NX版本和精度要求选。3.1 NXOpen对象方式Body.GetBoundingBox()NXOpen是NX二次开发的官方推荐接口体系C、C#、Python都有对应封装。对一个具体实体可以直接调用Body.GetBoundingBox()拿到一个包含最小角点和最大角点的对象或数组不同NX版本对这个返回值类型的封装略有差异。有的版本返回一个BoundingBox对象里面有CenterPoint之类的属性有的版本直接返回6个浮点数。最稳妥的办法是在你的NX里按F11打开录制然后手动选中一个体用“分析→测量”或者“创建包容块”操作录出来的代码里就会展示当前版本GetBoundingBox的真实用法。我的经验是这个接口适合需要快速拿到某个体的局部包络但想要遍历整个part所有体的总包络时每次都去解析返回值反而麻烦。3.2 UF函数方式UF_MODL_ask_bounding_boxUF函数是NX的老牌C接口虽然官方一直说推荐用NXOpen但UF函数在Python里依然可以调用而且稳定性极好。我这套工具的核心就是用UF_MODL_ask_bounding_box。它接收一个tag实体的标识返回一个长度为6的浮点数数组前三个值是最小角点的X、Y、Z后三个值是最大角点的X、Y、Z。在Python里的调用方式是这样的import NXOpen import NXOpen.UF ufs NXOpen.UF.UFSession.GetUFSession() box ufs.Modl.AskBoundingBox(body.Tag)body.Tag在Python里可以直接作为整型传入这一点对新手很友好。拿到box之后box[0]到box[2]是min角点box[3]到box[5]是max角点长宽高就是对应坐标相减。这个接口返回的单位是部件单位。如果你的prt单位是毫米返回的就是毫米如果是英寸返回的就是英寸。做工具时一定要统一单位我习惯在输出前做一次round四舍五入保留三位小数。3.3 遍历Face求极值自定义方向的前置方案当你遇到一个斜着放置的零件或者希望按工作坐标系的某个方向而不是绝对坐标系方向来算尺寸时UF和NXOpen的默认包围盒都不够用。这时候你需要自己遍历实体的所有面再遍历每个面上的边或者顶点把所有点投影到目标方向轴上求最小值、最大值。这套逻辑本身不复杂但计算量和代码量会明显上升。对于第一篇文章我不展开写完整代码只给一个思路先收集体上所有面的顶点坐标然后定义三个目标方向向量比如工作坐标系的X轴、Y轴、Z轴每个点分别和方向向量做点积取每个方向上的最小值和最大值差值就是该方向上的“投影尺寸”。这就是最小有向包围盒OBB的雏形。后续如果大家的零件普遍是斜的我再专门写一篇。三种方式对比如下方案稳定性代码量灵活性适用场景Body.GetBoundingBox()中等版本差异大少低快速看单个体UF_MODL_ask_bounding_box高老接口稳定中中批量统计、工具开发遍历Face求极值高但代码复杂多高需自定义方向或OBB我目前的生产工具默认用UF函数这样不管在哪个NX版本上跑行为都一致。如果遇到方向不对的零件再进入自定义方向分支处理。4. 完整脚本求当前工作part中所有体的最大包络尺寸下面这段脚本是我工具里最基础的一个版本用途是打开任意一个prt运行它自动计算当前工作部件下所有实体体的整体包络尺寸并输出最小角点、最大角点以及X/Y/Z方向尺寸。import NXOpen import NXOpen.UF def listing_write(the_session, text): 把文本输出到NX的信息窗口 listing_window the_session.ListingWindow() listing_window.Open() listing_window.WriteLine(text) def main(): the_session NXOpen.Session.GetSession() work_part the_session.Parts.Work if work_part is None: print(没有打开的工作部件请先打开一个prt再运行) return ufs NXOpen.UF.UFSession.GetUFSession() min_pt [float(inf), float(inf), float(inf)] max_pt [float(-inf), float(-inf), float(-inf)] body_count 0 for body in work_part.Bodies: tag body.Tag try: box ufs.Modl.AskBoundingBox(tag) except Exception as ex: listing_write(the_session, 体 %s 计算失败: %s % (body.JournalIdentifier, str(ex))) continue body_count 1 min_pt[0] min(min_pt[0], box[0]) min_pt[1] min(min_pt[1], box[1]) min_pt[2] min(min_pt[2], box[2]) max_pt[0] max(max_pt[0], box[3]) max_pt[1] max(max_pt[1], box[4]) max_pt[2] max(max_pt[2], box[5]) if max_pt[0] min_pt[0]: listing_write(the_session, 当前part没有找到任何可计算的实体体) return dx round(max_pt[0] - min_pt[0], 3) dy round(max_pt[1] - min_pt[1], 3) dz round(max_pt[2] - min_pt[2], 3) listing_write(the_session, 共统计实体体数量: %d % body_count) listing_write(the_session, 最小角点: (%s, %s, %s) % (min_pt[0], min_pt[1], min_pt[2])) listing_write(the_session, 最大角点: (%s, %s, %s) % (max_pt[0], max_pt[1], max_pt[2])) listing_write(the_session, 包络尺寸: 长X宽X高 %s X %s X %s % (dx, dy, dz)) listing_write(the_session, 对应方向: X %s, Y %s, Z %s % (dx, dy, dz)) if __name__ __main__: main()这段代码有几点值得说明。第一work_part.Bodies遍历的是当前部件下所有实体body包括实体和片体具体和版本有关。如果你的prt里有大量片体不想统计它们可以在遍历时加一个body.IsSolidBody判断但这个属性在不同NX版本里命名略有差异建议用录制Journal的方式确认一下准确写法。第二listing_write这个函数封装了信息窗口输出。NX的print在Journal运行时输出位置不稳定有时候能看到有时候被吞掉。信息窗口输出是NX Open Python最可靠的显示方式尤其适合工具类脚本。你打开信息窗口的快捷键是CtrlShiftL或者通过Window Output。第三异常处理很关键。一个prt里可能有损坏的几何体、轻量级体或者比较特殊的构造体直接调用BoundingBox偶尔会报错。我的处理方式是单个体失败不中断整个程序打印出JournalIdentifier方便你回到模型里定位问题体。要验证脚本对不对最快的方法是新建一个prt插入一个100x50x20的方块体然后运行脚本。正常输出应该类似共统计实体体数量: 1 最小角点: (0.0, 0.0, 0.0) 最大角点: (100.0, 50.0, 20.0) 包络尺寸: 长X宽X高 100.0 X 50.0 X 20.0 对应方向: X 100.0, Y 50.0, Z 20.0如果你把方块旋转45度再运行会发现长宽高变成一组和原来完全不同的数值。这不是代码出错而是UF函数的包围盒始终基于绝对坐标系的X/Y/Z方向模型一旋转外接长方体的范围就变了。这就引出下一部分最重要的话题怎样保证你算出来的尺寸是“车间能用”的尺寸。5. 让结果可用从包络尺寸到真正的坯料尺寸很多教程写到第四部分就结束了但现实中拿到一个“绝对坐标系下的长宽高”往往还不够。真正要让结果可用必须处理三个问题方向对齐、余量规则、结果输出。5.1 方向问题WCS与绝对坐标系先说坐标系。UF_MODL_ask_bounding_box和大部分NX内置测量体功能一样返回的是绝对坐标系下的包络范围。在模具设计、机械加工场景里零件在建模时一般会尽量把主方向摆正到绝对坐标方向这时候直接用没问题。但总会有一些零件是斜着建模的或者为了装配方便主方向和工作坐标系的某个轴对齐而不是和绝对坐标对齐。遇到这种情况最简单粗暴的修正方案有两个方案A在NX里手动把WCS旋转到目标方向然后旋转体或移动体把模型摆正后再算。这个方案适合单个零件不适合批量。方案B程序里读取当前工作坐标系WCS的三个轴方向把实体的所有关键点投影到WCS轴上得到按WCS方向的外接尺寸。这个方案可封装成通用函数但代码量不小。对于第一篇文章我的建议是先确认你的模型有没有摆正。90%的规则零件其实都是好的只有少数斜装零件需要特殊处理。等这套基础脚本跑通之后再针对斜装零件写一个“按WCS方向求投影尺寸”的增强版函数。5.2 余量和圆整规则怎么加拿到了包络尺寸不等于拿到了坯料尺寸。实际项目中长宽高三个方向都要根据不同加工工艺加放余量。我在这套工具里把余量配置做成一个独立的JSON或Python字典由工艺工程师维护而不是写死在代码里。一个简单示例MARGIN_RULES { cnc: {x: 2.0, y: 2.0, z: 3.0}, grind: {x: 0.5, y: 0.5, z: 0.5}, wire_edm: {x: 1.0, y: 1.0, z: 0.2}, } def apply_margin(dx, dy, dz, rule_namecnc): rule MARGIN_RULES[rule_name] final_dx dx rule[x] final_dy dy rule[y] final_dz dz rule[z] return final_dx, final_dy, final_dz圆整规则就更有行业味道了。板料下料通常按“逢5进1”或“逢10进1”棒料按标准直径靠档。举例你算出某块板的长度为122.4mm按10mm圆整规格应当取130mm宽度81.2mm取90mm。这个逻辑可以用一段很短的代码实现import math def round_up_to_step(size, step10): return math.ceil(size / step) * step但注意这种“逢10进1”不是所有车间都适用有的精加工车间可能要求“逢5进1”。所以最好把圆整步长也做成配置项不要让算法替你拍板。5.3 把结果写进属性或导出CSV打印到信息窗口只是调试阶段的做法生产环境要把结果沉淀下来。最常见的两种做法是写属性和导CSV。写属性的话可以用NXOpen的属性API把长宽高、坯料编码写到部件属性或体属性。具体接口在不同版本有差异我建议你先用录制Journal的方式走一遍“属性→编辑属性”看看录制代码里的真实API再改成自己的逻辑。关键点是属性名要提前和BOM、ERP团队约定好避免大小写和命名不一致。导CSV反而简单因为NX内置Python的标准库是完整的直接用csv模块写文件即可import csv import os def export_dimension_to_csv(file_path, dx, dy, dz): with open(file_path, w, newline) as f: writer csv.writer(f) writer.writerow([名称, X/mm, Y/mm, Z/mm]) writer.writerow([当前部件, dx, dy, dz])我实际项目里的做法是选一个局域网共享目录程序跑完后把整个文件夹下所有prt的尺寸统一汇总成一个CSV然后下游的ERP定时任务去读这个文件。这样设计和生产之间就有了一个“脏活累活”的自动通道不需要人为抄数。5.4 后面几篇我会写什么坯料尺寸这个方向可以一直往下挖。第二篇我打算讲如何根据包络尺寸自动生成一个毛坯块体Block并把毛坯块放到指定图层第三篇讲装配环境下统计所有组件整体包络尺寸这里会涉及轻量级组件、Reference Set、隐藏组件等一堆边界情况再往后可以聊特征识别比如区分通孔和盲孔通过面的拓扑关系判断孔类型用于估算加工工时和线切割路径。这些都是实际车间项目里会连续遇到的问题一篇篇拆开写每一篇都可以直接落地。最后分享一个我在实际使用中发现的细节UF_MODL_ask_bounding_box返回的是当前几何的真实包络但如果模型里有被抑制的特征、轻量级显示状态或者小平面体统计结果可能和设计人员肉眼看到的不一样。所以自动计算做完之后建议在交付前人工抽查两三个模型尤其是带WAVE链接或者大量特征的复杂part。这个经验是常规教程里不会写的但搞二次开发的人早晚会遇到。
返回列表