☰
python的先进制造技术工业场景模拟第八十二篇:仿真数控粗精工序加工流程,模拟刀具磨损逐步累积,观察零件粗糙度逐步劣化。
2026/10/7 15:13:39 网站建设 项目流程

周五白班,精加工工位巡检。

“这批轴套,前50件还亮得像镜子,到第80件开始发雾,第120件三坐标一量,Ra从0.8飘到1.6了,”数控操作工老肖拿指甲刮了刮工件表面,“以前换刀按件数定,比如150件换,可实际跟材料批次、切深、转速都有关,刀尖磨钝是慢慢爬的,粗糙度也是跟着爬的,等发现就超差了。”

我接上导出的刀补日志、工序参数、每件的表面粗糙度抽检表。

“这里面有啥?”我问。

“粗加工刀轨、精加工进给F、主轴转速S、每件的Ra实测、刀具半径补偿值都有,”老肖说,“但系统只给单件结果,不模拟‘刀尖后刀面磨损VB怎么随件数爬’‘磨损怎么映射到残留高度’‘Ra怎么逐步劣化’。想换种材料,又得跑一炉看趋势。”

“最亏的是中段,”老肖补一句,“50到100件之间,Ra从0.8爬到1.2,还没超差,质检按批检就漏了,到120件直接报废几件。排产还按150件换刀,等于拿超差换产能。”

“我就想干一件事,”老肖说,“给粗精工序参数+刀具初始状态,模拟VB磨损逐件累积,反推残留高度,算出每件Ra曲线,标出从哪件开始进临界区、哪件必须换刀,像个小刀具寿命仿真器,不用跑一炉。”

“数控不是看程序跑没跑,”我接话,“是看‘刀尖每走一件磨掉多少、残留高度怎么涨、Ra曲线怎么斜着爬’。用 numpy 做磨损递推,pandas 管工序件表,scipy 算残留高度与Ra映射,matplotlib 画磨损-Ra双轴曲线+刀纹云图,networkx 建工序-刀具-粗糙度关联,sklearn 做超差预警分类。”

“对,”老肖点头,“要能说清‘第1件VB=0.02mm Ra0.78,第82件VB=0.12mm Ra1.21进临界,第118件VB=0.18mm Ra1.62超差,建议第110件换刀;主因是精加工进给+VB耦合’。”

“OOP 封好,”我开工程,“工序加载器、刀具磨损模型、残留高度映射、粗糙度递推器、超差分类器、可视化器,合成多批次多材料数据,下载就能跑。”

敲了行原型:

# 目标: 粗精工序 → 刀具VB磨损递推 → 残留高度 → Ra逐件劣化

# 方法: 磨损累积模型 + 几何残留高度 + RF超差分类 + 关联图

老肖凑近看:“那以后看报告:VB磨损曲线+Ra双轴,残留高度随件数变化,刀纹热力图,工序-刀具-粗糙度网络,超差预测散点。新批次上机前先跑,黄线就是换刀点。”

“对,”我接话,“数控仿真不是‘画个刀轨’,是‘提前看见刀尖哪件开始钝、表面哪件开始毛’。数字孪生里挂这个刀具看板,就是操作工的‘换刀闹钟’。”

一、实际应用场景(真实痛点)

场景设定:数控车/铣精加工轴套类零件,粗加工去量、精加工保表面质量。刀具后刀面磨损 VB 随加工件数逐步累积,残留高度随之增大,Ra 从 0.8μm 逐步爬到超差。现场按固定件数换刀,未耦合磨损-粗糙度动态关系,中段劣化被批检漏掉。

现场原话(叙事化):

“不是程序编错了,”老肖说,“是刀尖钝得悄无声息。前50件手摸都滑,到80件看着就发雾,三坐标一量Ra1.3,批检还按10件抽1件,正好抽到的都还行。”

“最亏的是换刀策略,”老肖说,“定死150件换,可这批料硬点,110件就超了,后面8件全废。等于用超差换那40件的产能。”

核心矛盾:“固定件数换刀+单件Ra抽检” 与 “VB磨损递推+残留高度映射+Ra逐件曲线+超差预警+关联图” 之间的断层。

二、痛点分析(映射到滨州职业学院《先进制造技术》课程模型)

《先进制造技术》课程模块 本篇痛点对应

数控加工与CAD/CAM技术:粗精加工、刀具磨损、切削参数、表面粗糙度、残留高度 VB递推+Ra劣化+换刀点

先进制造技术基础:几何精度、表面质量评价、材料去除机理 残留高度→Ra映射

FMS与先进生产管理:刀具寿命管理、换刀策略、在制品质量追踪 动态换刀点+质量追踪

智能制造与数字孪生:刀具状态数字映射、粗糙度看板 磨损/ Ra挂孪生

先进制造新模式:工艺知识库(材料-参数-刀具寿命库) 磨损模型复用

一句话总结:我们需要一个“粗精工序参数→刀具VB磨损递推→残留高度→Ra逐件曲线→超差预警+关联图”程序,实现从“固定件数换刀”到“按磨损状态动态换刀”的闭环。

三、核心逻辑讲解(大白话)

3.1 问题本质:把刀尖想成“慢慢变圆的铅笔头”

把精加工刀尖想成削铅笔的刀,刚磨完是尖的,削出来的面光;用久了变圆,削出来的面就有一道道棱:

* VB磨损 = 刀尖后刀面磨掉的宽度,单位mm,从0.02慢慢爬到0.2

* 残留高度 = 刀尖是圆弧,走刀后工件表面留下的微小波峰,刀尖越钝波峰越高

* Ra = 这些波峰波谷平均出来的粗糙度值

* 粗加工 = 先挖掉大部分料,不管光洁度

* 精加工 = 吃刀浅、走刀密,靠刀尖圆弧保光洁度

* 固定换刀 = 数件数,不管刀钝没钝

* 动态仿真 = 每加工一件,VB加一点,残留高度算一次,Ra跟一次,画成曲线

3.2 业务逻辑 → 代码映射

输入工序参数+刀具初始状态

│

▼ ProcessParamLoader (pandas)

读取表:

件号, 工序(粗/精), 主轴转速S, 进给F, 切深ap,

刀尖圆弧半径re, 材料硬度, 初始VB

│

▼ ToolWearModel (numpy)

VB磨损递推:

ΔVB_i = k * (ap*F/S) * 材料系数 * (1+已磨损放大项)

VB_i = VB_{i-1} + ΔVB_i

粗加工磨损权重高, 精加工慢但敏感

│

▼ ResidualHeightModel (scipy + numpy)

残留高度:

h = f(F, re, VB) 刀尖变钝→等效re增大

理论: h ≈ F²/(8*(re+VB))

│

▼ RoughnessPropagator (numpy + scipy)

Ra递推:

Ra ≈ C * h^0.8 + 刀具振动项

逐件输出Ra序列

分级: 优(Ra≤0.8) / 良(≤1.6) / 临界(1.2~1.6) / 超差(>1.6)

│

▼ OverLimitClassifier (sklearn)

超差预警:

特征: VB, Ra, 件号, 材料硬度, F, ap

标签: 安全/临界/超差

RF三分类 + 5折宏F1

预测“还有几件到超差”

│

▼ CncVisualizer (matplotlib + networkx)

可视化:

1. VB磨损+Ra双Y轴曲线(标换刀线)

2. 残留高度随件数曲线

3. 刀纹表面热力图(模拟不同VB下刀纹)

4. 工序-刀具-粗糙度关联网络

5. 超差预测vs实际散点

6. 单件Ra分布箱线(分段)

│

▼ SyntheticCncBatch (numpy)

合成数据:

多批次×多材料, 机制: 硬料VB爬得快, F大残留高, VB耦合放大

3.3 为什么不能“固定件数换刀”

视角 问题

按件数换刀 漏掉材料硬度差异

单件Ra抽检 中段劣化被平均掉

看程序参数 看不到刀尖变圆

VB递推 每件磨多少都算

残留高度 刀钝→波峰涨可量化

Ra曲线 斜爬过程全看见

RF预警 提前报“还有N件超差”

3.4 分析前后对比

维度 传统方式 本程序

换刀依据 150件固定 VB=0.18动态换刀(第110件)

劣化发现 超差后返工 第82件进临界即预警

中段质量 批检漏掉 逐件Ra曲线可见

主因分析 凭经验 VB+进给耦合量化

知识沉淀 老师傅记忆 材料-参数-寿命库

四、OOP 代码实现

4.1 项目结构

cnc_wear_roughness/

├── cnc_wear_roughness/

│ ├── __init__.py

│ ├── process_param_loader.py # 工序参数加载

│ ├── tool_wear_model.py # VB磨损递推(numpy)

│ ├── residual_height_model.py # 残留高度(scipy)

│ ├── roughness_propagator.py # Ra递推

│ ├── over_limit_classifier.py # 超差分类(sklearn)

│ ├── cnc_visualizer.py # 可视化

│ └── synthetic_cnc_batch.py # 合成批次

├── tests/

│ ├── __init__.py

│ └── test_cnc.py

├── results/

│ ├── wear_ra_curve.png

│ ├── residual_height_curve.png

│ ├── tool_mark_heatmap.png

│ ├── process_tool_network.png

│ ├── overrun_pred_scatter.png

│ ├── ra_boxplot_stage.png

│ ├── cnc_detail.csv

│ └── cnc_report.txt

└── run_cnc.py

4.2 核心源码

<details>

<summary></summary>

"""数控工序参数加载器。"""

import pandas as pd

from pathlib import Path

class ProcessParamLoader:

"""加载粗精工序参数与刀具初始状态。"""

def __init__(self, filepath: str = "cnc_process.csv",

encoding: str = "utf-8"):

self.filepath = Path(filepath)

self.encoding = encoding

def load(self) -> pd.DataFrame:

if not self.filepath.exists():

raise FileNotFoundError(self.filepath)

df = pd.read_csv(self.filepath, encoding=self.encoding)

req = ["part_no", "op", "spindle_s", "feed_f", "ap",

"tool_re", "material_hb", "vb_init"]

miss = [c for c in req if c not in df.columns]

if miss:

raise ValueError(f"缺列: {miss}")

for c in req[1:]:

df[c] = pd.to_numeric(df[c], errors="coerce")

return df.dropna(subset=req).reset_index(drop=True)

def summary(self, df: pd.DataFrame) -> str:

s = f"计划件数: {len(df)}\n"

s += f"精加工转速S: {df[df.op=='finish']['spindle_s'].iloc[0]}rpm\n"

s += f"精加工进给F: {df[df.op=='finish']['feed_f'].iloc[0]}mm/r\n"

s += f"刀尖圆弧re: {df['tool_re'].iloc[0]}mm\n"

s += f"材料硬度: {df['material_hb'].iloc[0]}HB\n"

s += f"初始VB: {df['vb_init'].iloc[0]}mm"

return s.rstrip()

</details>

<details>

<summary></summary>

"""刀具后刀面磨损VB递推 (numpy)。"""

import numpy as np

from dataclasses import dataclass

@dataclass

class WearResult:

vb: np.ndarray

dvb: np.ndarray

class ToolWearModel:

"""

VB累积模型(教学级):

ΔVB = k * (ap*F/S) * 材料系数 * (1+0.5*VB/VB_ref)

粗加工权重1.0, 精加工权重0.35(吃刀浅但敏感)

已磨损刀具摩擦加剧, 磨损加速(自放大)

"""

def __init__(self, k: float = 1.2e-4, vb_ref: float = 0.2):

self.k = k

self.vb_ref = vb_ref

def simulate(self, n_parts: int, op: np.ndarray,

s: float, f: float, ap: np.ndarray,

material_hb: float, vb_init: float) -> WearResult:

vb = np.zeros(n_parts)

dvb = np.zeros(n_parts)

mat_coef = 0.6 + material_hb / 200.0 # 硬料磨损快

for i in range(n_parts):

w = 1.0 if op[i] == "rough" else 0.35

base = self.k * (ap[i] * f / max(s, 1)) * mat_coef * w

amp = 1.0 + 0.5 * (vb[i-1] / self.vb_ref if i > 0 else 0.0)

d = base * amp

if i == 0:

vb[i] = vb_init + d

else:

vb[i] = vb[i-1] + d

dvb[i] = d

return WearResult(vb, dvb)

</details>

<details>

<summary></summary>

"""残留高度模型 (scipy + numpy)。"""

import numpy as np

from dataclasses import dataclass

@dataclass

class ResidualResult:

h_res: np.ndarray

class ResidualHeightModel:

"""

刀尖圆弧+磨损等效放大:

re_eff = re + VB (刀钝等效圆弧变大)

h = F^2 / (8 * re_eff) (几何残留高度)

"""

def __init__(self):

pass

def compute(self, f: float, re: float,

vb: np.ndarray) -> ResidualResult:

re_eff = re + vb

h = (f ** 2) / (8.0 * re_eff)

return ResidualResult(h)

</details>

<details>

<summary></summary>

"""Ra粗糙度递推 (numpy + scipy)。"""

import numpy as np

from dataclasses import dataclass

from scipy.ndimage import gaussian_filter1d

@dataclass

class RoughnessResult:

ra: np.ndarray

grade: np.ndarray

class RoughnessPropagator:

"""

Ra ≈ C * h^0.8 + 微振动项

分级:

excellent: Ra<=0.8

good: <=1.6

critical: 1.2~1.6

overrun: >1.6

"""

def __init__(self, c: float = 0.9, vib: float = 0.05):

self.c = c

self.vib = vib

def propagate(self, h_res: np.ndarray,

n_parts: int) -> RoughnessResult:

ra = self.c * (h_res ** 0.8) * 1000.0 + self.vib * np.arange(n_parts)/n_parts

ra = gaussian_filter1d(ra, sigma=1.0) # 平滑工艺噪声

grade = np.array([self._grade(r) for r in ra])

return RoughnessResult(ra, grade)

def _grade(self, r: float) -> str:

if r <= 0.8:

return "excellent"

if r <= 1.2:

return "good"

if r <= 1.6:

return "critical"

return "overrun"

</details>

<details>

<summary></summary>

"""超差预警分类 (sklearn RF)。"""

import numpy as np

import pandas as pd

from typing import Dict

from sklearn.ensemble import RandomForestClassifier

from sklearn.model_selection import cross_val_score, KFold

class OverLimitClassifier:

"""安全/临界/超差 三分类 + 剩余件数预测。"""

def __init__(self, random_state: int = 42):

self.random_state = random_state

self.model_ = None

self.feat = ["vb", "ra", "part_idx", "material_hb", "feed_f", "ap"]

def fit(self, df: pd.DataFrame, y: np.ndarray):

self.model_ = RandomForestClassifier(

n_estimators=300, max_depth=6, min_samples_leaf=2,

random_state=self.random_state, n_jobs=-1)

self.model_.fit(df[self.feat].values, y)

return self

def feature_importance(self) -> Dict:

imp = dict(zip(self.feat, self.model_.feature_importances_))

return dict(sorted(imp.items(), key=lambda x: x[1], reverse=True))

def cross_validate(self, df: pd.DataFrame, y: np.ndarray) -> Dict:

kf = KFold(n_splits=5, shuffle=True, random_state=self.random_state)

sc = cross_val_score(self.model_, df[self.feat].values, y,

cv=kf, scoring="f1_macro")

return {"f1_macro_mean": float(sc.mean()), "f1_macro_std": float(sc.std())}

def predict(self, df: pd.DataFrame) -> np.ndarray:

return self.model_.predict(df[self.feat].values)

</details>

<details>

<summary></summary>

"""数控可视化 (matplotlib + networkx)。"""

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from pathlib import Path

import networkx as nx

plt.rcParams["font.sans-serif"] = ["SimHei", "WenQuanYi Micro Hei", "DejaVu Sans"]

plt.rcParams["axes.unicode_minus"] = False

GRADE_COLOR = {"excellent":"#27AE60","good":"#2ECC71",

"critical":"#F39C12","overrun":"#E74C3C"}

class CncVisualizer:

def __init__(self, results_dir: str = "results"):

self.results_dir = Path(results_dir)

self.results_dir.mkdir(exist_ok=True)

def wear_ra_curve(self, idx, vb, ra, change_point, overrun_point):

fig, ax1 = plt.subplots(figsize=(12, 6))

ax1.plot(idx, vb*1000, color="#2C3E50", lw=1.8, label="VB磨损(μm)")

ax1.set_xlabel("加工件数", fontsize=12)

ax1.set_ylabel("VB磨损 (μm)", color="#2C3E50", fontsize=12)

ax2 = ax1.twinx()

for i, g in enumerate(["excellent","good","critical","overrun"]):

m = ra == g

if m.any():

ax2.scatter(idx[m], ra[m], c=GRADE_COLOR[g], s=18,

label=f"Ra-{g}", zorder=5)

ax2.set_ylabel("Ra (μm)", color="#E67E22", fontsize=12)

ax1.axvline(change_point, color="#F39C12", ls="--", lw=2,

label=f"临界点#{change_point}")

ax1.axvline(overrun_point, color="#E74C3C", ls="--", lw=2,

label=f"超差点#{overrun_point}")

ax1.set_title("刀具VB磨损 + Ra粗糙度双轴曲线",

fontsize=13, fontweight="bold")

ax1.grid(alpha=0.25)

lines1, labels1 = ax1.get_legend_handles_labels()

lines2, labels2 = ax2.get_legend_handles_labels()

ax1.legend(lines1+lines2, labels1+labels2, fontsize=8,

loc="upper left", ncol=2)

plt.tight_layout()

plt.savefig(self.results_dir/"wear_ra_curve.png",

dpi=150, bbox_inches="tight")

plt.close()

def residual_curve(self, idx, h_res):

fig, ax = plt.subplots(figsize=(11, 5))

ax.plot(idx, h_res*1000, color="#8E44AD", lw=1.8)

ax.fill_between(idx, 0, h_res*1000, color="#8E44AD", alpha=0.1)

ax.set_xlabel("加工件数", fontsize=12)

ax.set_ylabel("残留高度 (μm)", fontsize=12)

ax.set_title("残留高度随件数变化(刀钝→波峰涨)",

fontsize=13, fontweight="bold")

ax.grid(alpha=0.3)

plt.tight_layout()

plt.savefig(self.results_dir/"residual_height_curve.png",

dpi=150, bbox_inches="tight")

plt.close()

def tool_mark_heatmap(self, vb_end, re, f, n_grid=80):

fig, ax = plt.subplots(figsize=(9, 5))

# 模拟刀纹: 横向走刀, 纵向波峰随VB

x = np.linspace(0, 5, n_grid)

y = np.linspace(0, 1, 20)

X, Y = np.meshgrid(x, y)

re_eff = re + vb_end

wave = (f**2)/(8*re_eff)*1000 * np.sin(2*np.pi*X/0.05)**2

im = ax.imshow(wave, aspect="auto", cmap="copper",

extent=[0,5,0,1], origin="lower")

ax.set_xlabel("工件周向展开 (mm)", fontsize=12)

ax.set_ylabel("轴向 (mm)", fontsize=12)

ax.set_title(f"刀纹表面形貌(VB={vb_end*1000:.0f}μm时)",

fontsize=13, fontweight="bold")

plt.colorbar(im, ax=ax, label="高度(μm)")

plt.tight_layout()

plt.savefig(self.results_dir/"tool_mark_heatmap.png",

dpi=150, bbox_inches="tight")

plt.close()

def process_network(self, imp: Dict):

fig, ax = plt.subplots(figsize=(11, 8))

G = nx.DiGraph()

G.add_node("Ra超差", kind="target")

for n in ["VB磨损","残留高度","进给F","切深ap","材料硬度","件号"]:

G.add_node(n, kind="factor")

key_map = {"vb":"VB磨损","ra":"Ra超差","feed_f":"进给F","ap":"切深ap",

"material_hb":"材料硬度","part_idx":"件号",

"h_res":"残留高度"}

for k,v in imp.items():

if k in ("vb","ra"):

continue

G.add_edge(key_map.get(k,k), "Ra超差", weight=v)

G.add_edge("VB磨损","残留高度", weight=0.9)

G.add_edge("残留高度","Ra超差", weight=0.9)

G.add_edge("进给F","残留高度", weight=0.5)

pos = nx.spring_layout(G, seed=42)

cmap = ["#E74C3C" if n=="Ra超差" else "#3498DB" for n in G.nodes()]

nx.draw_networkx_nodes(G,pos,node_color=cmap,node_size=3200,

alpha=0.9,ax=ax)

nx.draw_networkx_edges(G,pos,arrowstyle="-|>",arrowsize=20,

edge_color="#555",width=2,ax=ax)

nx.draw_networkx_labels(G,pos,font_size=11,ax=ax,

font_color="white",font_weight="bold")

ax.set_title("工序-刀具-粗糙度关联网络", fontsize=14, fontweight="bold")

ax.axis("off")

plt.tight_layout()

plt.savefig(self.results_dir/"process_tool_network.png",

dpi=150, bbox_inches="tight")

plt.close()

def pred_scatter(self, y_true, y_pred):

fig, ax = plt.subplots(figsize=(8, 8))

labels = ["安全","临界","超差"]

ct = np.array([labels.index(y) for y in y_true])

cp = np.array([labels.index(y) for y in y_pred])

ax.scatter(ct, cp, c="#27AE60", s=60, edgecolors="k", alpha=0.8)

ax.plot([-0.5,2.5],[-0.5,2.5],"r--",lw=2,label="理想")

ax.set_xticks([0,1,2]); ax.set_xticklabels(labels)

ax.set_yticks([0,1,2]); ax.set_yticklabels(labels)

ax.set_xlabel("实际状态", fontsize=12)

ax.set_ylabel("预测状态", fontsize=12)

ax.set_title("超差预警 预测vs实际", fontsize=13, fontweight="bold")

ax.legend(fontsize=10); ax.grid(alpha=0.3)

plt.tight_layout()

plt.savefig(self.results_dir/"overrun_pred_scatter.png",

dpi=150, bbox_inches="tight")

plt.close()

def ra_boxplot(self, idx, ra, stages):

fig, ax = plt.subplots(figsize=(10, 6))

data = [ra[(idx>=s[0])&(idx<=s[1])] for s in stages]

labels = [f"{s[0]}-{s[1]}件" for s in stages]

bp = ax.boxplot(data, labels=labels, patch_artist=True)

for patch, g in zip(bp["boxes"], ["excellent","good","critical","overrun"]):

patch.set_facecolor(GRADE_COLOR[g]); patch.set_alpha(0.7)

ax.set_ylabel("Ra (μm)", fontsize=12)

ax.set_xlabel("加工阶段", fontsize=12)

ax.set_title("分段Ra分布箱线图", fontsize=13, fontweight="bold")

ax.grid(alpha=0.25)

plt.tight_layout()

plt.savefig(self.results_dir/"ra_boxplot_stage.png",

dpi=150, bbox_inches="tight")

plt.close()

</details>

<details>

<summary></summary>

"""合成数控加工批次数据。"""

import numpy as np

import pandas as pd

from pathlib import Path

from typing import Optional

class SyntheticCncBatch:

"""

多批次×多材料

机制:

硬料VB爬得快

精加工F大→残留高

VB自放大

"""

def __init__(self, rng: Optional[np.random.RandomState] = None):

self.rng = rng or np.random.RandomState(42)

def generate(self, out_path: str = "cnc_process.csv",

n_parts: int = 130,

material_hb: float = 180.0,

feed_f: float = 0.08,

spindle_s: float = 3000.0,

tool_re: float = 0.4,

vb_init: float = 0.02) -> pd.DataFrame:

rows = []

for i in range(n_parts):

# 前5件粗加工, 其余精加工

op = "rough" if i < 5 else "finish"

ap = 0.8 if op == "rough" else 0.1

rows.append({

"part_no": f"P{i+1:03d}",

"op": op,

"spindle_s": spindle_s,

"feed_f": feed_f,

"ap": ap,

"tool_re": tool_re,

"material_hb": material_hb,

"vb_init": vb_init,

})

df = pd.DataFrame(rows)

Path(out_path).parent.mkdir(parents=True, exist_ok=True)

df.to_csv(out_path, index=False, encoding="utf-8")

return df

</details>

<details>

<summary></summary>

"""

数控粗精工序仿真: 刀具磨损累积 → 残留高度 → Ra逐步劣化

================================================================================

课程映射(滨州职业学院《先进制造技术》):

数控加工与CAD/CAM:粗精加工/刀具磨损/残留高度/表面粗糙度

先进制造技术基础:几何精度/表面质量评价

FMS与先进生产管理:刀具寿命管理/动态换刀

智能制造与数字孪生:刀具状态看板

先进制造新模式:材料-参数-寿命知识库

技术栈(严格):

pandas / numpy # 工序表/磨损递推

scipy # 平滑/几何处理

scikit-learn # RF超差分类

matplotlib / networkx# 双轴曲线+关联图

"""

import sys, os

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

import numpy as np

import pandas as pd

from pathlib import Path

from cnc_wear_roughness.process_param_loader import ProcessParamLoader

from cnc_wear_roughness.tool_wear_model import ToolWearModel

from cnc_wear_roughness.residual_height_model import ResidualHeightModel

from cnc_wear_roughness.roughness_propagator import RoughnessPropagator

from cnc_wear_roughness.over_limit_classifier import OverLimitClassifier

from cnc_wear_roughness.cnc_visualizer import CncVisualizer

from cnc_wear_roughness.synthetic_cnc_batch import SyntheticCncBatch

def main():

print("=" * 70)

print("数控粗精工序仿真: 刀具磨损→残留高度→Ra逐步劣化")

print("=" * 70)

results_dir = Path("results"); results_dir.mkdir(exist_ok=True)

# 1. 合成

print("\n[1/8] 生成工序批次...")

gen = SyntheticCncBatch(rng=np.random.RandomState(42))

df = gen.generate("cnc_process.csv", n_parts=130,

material_hb=185.0, feed_f=0.08,

spindle_s=3000.0, tool_re=0.4, vb_init=0.02)

print(f" 130件, 前5件粗加工, 材料185HB, 精加工F=0.08mm/r")

# 2. 加载

print("\n[2/8] 加载工序参数...")

df = ProcessParamLoader("cnc_process.csv").load()

print(ProcessParamLoader().summary(df))

n = len(df)

op = df["op"].values

s = df["spindle_s"].iloc[0]

f = df["feed_f"].iloc[0]

ap = df["ap"].values

re = df["tool_re"].iloc[0]

hb = df["material_hb"].iloc[0]

vb0 = df["vb_init"].iloc[0]

idx = np.arange(1, n+1)

# 3. VB磨损递推

print("\n[3/8] 刀具VB磨损递推...")

wear = ToolWearModel(k=1.2e-4, vb_ref=0.2).simulate(

n, op, s, f, ap, hb, vb0)

print(f" 首件VB={wear.vb[0]*1000:.1f}μm, "

f"末件VB={wear.vb[-1]*1000:.1f}μm")

# 4. 残留高度

print("\n[4/8] 残留高度计算...")

res = ResidualHeightModel().compute(f, re, wear.vb)

print(f" 首件残留高度={res.h_res[0]*1000:.3f}μm, "

f"末件={res.h_res[-1]*1000:.3f}μm")

# 5. Ra递推

print("\n[5/8] Ra粗糙度递推...")

rp = RoughnessPropagator(c=0.9, vib=0.05)

rr = rp.propagate(res.h_res, n)

ra = rr.ra

# 定位关键点

critical_idx = int(np.argmax(ra > 1.2)) + 1

overrun_idx = int(np.argmax(ra > 1.6)) + 1

# 建议换刀

利用AI解决实际问题,如果你觉得这个工具好用,欢迎关注长安牧笛!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询