ARTICLE DETAIL

资讯详情

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

python的先进制造技术工业场景模拟第三十五篇:读取工装夹具磨损检测记录,统计夹具定位面磨损量,生成夹具检修清单。

python的先进制造技术工业场景模拟第三十五篇:读取工装夹具磨损检测记录,统计夹具定位面磨损量,生成夹具检修清单。 周三下午机加车间换型前点检。这套液压夹具用了快八个月设备员老周拿游标卡尺比着定位面定位面磨下去 0.12mm 了图纸要求定位面磨损不超过 0.08mm。可我们手里的记录本上是每次点检手写的正常/轻微拉伤/换过垫片根本没法算累计磨损曲线。我翻了翻他们导出的 Excel。这表里有什么老周问。每条是某套夹具某个定位面的单次检测记录带夹具编号、定位面编号、检测日期、实测厚度、原始厚度、使用次数我指着屏幕问题是它只给单次绝对值没算相对磨损量也没按面聚合趋势更没跟阈值比。现在靠老师傅记性判断哪套该修换型时才发现已经超差工件定位漂移首件尺寸全偏。我就想干一件事老周说把每套夹具每个定位面的累计磨损量算出来按磨损速率排个序超阈值的自动进检修清单还能看哪几套是快磨穿的高危件顺便按磨损模式聚个类区分是均匀磨耗还是局部拉伤。比如 F-03 夹具的 A 定位面原始 25.000mm现在 24.878mm磨损 0.122mm我接话按每周检测记录连起来前三个月每月磨 0.01mm后两个月每月磨 0.05mm说明夹紧力偏载了磨耗在加速。这种加速曲线手写本看不出来。对老周点头还有同线十几套夹具有的定位面磨得快是因为毛坯飞边刮擦有的是液压油含磨粒想让程序按磨损量速率加速度分个类以后检修工单直接按红黄绿派。用 pandas 按夹具×定位面聚合检测序列numpy 算磨损量/速率/加速度matplotlib 画磨损曲线热力图柱状图scipy 做磨损趋势线性检验和组间对比scikit-learn 聚类磨损模式networkx 建夹具-定位面磨损关系网我开工程数据自包含合成一批夹具点检数据下载就能跑。敲了行原型wear df.groupby([fixture_id,face_id]).apply(lambda g: g[measured] - g[nominal]) # 负值即磨损wear_rate np.polyfit(days, wear_mm, 1)[0] # 斜率磨损速率完整版用 OOP 封好我说加载器、磨损计算器、趋势分析器、显著性检验器、模式聚类器、关系网、出图器输出检修清单 CSV 5 张图 文字报告存 results/。老周凑近看那以后看报告12 套夹具 36 个定位面超阈值的 5 个其中 F-03-A 磨损 0.122mm 红色磨损速率 0.011mm/周且二阶加速F-07-C 是局部拉伤型均值磨损不大但单点跳变聚类分出均匀磨耗/加速磨耗/局部拉伤/健康四类。检修工单按红黄绿自动生成下周先修 F-03-A 和 F-07-C。对我接话夹具定位面不是易耗品清单里的模糊项是带磨损曲线的过程资产。数字孪生里建夹具寿命模型这些序列就是标定基准。一、实际应用场景真实痛点场景设定机加产线多套工装夹具并行使用定位面长期受装夹力、切屑刮擦、液压油磨粒作用。点检记录以单次实测厚度形式留存但缺乏累计磨损量化、趋势判断与检修派工机制。工艺与设备组需要把点检流水转成可排序、可预警、可派单的夹具检修体系。现场原话叙事化不是我们不管夹具老周说是以前管法太粗。记录本写正常其实已经磨了 0.06mm离阈值就差一丢丢。等到首件尺寸飘了才反查是定位面塌了。每次换型都像开盲盒。还有加速这件事老周补充有套夹具前半年稳得很后俩月突然掉得快是压板偏了导致单边受力。手写记录连不成曲线就当随机磨损处理了其实早该预警。核心矛盾点检绝对值流水 与 按面聚合累计磨损 磨损速率/加速度 超阈预警 模式聚类 检修工单生成 之间的断层。二、痛点分析映射到滨州职业学院《先进制造技术》课程模型《先进制造技术》模块 本篇痛点对应数控加工与CAD/CAM技术工装夹具定位原理、基准统一 定位面磨损→定位精度漂移先进制造技术基础公差、测量技术、磨损与精度保持性 累计磨损量/速率量化FMS与先进生产管理工装管理、预防性维护 检修清单红黄绿派工智能制造与数字孪生夹具寿命数字模型 磨损序列作孪生标定数据先进制造新模式数据驱动预测性维护 磨损模式聚类→预测检修一句话总结我们需要一个工装夹具定位面磨损分析 检修清单生成程序用pandas 按夹具×面聚合序列numpy 算磨损量/速率/加速度matplotlib 画曲线/热力图/柱状图scipy 做趋势显著性与组间检验scikit-learn 聚类磨损模式networkx 建夹具-面关系网实现从点检流水到累计磨损 趋势预警 模式画像 检修工单。三、核心逻辑讲解大白话3.1 问题本质把定位面想成鞋底把夹具定位面想成工人穿了八个月的劳保鞋鞋底* 原始厚度 新鞋底厚度* 实测厚度 现在鞋底剩多厚* 磨损量 新厚度 - 现在厚度正数就是磨掉了* 磨损速率 每周磨掉多少像看鞋底每月薄多少* 磨损加速度 最近是不是越磨越快鞋底后俩月突然露钉子* 阈值 0.08mm 鞋底磨到这条线就必须换* 均匀磨耗 整片平平地薄* 局部拉伤 某一点被飞边刮出坑均值不大但跳变* 检修清单 按红黄绿排好红的直接停线换3.2 业务逻辑 → 代码映射导入点检记录│▼ FixtureLoader (pandas)读取 CSVfixture_id, face_id, check_date, nominal, measured, usage_cnt算 wear_mm nominal - measured按日期排序│▼ WearCalculator (numpy/pandas)按 夹具×面 聚合累计磨损量 / 当前磨损 / 最小剩余厚度│▼ TrendAnalyzer (numpy)趋势拟合一阶拟合斜率 → 磨损速率 (mm/周)二阶拟合系数 → 磨损加速度局部跳变检测 → 识别拉伤│▼ WearStatistics (scipy)统计检验磨损趋势线性显著性 (p值)多夹具同面组间对比 (ANOVA)│▼ WearProfiler (scikit-learn)磨损模式聚类特征[累计磨损, 速率, 加速度, 跳变幅度]KMeans → 健康/均匀磨耗/加速磨耗/局部拉伤│▼ FixtureGraph (networkx)夹具-定位面关系网节点夹具/面边权当前磨损量超阈边标红│▼ FixtureVisualizer (matplotlib)可视化1. 各定位面磨损曲线(含阈值线)2. 夹具×面磨损热力图3. 超阈检修柱状图(红黄绿)4. 磨损模式聚类散点5. 夹具-面关系网│▼ SyntheticFixtureGenerator (numpy)合成数据多夹具×多定位面×多期点检含加速磨耗面、局部拉伤面3.3 为什么不能只看最新一次实测视角 问题只看最新厚度 24.878 不知道是匀速磨还是加速磨手写正常/异常 无量化无法预警磨损曲线速率加速度 加速段提前 2 个月预警模式聚类 区分均匀磨 vs 局部拉伤修法不同3.4 分析前后对比维度 手写点检本 本程序累计磨损 心算 自动聚合趋势判断 凭感觉 速率加速度量化超阈预警 首件飘了才知 提前进红单修法分类 老师傅经验 聚类分模式工单派发 换型临时排 红黄绿自动生成四、OOP 代码实现4.1 项目结构fixture_wear_analysis/├── fixture_wear_analysis/│ ├── __init__.py│ ├── fixture_loader.py # 点检数据加载│ ├── wear_calculator.py # 磨损量计算│ ├── trend_analyzer.py # 速率/加速度拟合│ ├── wear_statistics.py # 统计检验(scipy)│ ├── wear_profiler.py # 模式聚类(sklearn)│ ├── fixture_graph.py # 夹具-面关系网(networkx)│ ├── visualizer.py # 可视化│ └── synthetic_data.py # 合成数据├── tests/│ ├── __init__.py│ └── test_fixture_wear.py├── results/│ ├── wear_curves.png│ ├── wear_heatmap.png│ ├── maintenance_bar.png│ ├── wear_cluster.png│ ├── fixture_network.png│ ├── wear_summary.csv│ ├── maintenance_list.csv│ ├── wear_clusters.csv│ └── fixture_report.txt└── run_fixture_analysis.py4.2 核心源码detailssummary/summary工装夹具点检数据加载器import pandas as pdfrom pathlib import Pathfrom typing import Optionalclass FixtureLoader:加载夹具定位面点检CSVdef __init__(self, filepath: str fixture_check.csv,encoding: str utf-8):self.filepath Path(filepath)self.encoding encodingself._raw: Optional[pd.DataFrame] Nonedef load(self) - pd.DataFrame:if not self.filepath.exists():raise FileNotFoundError(f文件不存在: {self.filepath})self._raw pd.read_csv(self.filepath, encodingself.encoding)rename {}for tgt, al in {fixture_id: [fixture_id, 夹具编号, fix],face_id: [face_id, 定位面, face],check_date: [check_date, 检测日期, date],nominal: [nominal, 原始厚度, nom],measured: [measured, 实测厚度, act],usage_cnt: [usage_cnt, 使用次数, cnt],}.items():if tgt not in self._raw.columns:for a in al:if a in self._raw.columns:rename[a] tgtbreakself._raw self._raw.rename(columnsrename)req [fixture_id, face_id, check_date, nominal, measured]miss [c for c in req if c not in self._raw.columns]if miss:raise ValueError(f缺少必要列: {miss})self._raw[fixture_id] self._raw[fixture_id].astype(str).str.strip()self._raw[face_id] self._raw[face_id].astype(str).str.strip()self._raw[check_date] pd.to_datetime(self._raw[check_date], errorscoerce)self._raw[nominal] pd.to_numeric(self._raw[nominal], errorscoerce)self._raw[measured] pd.to_numeric(self._raw[measured], errorscoerce)self._raw[usage_cnt] pd.to_numeric(self._raw.get(usage_cnt, 0), errorscoerce).fillna(0).astype(int)self._raw self._raw.dropna(subset[nominal, measured, check_date]).copy()self._raw[wear_mm] (self._raw[nominal] - self._raw[measured]).round(4)self._raw self._raw.sort_values([fixture_id, face_id, check_date]).reset_index(dropTrue)return self._raw/detailsdetailssummary/summary磨损量计算 (numpy/pandas)import numpy as npimport pandas as pdfrom typing import Optionalclass WearCalculator:按夹具×定位面聚合累计磨损def __init__(self):passdef summarize(self, df: pd.DataFrame) - pd.DataFrame:rows []for (fix, face), g in df.groupby([fixture_id, face_id]):g g.sort_values(check_date)wear g[wear_mm].valuesdays (g[check_date] - g[check_date].iloc[0]).dt.days.valuesweeks days / 7.0current_wear float(wear[-1])total_span_w float(weeks[-1]) if len(weeks) 1 else 1.0avg_rate current_wear / max(total_span_w, 1e-6)rows.append({fixture_id: fix,face_id: face,check_count: len(g),current_wear_mm: round(current_wear, 4),max_wear_mm: round(float(np.max(wear)), 4),min_remaining_mm: round(float(g[measured].min()), 3),avg_wear_rate_mm_wk: round(avg_rate, 5),total_usage: int(g[usage_cnt].max()) if usage_cnt in g else 0,first_date: g[check_date].iloc[0].strftime(%Y-%m-%d),last_date: g[check_date].iloc[-1].strftime(%Y-%m-%d),})return pd.DataFrame(rows).sort_values(current_wear_mm, ascendingFalse).reset_index(dropTrue)def over_threshold(self, summary_df: pd.DataFrame,threshold: float 0.08) - pd.DataFrame:out summary_df.copy()out[over_thresh] out[current_wear_mm] thresholdout[margin_mm] (out[current_wear_mm] - threshold).round(4)return out/detailsdetailssummary/summary磨损趋势分析速率 加速度 跳变 (numpy)import numpy as npimport pandas as pdfrom typing import Optionalclass TrendAnalyzer:一阶拟合: wear k1*weeks b - k1 磨损速率二阶拟合: wear k2*weeks^2 k1*weeks b - k2 加速度项跳变: 相邻检测磨损增量 jump_thr 判定局部拉伤def __init__(self, jump_thr_mm: float 0.04):self.jump_thr jump_thr_mmdef analyze(self, df: pd.DataFrame, summary_df: pd.DataFrame) - pd.DataFrame:out summary_df.copy()rate_lst, acc_lst, jump_lst [], [], []for _, r in out.iterrows():g df[(df[fixture_id] r[fixture_id]) (df[face_id] r[face_id])].sort_values(check_date)wear g[wear_mm].values.astype(float)days (g[check_date] - g[check_date].iloc[0]).dt.days.valuesweeks days / 7.0if len(weeks) 2:k1, b np.polyfit(weeks, wear, 1)if len(weeks) 3:k2, _, _ np.polyfit(weeks, wear, 2)else:k2 0.0# 相邻增量diffs np.diff(wear)max_jump float(np.max(diffs)) if len(diffs) else 0.0else:k1, k2, max_jump 0.0, 0.0, 0.0rate_lst.append(round(float(k1), 5))acc_lst.append(round(float(k2), 6))jump_lst.append(round(max_jump, 4))out[wear_rate_mm_wk] rate_lstout[wear_accel] acc_lstout[max_jump_mm] jump_lstout[is_accelerating] out[wear_accel] 1e-4out[is_local_gouge] out[max_jump_mm] self.jump_thrreturn out/detailsdetailssummary/summary磨损统计检验 (scipy)import numpy as npimport pandas as pdfrom scipy import statsfrom typing import Dict, Listclass WearStatistics:趋势显著性 同面多夹具对比def __init__(self, alpha: float 0.05):self.alpha alphadef trend_significance(self, df: pd.DataFrame) - pd.DataFrame:各面磨损线性趋势显著性rows []for (fix, face), g in df.groupby([fixture_id, face_id]):g g.sort_values(check_date)wear g[wear_mm].valuesdays (g[check_date] - g[check_date].iloc[0]).dt.days.valuesweeks days / 7.0if len(weeks) 3:rows.append({fixture_id: fix, face_id: face,slope: 0.0, p_value: np.nan,significant: False})continueslope, intercept np.polyfit(weeks, wear, 1)# 残差做相关性检验pred slope * weeks interceptres wear - predif np.std(weeks, ddof1) 1e-6:p np.nanelse:_, p stats.pearsonr(weeks, wear)rows.append({fixture_id: fix, face_id: face,slope: round(float(slope), 5),p_value: round(float(p), 4),significant: bool(p self.alpha),})return pd.DataFrame(rows)def face_anova(self, df: pd.DataFrame, face_id: str) - Dict:同定位面不同夹具磨损量对比groups []for _, g in df[df[face_id] face_id].groupby(fixture_id):if len(g) 1:groups.append(g[wear_mm].values)if len(groups) 2:return {face: face_id, f_statistic: np.nan,p_value: np.nan, significant: False}f, p stats.f_oneway(*groups)return {face: face_id, f_statistic: round(float(f), 4),p_value: round(float(p), 4),significant: bool(p self.alpha)}/detailsdetailssummary/summary磨损模式聚类 (scikit-learn)import numpy as npimport pandas as pdfrom sklearn.cluster import KMeansfrom sklearn.preprocessing import StandardScalerfrom typing import Optionalclass WearProfiler:基于磨损量/速率/加速度/跳变 聚类模式def __init__(self, n_clusters: int 4, random_state: int 42):self.n_clusters n_clustersself.random_state random_statedef profile(self, trend_df: pd.DataFrame) - pd.DataFrame:df trend_df.copy()feat_cols [current_wear_mm, wear_rate_mm_wk,wear_accel, max_jump_mm]for c in feat_cols:if c not in df.columns:df[c] 0.0X df[feat_cols].fillna(0).valuesscaler StandardScaler()Xs scaler.fit_transform(X)km KMeans(n_clustersself.n_clusters, random_stateself.random_state)df[cluster] km.fit_predict(Xs)centers scaler.inverse_transform(km.cluster_centers_)label_map {}for i, c in enumerate(centers):wear, rate, acc, jump cif jump 0.04:label_map[i] 局部拉伤型elif acc 1e-4 and wear 0.08:label_map[i] 加速磨耗型elif wear 0.05:label_map[i] 均匀磨耗型else:label_map[i] 健康型df[wear_pattern] df[cluster].map(label_map)return dfdef pattern_summary(self, df: pd.DataFrame) - pd.DataFrame:if wear_pattern not in df.columns:return pd.DataFrame()rows []for pat, g in df.groupby(wear_pattern):rows.append({pattern: pat,count: len(g),avg_wear_mm: round(g[current_wear_mm].mean(), 4),avg_rate_mm_wk: round(g[wear_rate_mm_wk].mean(), 5),items: , .join((g[fixture_id] - g[face_id]).tolist()[:10]),})order {健康型:0, 均匀磨耗型:1, 加速磨耗型:2, 局部拉伤型:3}return pd.DataFrame(rows).sort_values(pattern, keylambda s: s.map(order)).reset_index(dropTrue)/detailsdetailssummary/summary夹具-定位面磨损关系网 (networkx)import networkx as nximport pandas as pdfrom typing import Optionalclass FixtureGraph:建夹具-面关系网, 边权当前磨损量def __init__(self):self.G nx.DiGraph()def build(self, df: pd.DataFrame,threshold: float 0.08) - nx.DiGraph:self.G.clear()for fix in df[fixture_id].unique():self.G.add_node(fFIX:{fix}, ntypefixture)for _, r in df.iterrows():fnode fFIX:{r[fixture_id]}snode fFACE:{r[fixture_id]}_{r[face_id]}self.G.add_node(snode, ntypeface)w float(r[current_wear_mm])self.G.add_edge(fnode, snode, weightround(w, 4))if w threshold:self.G.edges[fnode, snode][over] Truereturn self.Gdef red_edges(self) - pd.DataFrame:rows []for u, v, d in self.G.edges(dataTrue):if d.get(over, False):rows.append({fixture: u.split(:)[-1],face: v.split(:)[-1].split(_)[-1],wear_mm: d[weight],})return pd.DataFrame(rows).sort_values(wear_mm, ascendingFalse).reset_index(dropTrue)/detailsdetailssummary/summary可视化 (matplotlib)import numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom pathlib import Pathplt.rcParams[font.sans-serif] [SimHei, DejaVu Sans]plt.rcParams[axes.unicode_minus] Falseclass FixtureVisualizer:def __init__(self, results_dir: str results):self.results_dir Path(results_dir)self.results_dir.mkdir(exist_okTrue)def wear_curves(self, df, threshold0.08):各定位面磨损曲线fig, ax plt.subplots(figsize(13, 7))fixes df[fixture_id].unique()cmap plt.cm.tab10(np.linspace(0, 1, len(fixes)))fmap {f: cmap[i] for i, f in enumerate(fixes)}for (fix, face), g in df.groupby([fixture_id, face_id]):g g.sort_values(check_date)ax.plot(g[check_date], g[wear_mm],markero, ms3, lw1.2,colorfmap[fix], labelf{fix}-{face})ax.axhline(threshold, colorred, ls--, lw1.5,labelf阈值 {threshold}mm)ax.set_ylabel(累计磨损量 (mm))ax.set_xlabel(检测日期)ax.set_title(各夹具定位面磨损曲线, fontsize14, fontweightbold)ax.legend(fontsize7, ncol2)ax.grid(alpha0.3)plt.tight_layout()plt.savefig(self.results_dir / wear_curves.png,dpi150, bbox_inchestight)plt.close()def heatmap(self, summary_df):夹具×面 磨损热力图pivot summary_df.pivot(indexfixture_id, columnsface_id,valuescurrent_wear_mm)fig, ax plt.subplots(figsize(10, 7))im ax.imshow(pivot.values, cmapYlOrRd, aspectauto)ax.set_xticks(range(len(pivot.columns)))ax.set_xticklabels(pivot.columns)ax.set_yticks(range(len(pivot.index)))ax.set_yticklabels(pivot.index)for i in range(pivot.shape[0]):for j in range(pivot.shape[1]):v pivot.values[i, j]ax.text(j, i, f{v:.3f}, hacenter, vacenter,fontsize8, colorblack)ax.set_title(夹具×定位面 当前磨损量热力图 (mm),fontsize14, fontweightbold)plt.colorbar(im, axax)plt.tight_layout()plt.savefig(self.results_dir / wear_heatmap.png,dpi150, bbox_inchestight)plt.close()def maintenance_bar(self, maint_df, threshold0.08):检修清单柱状图(红黄绿)d maint_df.sort_values(current_wear_mm, ascendingFalse)fig, ax plt.subplots(figsize(12, 6))colors []for _, r in d.iterrows():if r[current_wear_mm] threshold:colors.append(#E74C3C) # 红elif r[current_wear_mm] threshold * 0.75:colors.append(#F39C12) # 黄else:colors.append(#27AE60) # 绿ax.bar(range(len(d)), d[current_wear_mm], colorcolors,edgecolorwhite)ax.axhline(threshold, colorred, ls--, labelf阈值{threshold})ax.set_xticks(range(len(d)))ax.set_xticklabels(d[fixture_id] - d[face_id],rotation45, fontsize7)ax.set_ylabel(当前磨损量 (mm))ax.set_title(夹具定位面检修优先级(红超阈 黄临界 绿正常),fontsize13, fontweightbold)ax.legend()ax.grid(axisy, alpha0.3)plt.tight_layout()plt.savefig(self.results_dir / maintenance_bar.png,dpi150, bbox_inchestight)plt.close()def cluster_scatter(self, df):磨损模式聚类散点if wear_pattern not in df.columns:returnfig, ax plt.subplots(figsize(10, 7))pats [健康型, 均匀磨耗型, 加速磨耗型, 局部拉伤型]cmap {健康型:#27AE60,均匀磨耗型:#3498DB,加速磨耗型:#F39C12,局部拉伤型:#E74C3C}for pat in pats:sub df[df[wear_pattern] pat]if sub.empty:continueax.scatter(sub[current_wear_mm], sub[wear_rate_mm_wk],ccmap[pat], labelpat, s70,利用AI解决实际问题如果你觉得这个工具好用欢迎关注长安牧笛
返回列表