python的先进制造技术工业场景模拟第四十九篇:导入机器人工作站工件来料尺寸数据,分析来料尺寸波动对定位误差的影响。
周五上午,机器人上下料工作站。
"这批毛坯又出问题了,"质检员小吴拿着卡尺,皱着眉,"来料尺寸标称 Φ50±0.05mm,实际我抽了 20 件,最大 Φ50.12,最小 Φ49.83,波动快到 0.3mm 了。机器人抓手按标称值算抓取中心,结果大件抓偏、小件夹不紧,定位误差直接飙到 0.4mm 以上,后面 CNC 加工余量不够,报废了 3 个。"
我接上他导出的来料尺寸测量表。
"这表里有什么?"小吴问。
"每批来料的实测外径、内径、高度,还有对应的机器人抓取后实测定位误差,"我指着屏幕,"但它就是两张表——一张来料尺寸,一张定位误差。你隐约觉得'来料大了就抓偏',但说不清到底是哪个尺寸维度影响最大、影响多少。现在调机器人抓取参数只能凭经验试,试一次撞一次。"
"我就想干一件事,"小吴说,"把来料尺寸波动和定位误差关联起来。算清楚:外径每大 0.1mm,定位误差增加多少?内径波动和高度的耦合效应呢?给我一个灵敏度排名,告诉我'以后来料检验重点卡哪个尺寸'。"
"比如外径波动贡献了 60% 的定位误差,内径只贡献 15%,"我接话,"用 pandas 做数据关联,numpy 算协方差矩阵,scipy 做多元线性回归+偏相关系数,scikit-learn 做随机森林特征重要性验证,matplotlib 画散点矩阵+残差图+灵敏度柱状图+误差传播蒙特卡洛模拟。networkx 把'尺寸维度→误差分量'当因果链路图。"
"对,"小吴点头,"别给我黑盒,要能说清楚是'外径超差 0.1mm 直接导致 X 方向偏 0.08mm'还是'高度波动通过夹具间隙放大了旋转误差'。我看得懂,能拿去跟采购说'外径公差必须收紧到 ±0.03mm,别的可以放宽'。"
"用 pandas 读来料+误差数据,scipy 做回归+相关性,matplotlib 出 6 图+报告,存 results/,"我开工程,"数据自包含,合成一批含外径/内径/高度三维波动、故意让外径主导定位误差的数据,下载就能跑。"
敲了行原型:
# 定位误差 = f(外径波动, 内径波动, 高度波动) + 随机噪声
# 灵敏度: ∂误差/∂外径, ∂误差/∂内径, ∂误差/∂高度
# 蒙特卡洛: 尺寸按分布采样 → 误差传播 → P95 误差
"完整版 OOP 封好,"我说,"数据加载器、尺寸分析器、回归建模器、灵敏度分析器、误差传播模拟器、可视化器,输出灵敏度排名+回归系数+蒙特卡洛P95+6图+报告。"
小吴凑近看:"那以后看报告:外径灵敏度 0.72 排第一,内径 0.18 排第二,高度 0.10 排第三;回归 R²=0.89;蒙特卡洛 P95 误差 0.38mm。结论:来料外径公差收紧到 ±0.03mm,内径和高度可以放宽到 ±0.08mm。"
"对,"我接话,"机器人不是'抓到就行',是'来料波动决定了你能抓多准'。数字孪生里挂来料质量节点,这套就是机器人工作站的'公差分配大脑'。"
一、实际应用场景(真实痛点)
场景设定:机器人上下料工作站,负责将毛坯件从料框抓取放置到 CNC 夹具上。来料由外协供应商提供,尺寸存在批次波动。机器人视觉/机械定位依赖来料标称尺寸计算抓取位姿。当来料尺寸偏离标称值时,定位误差增大,导致后续加工余量不足或夹具干涉。
现场原话(叙事化):
"不是我们机器人不准,"小吴说,"是来料尺寸飘了,机器人按标称值算抓取点,实际毛坯大一圈或者小一截,抓手中心就偏了。偏了之后放夹具里歪的,CNC 铣出来一面余量不够直接报废。上个月报废了 7 个,全是这个原因。"
"最坑的是供应商,"小吴补充,"他们每批都出检验报告,写着'符合 ±0.05mm 公差',但你仔细看,外径在上限 +0.04,内径在下限 -0.04,高度又在上限 +0.03——三个维度叠加起来,机器人端的综合定位误差远超 0.05mm。我们跟供应商扯皮,人家说'每个尺寸都在公差内啊'。我们需要的是:量化每个尺寸维度对定位误差的贡献权重,拿着数据去谈——哪个尺寸必须收紧,哪个可以放宽。"
核心矛盾:"来料抽检 + 经验调参" 与 "尺寸波动→定位误差映射 + 灵敏度量化 + 公差分配建议 + 蒙特卡洛误差传播" 之间的断层。
二、痛点分析(映射到滨州职业学院《先进制造技术》课程模型)
《先进制造技术》模块 本篇痛点对应
工业机器人技术基础:末端定位精度、误差来源 来料尺寸→定位误差映射
先进制造技术基础:公差配合、互换性 尺寸波动对装配/加工的影响
数控加工与CAD/CAM技术:加工余量保障 定位误差→余量不足报废
智能制造与数字孪生:质量数据驱动 来料质量→机器人精度数字孪生
先进制造新模式:供应链质量协同 数据驱动公差分配
一句话总结:我们需要一个"来料尺寸数据+定位误差记录→回归建模+灵敏度分析+蒙特卡洛误差传播+公差分配建议程序",用
"pandas" 读尺寸/误差表,
"numpy" 算协方差/灵敏度,
"scipy" 做多元回归+偏相关,
"scikit-learn" 做随机森林特征重要性验证,
"matplotlib" 画散点矩阵/残差/灵敏度/蒙特卡洛,
"networkx" 建尺寸→误差因果链路,实现从"凭经验调机器人"到"量化尺寸影响+公差分配+来料检验标准优化"。
三、核心逻辑讲解(大白话)
3.1 问题本质:把来料波动想成"多米诺骨牌"
把机器人抓取定位想成多米诺骨牌链:
* 来料尺寸 = 第一张牌(外径、内径、高度)
* 抓取偏移 = 第二张牌(抓手按标称算,实际偏了)
* 定位误差 = 最后倒下的牌(放歪了,加工报废)
* 灵敏度 = 推第一张牌时,最后一张倒多远
* 回归 = 算"外径每变 0.1mm,定位误差变多少"
* 蒙特卡洛 = 把尺寸波动当骰子摇 10000 次,看误差分布
* 因果链路 = 外径→抓取中心偏移→X方向定位误差
3.2 业务逻辑 → 代码映射
导入来料尺寸 + 定位误差数据
│
▼ IncomingDataLoader (pandas)
读取两张表:
来料: 批次, 工件ID, 外径, 内径, 高度, 标称值
误差: 工件ID, X误差, Y误差, Z误差, 旋转误差
合并: 按工件ID
│
▼ DimensionAnalyzer (numpy)
尺寸统计:
各维度: 均值, 标准差, Cp/Cpk
与标称值偏差分布
│
▼ RegressionModeler (scipy + sklearn)
回归建模:
多元线性回归: 误差 = β₀ + β₁×外径偏差 + β₂×内径偏差 + β₃×高度偏差
偏相关系数(控制其他变量后的净相关)
随机森林特征重要性(非线性验证)
│
▼ SensitivityAnalyzer (numpy)
灵敏度:
∂误差/∂各尺寸 = 回归系数标准化
贡献率 = |βᵢ×σᵢ| / Σ|βⱼ×σⱼ|
│
▼ MonteCarloPropagator (numpy)
误差传播:
尺寸按正态分布采样(均值, 标准差)
代入回归模型 → 误差分布
P95 = 95%分位数
│
▼ CausalGraph (networkx)
因果链路:
节点: 尺寸维度, 误差分量
边: 影响方向+权重
│
▼ IncomingVisualizer (matplotlib)
可视化:
1. 散点矩阵(尺寸 vs 各方向误差)
2. 回归残差图
3. 灵敏度排名柱状图
4. 蒙特卡洛误差分布直方图
5. 尺寸波动热力图(各批次)
6. 因果链路图(networkx)
│
▼ SyntheticIncomingData (numpy)
合成数据:
外径主导(β=0.7), 内径次之(β=0.2), 高度弱(β=0.1)
可复现
3.3 为什么不能只看"尺寸超不超差"
视角 问题
看公差范围 每个尺寸单独合格,叠加后可能超差
看报废率 事后统计,不知道根因
回归+灵敏度 量化"哪个尺寸影响最大"
蒙特卡洛 预测"来料波动下误差分布"
因果链路 解释"为什么外径影响大"
3.4 分析前后对比
维度 经验调参 本程序
尺寸影响 凭感觉 回归系数+灵敏度排名
公差建议 全部收紧(成本高) 重点收紧主导尺寸
误差预测 无 蒙特卡洛 P95
供应商沟通 "你们质量不行" "外径必须 ±0.03"
输出 口头 6图+报告+公差建议
四、OOP 代码实现
4.1 项目结构
incoming_variance_analysis/
├── incoming_variance_analysis/
│ ├── __init__.py
│ ├── incoming_data_loader.py # 来料+误差数据加载
│ ├── dimension_analyzer.py # 尺寸统计(numpy)
│ ├── regression_modeler.py # 回归+偏相关(scipy+sklearn)
│ ├── sensitivity_analyzer.py # 灵敏度分析(numpy)
│ ├── monte_carlo_propagator.py # 蒙特卡洛误差传播
│ ├── causal_graph.py # 因果链路(networkx)
│ ├── visualizer.py # 可视化
│ └── synthetic_incoming_data.py # 合成数据
├── tests/
│ ├── __init__.py
│ └── test_incoming.py
├── results/
│ ├── scatter_matrix.png
│ ├── residual_plot.png
│ ├── sensitivity_rank.png
│ ├── monte_carlo_dist.png
│ ├── batch_heatmap.png
│ ├── causal_network.png
│ ├── sensitivity_table.csv
│ ├── regression_report.txt
│ ├── monte_carlo_stats.csv
│ └ tolerance_recommendation.txt
└── run_incoming.py
4.2 核心源码
<details>
<summary></summary>
"""来料尺寸+定位误差数据加载器"""
import pandas as pd
from pathlib import Path
from typing import Optional
class IncomingDataLoader:
"""读取来料尺寸和定位误差数据"""
def __init__(self, incoming_path: str = "incoming_dimensions.csv",
error_path: str = "positioning_errors.csv",
encoding: str = "utf-8"):
self.incoming_path = Path(incoming_path)
self.error_path = Path(error_path)
self.encoding = encoding
def load(self) -> pd.DataFrame:
if not self.incoming_path.exists():
raise FileNotFoundError(self.incoming_path)
if not self.error_path.exists():
raise FileNotFoundError(self.error_path)
inc = pd.read_csv(self.incoming_path, encoding=self.encoding)
err = pd.read_csv(self.error_path, encoding=self.encoding)
req_inc = ["part_id", "batch_id", "outer_dia", "inner_dia", "height"]
req_err = ["part_id", "error_x", "error_y", "error_z", "error_rot"]
for c in req_inc + req_err:
if c not in inc.columns and c not in err.columns:
raise ValueError(f"缺列: {c}")
inc[req_inc[1:]] = inc[req_inc[1:]].apply(pd.to_numeric, errors="coerce")
err[req_err] = err[req_err].apply(pd.to_numeric, errors="coerce")
df = pd.merge(inc, err, on="part_id", how="inner")
df = df.dropna(subset=req_inc[1:]+req_err[1:]).reset_index(drop=True)
# 计算综合误差
df["total_error"] = np.sqrt(df["error_x"]**2 + df["error_y"]**2 +
df["error_z"]**2 + df["error_rot"]**2)
# 计算与标称值偏差(假设标称外径50, 内径25, 高度30)
df["outer_dia_dev"] = df["outer_dia"] - 50.0
df["inner_dia_dev"] = df["inner_dia"] - 25.0
df["height_dev"] = df["height"] - 30.0
return df
</details>
<details>
<summary></summary>
"""尺寸统计分析 (numpy)"""
import numpy as np
import pandas as pd
from typing import Dict
class DimensionAnalyzer:
"""各尺寸维度统计"""
def __init__(self, nominal_outer: float = 50.0,
nominal_inner: float = 25.0,
nominal_height: float = 30.0):
self.nominals = {"outer_dia": nominal_outer,
"inner_dia": nominal_inner,
"height": nominal_height}
def compute(self, df: pd.DataFrame) -> pd.DataFrame:
dims = ["outer_dia", "inner_dia", "height"]
results = []
for dim in dims:
vals = df[dim].values
dev = vals - self.nominals[dim]
mean = np.mean(vals)
std = np.std(vals, ddof=1)
# Cp/Cpk
usl = self.nominals[dim] + 0.05
lsl = self.nominals[dim] - 0.05
if std > 0:
cp = (usl - lsl) / (6 * std)
cpu = (usl - mean) / (3 * std)
cpl = (mean - lsl) / (3 * std)
cpk = min(cpu, cpl)
else:
cp = cpk = np.inf
results.append({
"dimension": dim,
"mean": round(mean, 4),
"std": round(std, 4),
"min": round(np.min(vals), 4),
"max": round(np.max(vals), 4),
"range": round(np.max(vals)-np.min(vals), 4),
"cp": round(cp, 3),
"cpk": round(cpk, 3),
})
return pd.DataFrame(results)
</details>
<details>
<summary></summary>
"""回归建模+偏相关 (scipy + scikit-learn)"""
import numpy as np
import pandas as pd
from scipy import stats
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import r2_score
from typing import Dict
class RegressionModeler:
"""多元回归+特征重要性"""
def __init__(self):
self.lr = LinearRegression()
self.rf = RandomForestRegressor(n_estimators=100, random_state=42)
def fit(self, df: pd.DataFrame) -> Dict:
X = df[["outer_dia_dev", "inner_dia_dev", "height_dev"]].values
y = df["total_error"].values
# 线性回归
self.lr.fit(X, y)
y_pred_lr = self.lr.predict(X)
r2_lr = r2_score(y, y_pred_lr)
# 随机森林
self.rf.fit(X, y)
y_pred_rf = self.rf.predict(X)
r2_rf = r2_score(y, y_pred_rf)
# 偏相关系数
pcorr = {}
for i, dim in enumerate(["outer_dia_dev", "inner_dia_dev", "height_dev"]):
others = [d for d in ["outer_dia_dev", "inner_dia_dev", "height_dev"] if d != dim]
X_others = df[others].values
# 残差化
res_y = y - LinearRegression().fit(X_others, y).predict(X_others)
res_x = df[dim].values - LinearRegression().fit(X_others, df[dim]).predict(X_others)
pcorr[dim] = round(stats.pearsonr(res_x, res_y)[0], 4)
return {
"lr_coefficients": dict(zip(
["outer_dia_dev", "inner_dia_dev", "height_dev"],
[round(c,4) for c in self.lr.coef_])),
"lr_intercept": round(self.lr.intercept_, 4),
"lr_r2": round(r2_lr, 4),
"rf_r2": round(r2_rf, 4),
"partial_correlations": pcorr,
}
def predict(self, X: np.ndarray) -> np.ndarray:
return self.lr.predict(X)
</details>
<details>
<summary></summary>
"""灵敏度分析 (numpy)"""
import numpy as np
import pandas as pd
from typing import Dict, List
class SensitivityAnalyzer:
"""计算各尺寸维度对定位误差的灵敏度"""
def __init__(self):
pass
def compute(self, df: pd.DataFrame, reg_coeffs: Dict) -> pd.DataFrame:
dims = ["outer_dia_dev", "inner_dia_dev", "height_dev"]
names = ["外径偏差", "内径偏差", "高度偏差"]
results = []
total_effect = 0
effects = []
for dim in dims:
std_dim = df[dim].std()
effect = abs(reg_coeffs[dim]) * std_dim
effects.append(effect)
total_effect += effect
for i, (dim, name) in enumerate(zip(dims, names)):
std_dim = df[dim].std()
contribution = effects[i] / total_effect * 100 if total_effect > 0 else 0
results.append({
"dimension": name,
"reg_coefficient": reg_coeffs[dim],
"std": round(std_dim, 4),
"effect_size": round(effects[i], 4),
"contribution_pct": round(contribution, 1),
})
return pd.DataFrame(results).sort_values("contribution_pct",
ascending=False).reset_index(drop=True)
</details>
<details>
<summary></summary>
"""蒙特卡洛误差传播 (numpy)"""
import numpy as np
import pandas as pd
from typing import Dict, List
class MonteCarloPropagator:
"""尺寸波动→误差传播模拟"""
def __init__(self, n_sim: int = 10000, rng: np.random.RandomState = None):
self.n_sim = n_sim
self.rng = rng or np.random.RandomState(42)
def propagate(self, means: Dict, stds: Dict,
coeffs: Dict, intercept: float) -> Dict:
# 采样
outer_samples = self.rng.normal(means["outer_dia_dev"],
stds["outer_dia_dev"], self.n_sim)
inner_samples = self.rng.normal(means["inner_dia_dev"],
stds["inner_dia_dev"], self.n_sim)
height_samples = self.rng.normal(means["height_dev"],
stds["height_dev"], self.n_sim)
# 误差传播
errors = (intercept +
coeffs["outer_dia_dev"] * outer_samples +
coeffs["inner_dia_dev"] * inner_samples +
coeffs["height_dev"] * height_samples +
self.rng.normal(0, 0.02, self.n_sim)) # 噪声
errors = np.abs(errors)
return {
"mean_error": round(np.mean(errors), 4),
"std_error": round(np.std(errors), 4),
"p50": round(np.percentile(errors, 50), 4),
"p95": round(np.percentile(errors, 95), 4),
"p99": round(np.percentile(errors, 99), 4),
"max": round(np.max(errors), 4),
"samples": errors,
}
</details>
<details>
<summary></summary>
"""因果链路图 (networkx)"""
import networkx as nx
import pandas as pd
from typing import Dict, List
class CausalGraph:
"""尺寸维度→误差分量因果网络"""
def __init__(self):
self.G = nx.DiGraph()
def build(self, sensitivity_df: pd.DataFrame,
reg_coeffs: Dict) -> nx.DiGraph:
self.G.clear()
# 尺寸节点
dims = ["外径偏差", "内径偏差", "高度偏差"]
errors = ["X方向误差", "Y方向误差", "Z方向误差", "旋转误差"]
for d in dims:
self.G.add_node(d, ntype="dimension", weight=1.0)
for e in errors:
self.G.add_node(e, ntype="error", weight=1.0)
# 边(基于回归系数映射)
mapping = {
"外径偏差": ["X方向误差", "旋转误差"],
"内径偏差": ["Y方向误差"],
"高度偏差": ["Z方向误差"],
}
for dim in dims:
for err in mapping[dim]:
weight = abs(reg_coeffs.get(dim.replace("偏差", "_dev"), 0.5))
self.G.add_edge(dim, err, weight=weight)
return self.G
</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", "DejaVu Sans"]
plt.rcParams["axes.unicode_minus"] = False
class IncomingVisualizer:
def __init__(self, results_dir: str = "results"):
self.results_dir = Path(results_dir)
self.results_dir.mkdir(exist_ok=True)
def scatter_matrix(self, df: pd.DataFrame):
"""散点矩阵: 尺寸 vs 误差"""
fig, axes = plt.subplots(2, 3, figsize=(15, 10))
dims = ["outer_dia_dev", "inner_dia_dev", "height_dev"]
errs = ["error_x", "total_error"]
for i, dim in enumerate(dims):
for j, err in enumerate(errs):
ax = axes[j, i]
ax.scatter(df[dim], df[err], alpha=0.6, s=20, c="#3498DB")
# 趋势线
z = np.polyfit(df[dim], df[err], 1)
p = np.poly1d(z)
ax.plot(df[dim], p(df[dim]), "r--", linewidth=1)
ax.set_xlabel(dim)
ax.set_ylabel(err)
ax.grid(alpha=0.3)
plt.tight_layout()
plt.savefig(self.results_dir/"scatter_matrix.png", dpi=150, bbox_inches="tight")
plt.close()
def residual_plot(self, df: pd.DataFrame, y_true: np.ndarray, y_pred: np.ndarray):
"""回归残差图"""
residuals = y_true - y_pred
fig, ax = plt.subplots(1, 2, figsize=(12, 5))
ax[0].scatter(y_pred, residuals, alpha=0.6, s=20)
ax[0].axhline(0, color="r", linestyle="--")
ax[0].set_xlabel("预测误差")
ax[0].set_ylabel("残差")
ax[0].set_title("残差 vs 预测值")
ax[0].grid(alpha=0.3)
ax[1].hist(residuals, bins=20, color="#3498DB", alpha=0.7, edgecolor="black")
ax[1].set_xlabel("残差")
ax[1].set_ylabel("频次")
ax[1].set_title("残差分布")
ax[1].grid(alpha=0.3)
plt.tight_layout()
plt.savefig(self.results_dir/"residual_plot.png", dpi=150, bbox_inches="tight")
plt.close()
def sensitivity_rank(self, sens_df: pd.DataFrame):
"""灵敏度排名"""
fig, ax = plt.subplots(figsize=(8, 5))
ax.barh(sens_df["dimension"][::-1],
sens_df["contribution_pct"][::-1],
color=["#E74C3C","#3498DB","#2ECC71"][::-1], alpha=0.8)
ax.set_xlabel("贡献率 (%)")
ax.set_title("各尺寸维度对定位误差的贡献率", fontsize=13, fontweight="bold")
ax.grid(axis="x", alpha=0.3)
for i, v in enumerate(sens_df["contribution_pct"][::-1]):
ax.text(v+1, i, f"{v}%", va="center", fontsize=9)
plt.tight_layout()
plt.savefig(self.results_dir/"sensitivity_rank.png", dpi=150, bbox_inches="tight")
plt.close()
def monte_carlo_dist(self, mc_result: Dict):
"""蒙特卡洛误差分布"""
fig, ax = plt.subplots(figsize=(10, 6))
ax.hist(mc_result["samples"], bins=50, color="#9B59B6",
alpha=0.7, edgecolor="black", density=True)
ax.axvline(mc_result["p95"], color="red", linestyle="--", linewidth=2,
label=f"P95={mc_result['p95']}mm")
ax.axvline(mc_result["mean_error"], color="green", linestyle="--", linewidth=2,
label=f"均值={mc_result['mean_error']}mm")
ax.set_xlabel("定位误差 (mm)")
ax.set_ylabel("概率密度")
ax.set_title("蒙特卡洛误差传播分布", fontsize=13, fontweight="bold")
ax.legend()
ax.grid(alpha=0.3)
plt.tight_layout()
plt.savefig(self.results_dir/"monte_carlo_dist.png", dpi=150, bbox_inches="tight")
plt.close()
def batch_heatmap(self, df: pd.DataFrame):
"""各批次尺寸波动热力图"""
batch_stats = df.groupby("batch_id")[["outer_dia_dev","inner_dia_dev","height_dev"]].mean()
fig, ax = plt.subplots(figsize=(8, max(4, len(batch_stats)*0.4)))
im = ax.imshow(batch_stats.values.T, cmap="RdYlBu_r", aspect="auto")
ax.set_xticks(range(len(batch_stats)))
ax.set_xticklabels(batch_stats.index, rotation=45)
ax.set_yticks(range(3))
ax.set_yticklabels(["外径偏差","内径偏差","高度偏差"])
ax.set_title("各批次尺寸偏差热力图", fontsize=13, fontweight="bold")
plt.colorbar(im, ax=ax)
plt.tight_layout()
plt.savefig(self.results_dir/"batch_heatmap.png", dpi=150, bbox_inches="tight")
plt.close()
def causal_network(self, G: nx.DiGraph):
"""因果链路图"""
fig, ax = plt.subplots(figsize=(10, 7))
pos = nx.spring_layout(G, seed=42, k=0.8)
node_colors = ["#E74C3C" if G.nodes[n].get("ntype")=="dimension" else "#3498DB"
for n in G.nodes()]
node_sizes = [G.nodes[n].get("weight",1)*500 for n in G.nodes()]
edge_weights = [G[u][v].get("weight",0.5)*3 for u,v in G.edges()]
nx.draw_networkx_nodes(G, pos, node_color=node_colors,
node_size=node_sizes, alpha=0.85, ax=ax)
nx.draw_networkx_edges(G, pos, width=edge_weights, alpha=0.5,
arrows=True, arrowsize=15, ax=ax)
labels = {n: n for n in G.nodes()}
nx.draw_networkx_labels(G, pos, labels, font_size=9, ax=ax)
ax.set_title("尺寸维度→定位误差因果链路", fontsize=13, fontweight="bold")
ax.axis("off")
plt.tight_layout()
plt.savefig(self.results_dir/"causal_network.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 SyntheticIncomingGenerator:
"""
合成来料尺寸+定位误差
外径主导定位误差
"""
def __init__(self, rng: Optional[np.random.RandomState] = None):
self.rng = rng or np.random.RandomState(42)
def generate(self, n_parts: int = 60,
incoming_path: str = "incoming_dimensions.csv",
error_path: str = "positioning_errors.csv") -> tuple:
batches = [f"B{i:03d}" for i in range(1, 7)]
# 来料尺寸
inc_records = []
err_records = []
part_id = 1
for _ in range(n_parts):
batch = self.rng.choice(batches)
# 外径: 均值50, 标准差0.04(主导)
outer = self.rng.normal(50.0, 0.04)
# 内径: 均值25, 标准差0.02
inner = self.rng.normal(25.0, 0.02)
# 高度: 均值30, 标准差0.03
heigh
利用AI解决实际问题,如果你觉得这个工具好用,欢迎关注长安牧笛!
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)