python的先进制造技术工业场景模拟第六十篇:读取机器人轨迹误差数据集,建立回归模型,预测不同运动距离下定位误差。
周三下午,机器人调试间。
"你看这条弧焊轨迹,"调试员小赵把激光跟踪仪的报告甩在桌上,"新到的弧焊机器人,标称重复定位精度 ±0.05mm,但跑了一圈 2 米长焊缝,末端实际轨迹跟编程轨迹差了 0.42mm。而且不是固定的——跑 0.5 米差 0.12mm,跑 1 米差 0.25mm,跑 2 米差 0.42mm,跑 3 米直接到 0.68mm。距离越长误差越大,但没人说得清到底什么关系。"
我点开他导出的 CSV。
"这表里有什么?"我问。
"每次标定采集的数据:运行距离(m)、各关节角度、末端实际位置(XYZ)、理论位置(XYZ)、定位误差(mm)、速度(mm/s)、负载(kg)、环境温度(℃),"小赵说,"但它就是一张误差记录表。你能看到误差随距离在涨,但工艺卡上写的是'定位精度 ±0.1mm'——那是空载短距离的指标。实际焊接 2 米长焊缝,我怎么预判误差会到多少?总不能每换一种焊缝长度就重新拿激光跟踪仪测一遍吧?"
"我就想干一件事,"小赵说,"给我一个程序:把历史轨迹误差数据灌进去,建个回归模型,输入'我要跑多长的距离',直接输出'预估定位误差是多少'。我拿去跟工艺员说'这条 2.5 米焊缝,预计末端误差 0.52mm,超了工艺要求的 0.3mm,得加中间标点或者分段焊'。"
"比如误差跟运行距离不是简单的线性关系——可能是距离的一次项+二次项叠加,因为连杆柔性变形和齿轮间隙都随行程累积,"我接话,"用 pandas 做数据清洗+特征工程,numpy 算误差统计量,scikit-learn 的 PolynomialFeatures 做距离多项式展开,用 Ridge 回归拟合'距离→误差'的映射,再跟 Linear/Pipeline 对比。scipy 做残差正态性检验和置信区间,matplotlib 画实际距离vs误差散点+回归拟合曲线+残差分布+特征重要性+多项式阶数对比+预测误差带,networkx 建'特征→模型→预测'的推理链路。"
"对,"小赵点头,"别给我黑盒,要能说清楚'为什么跑 2 米误差是 0.42 而不是 0.2'。我看得懂,能拿去跟质量部门解释'误差 = 0.05 + 0.08×距离 + 0.03×距离²,R²=0.96,距离是最主要因素'。"
"用 pandas 做特征工程,sklearn Ridge 回归+多项式,scipy 残差检验,matplotlib 出 6 图+报告,存 results/,"我开工程,"数据自包含,合成一批 80 条轨迹误差记录(距离 0.2-5m),下载就能跑。"
敲了行原型:
# 误差模型: error = β₀ + β₁×distance + β₂×distance² + β₃×speed + β₄×payload + ε
# Ridge 回归 → 防止过拟合(多项式高阶容易炸)
# 输入: 运行距离 → 输出: 预测误差 + 95%置信区间
# 残差检验 → 模型靠不靠谱
"完整版 OOP 封好,"我说,"数据加载器、特征工程器、回归建模器、模型评估器、可视化器、推理链路,输出误差预测+6图+报告。"
小赵凑近看:"那以后看报告:Ridge 回归 R²=0.967,距离解释了 78% 的误差变异,速度 12%,负载 7%。预测 2.5 米焊缝的误差 0.52±0.06mm(95% CI)。多项式 2 阶最优,3 阶开始过拟合。残差基本正态,模型可信。结论:超过 1.8 米的长焊缝必须分段或加中间标点,单段精度保不住。"
"对,"我接话,"机器人不是标称 ±0.05mm 就永远 ±0.05mm,是'跑得越远飘得越多'。数字孪生里挂误差预测节点,这套就是编程员的'长轨迹精度预警器'。"
一、实际应用场景(真实痛点)
场景设定:工业机器人在执行长轨迹任务(弧焊、涂胶、切割)时,末端定位误差随运行距离增加而累积。工艺部门按"标称重复定位精度"制定工艺卡,但实际长轨迹误差远超标称值,导致焊接偏缝、涂胶断线、切割过切等质量问题。
现场原话(叙事化):
"不是机器人精度不行,"小赵说,"是标称精度是空载短距离测的。实际干 2.5 米长焊缝,连杆柔性变形、齿轮反向间隙、温度漂移全叠加起来,末端能飘到 0.5mm 以上。但工艺卡上写的是'定位精度 ±0.1mm'——那是跑 0.3 米短轨迹的指标。我拿这个指标去编 2.5 米的程序,焊出来整条缝偏移,质检不过关。"
"最坑的是没有预判手段,"小赵补充,"每次换新产品,焊缝长度变了,我就得重新拿激光跟踪仪测一遍实际误差。一个产品测 3 天,测完发现超差,改方案,再测。如果有个模型能根据历史数据告诉我'跑 2 米大概飘多少',我就能提前决定要不要分段焊或者加中间标点。现在全靠猜。"
核心矛盾:"标称精度指标 + 经验猜测" 与 "数据驱动的误差回归模型 + 距离-误差量化映射 + 长轨迹精度预警" 之间的断层。
二、痛点分析(映射到滨州职业学院《先进制造技术》课程模型)
《先进制造技术》模块 本篇痛点对应
工业机器人技术基础:机器人运动学与精度分析 定位误差建模与预测
先进制造技术基础:几何量公差与测量 误差累积规律量化
智能制造与数字孪生:过程建模与预测 数据驱动的误差预测
数控加工与CAD/CAM技术:轨迹规划精度 长轨迹分段策略
一句话总结:我们需要一个"机器人轨迹误差数据→特征工程+多项式Ridge回归+残差检验+误差带预测程序",用
"pandas" 做数据清洗/特征构造,
"numpy" 做统计量计算,
"scikit-learn" 多项式回归+模型对比,
"scipy" 残差正态性检验+置信区间,
"matplotlib" 画散点+回归曲线+残差分布+特征重要性+阶数对比+预测误差带,
"networkx" 建推理链路,实现从"标称精度查手册"到"数据驱动的误差量化预测+长轨迹精度预警"。
三、核心逻辑讲解(大白话)
3.1 问题本质:把机器人想成"尺子"
把机器人末端定位想成用一把会弯的尺子画线:
* 运行距离 = 你画的线有多长
* 定位误差 = 尺子弯了多少(线画歪了多少)
* 核心发现 = 线越长,尺子弯得越多——但不是直线变弯,是加速变弯(二次关系)
* 为什么 = 连杆柔性(距离越长关节转得越多→柔性变形越大)+ 齿轮间隙累积 + 温度漂移
* 你的目标 = 给一个距离,直接告诉你"大概会偏多少"
3.2 业务逻辑 → 代码映射
导入机器人轨迹误差数据
│
▼ TrajectoryDataLoader (pandas)
读取表:
运行距离(m), 各关节角度(°), 末端实际XYZ(mm),
理论XYZ(mm), 定位误差(mm), 速度(mm/s),
负载(kg), 环境温度(℃)
│
▼ FeatureEngineer (pandas + numpy)
特征工程:
距离 → 多项式展开(distance, distance², distance³)
速度分组 → 低速/中速/高速
负载分组 → 轻载/中载/重载
误差计算 → 欧氏距离(实际-理论)
│
▼ RegressionModeler (scikit-learn)
回归建模:
Ridge 回归(多项式2阶) → 防过拟合
Linear 回归 → 基线对比
Pipeline(StandardScaler + Ridge) → 标准化
交叉验证 → 选最佳 alpha
│
▼ ModelEvaluator (scipy + sklearn)
模型评估:
R², MSE, MAE
残差正态性 → Shapiro-Wilk
残差自相关 → Durbin-Watson
95% 置信区间 → prediction interval
│
▼ TrajectoryVisualizer (matplotlib + networkx)
可视化:
1. 距离-误差散点+回归曲线
2. 残差分布直方图+Q-Q
3. 特征系数条形图
4. 多项式阶数对比(R² vs degree)
5. 预测误差带(均值±2σ)
6. 推理链路网络图
│
▼ SyntheticTrajectoryData (numpy)
合成数据:
80条轨迹 × 距离0.2-5m
误差 = 0.05 + 0.08×d + 0.03×d² + 噪声
可复现
3.3 为什么不能"看标称精度"
视角 问题
标称 ±0.05mm 空载短距离,实际长轨迹完全不适用
经验法则 "长焊缝多留余量"——留多少?不知道
回归模型 输入距离→输出误差+置信区间
多项式 捕捉加速累积效应
残差检验 验证模型靠不靠谱
3.4 分析前后对比
维度 传统方式 本程序
误差预估 查手册/凭经验 回归模型量化预测
长轨迹策略 一刀切分段 按预测误差阈值分段
模型可信度 不知道 残差检验+交叉验证
输出 "差不多吧" 0.52±0.06mm (95% CI)
四、OOP 代码实现
4.1 项目结构
robot_error_predictor/
├── robot_error_predictor/
│ ├── __init__.py
│ ├── trajectory_data_loader.py # 数据加载
│ ├── feature_engineer.py # 特征工程
│ ├── regression_modeler.py # 回归建模
│ ├── model_evaluator.py # 模型评估
│ ├── trajectory_visualizer.py # 可视化
│ └── synthetic_trajectory_data.py # 合成数据
├── tests/
│ ├── __init__.py
│ └── test_trajectory.py
├── results/
│ ├── scatter_regression.png
│ ├── residual_analysis.png
│ ├── feature_coefficients.png
│ ├── degree_comparison.png
│ ├── prediction_band.png
│ ├── inference_network.png
│ ├── prediction_detail.csv
│ └── error_report.txt
└── run_trajectory.py
4.2 核心源码
<details>
<summary></summary>
"""机器人轨迹误差数据加载器"""
import pandas as pd
from pathlib import Path
from typing import Optional
class TrajectoryDataLoader:
"""读取机器人轨迹误差数据集"""
def __init__(self, filepath: str = "trajectory_error_data.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 = ["record_id", "distance_m", "error_mm", "speed_mm_s",
"payload_kg", "temp_c"]
miss = [c for c in req if c not in df.columns]
if miss:
raise ValueError(f"缺列: {miss}")
# 类型转换
num_cols = ["distance_m", "error_mm", "speed_mm_s",
"payload_kg", "temp_c"]
for c in num_cols:
df[c] = pd.to_numeric(df[c], errors="coerce")
df = df.dropna(subset=["distance_m", "error_mm"]).reset_index(drop=True)
return df
def summary(self, df: pd.DataFrame) -> str:
s = f"记录总数: {len(df)}\n"
s += f"距离范围: {df['distance_m'].min():.1f} - {df['distance_m'].max():.1f} m\n"
s += f"误差范围: {df['error_mm'].min():.3f} - {df['error_mm'].max():.3f} mm\n"
s += f"速度范围: {df['speed_mm_s'].min():.0f} - {df['speed_mm_s'].max():.0f} mm/s\n"
s += f"负载范围: {df['payload_kg'].min():.1f} - {df['payload_kg'].max():.1f} kg"
return s
</details>
<details>
<summary></summary>
"""特征工程 (pandas + numpy)"""
import numpy as np
import pandas as pd
from typing import Dict, List
class FeatureEngineer:
"""构造回归特征"""
def __init__(self, max_degree: int = 3):
self.max_degree = max_degree
def engineer(self, df: pd.DataFrame) -> pd.DataFrame:
result = df.copy()
# 多项式特征: distance^m
for d in range(2, self.max_degree + 1):
result[f"distance_m^{d}"] = result["distance_m"] ** d
# 速度分组
result["speed_low"] = (result["speed_mm_s"] < 300).astype(int)
result["speed_high"] = (result["speed_mm_s"] > 800).astype(int)
# 负载分组
result["payload_heavy"] = (result["payload_kg"] > 5.0).astype(int)
# 温度偏移(以22℃为基准)
result["temp_deviation"] = result["temp_c"] - 22.0
return result
def get_feature_columns(self, df: pd.DataFrame) -> List[str]:
"""返回用于回归的特征列"""
exclude = ["record_id", "error_mm"]
return [c for c in df.columns if c not in exclude]
def get_polynomial_features(self, distance: float,
degree: int = 2) -> np.ndarray:
"""为单个距离值生成多项式特征向量"""
features = [1.0, distance] # 偏置 + 一次项
for d in range(2, degree + 1):
features.append(distance ** d)
return np.array(features).reshape(1, -1)
</details>
<details>
<summary></summary>
"""回归建模 (scikit-learn)"""
import numpy as np
from typing import Dict, List, Tuple
from sklearn.linear_model import Ridge, LinearRegression
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score
import pandas as pd
class RegressionModeler:
"""多项式Ridge回归 + 线性基线"""
def __init__(self, alpha: float = 1.0, cv: int = 5):
self.alpha = alpha
self.cv = cv
self.ridge_model_ = None
self.linear_model_ = None
self.best_degree_ = 2
self.cv_results_ = {}
def fit_ridge(self, X: np.ndarray, y: np.ndarray,
degree: int = 2) -> Pipeline:
"""Ridge 回归(带多项式展开+标准化)"""
pipeline = Pipeline([
("poly", PolynomialFeatures(degree=degree, include_bias=False)),
("scaler", StandardScaler()),
("ridge", Ridge(alpha=self.alpha, random_state=42)),
])
pipeline.fit(X.reshape(-1, 1) if X.ndim == 1 else X, y)
self.ridge_model_ = pipeline
return pipeline
def fit_linear(self, X: np.ndarray, y: np.ndarray) -> LinearRegression:
"""线性基线"""
lin = LinearRegression()
lin.fit(X.reshape(-1, 1) if X.ndim == 1 else X, y)
self.linear_model_ = lin
return lin
def compare_degrees(self, X: np.ndarray, y: np.ndarray,
max_degree: int = 4) -> Dict:
"""对比不同多项式阶数"""
results = {}
X_1d = X.reshape(-1, 1) if X.ndim > 1 else X
for d in range(1, max_degree + 1):
pipeline = Pipeline([
("poly", PolynomialFeatures(degree=d, include_bias=False)),
("scaler", StandardScaler()),
("ridge", Ridge(alpha=self.alpha, random_state=42)),
])
scores = cross_val_score(pipeline, X_1d, y,
cv=self.cv, scoring="r2")
results[d] = {
"mean_r2": float(scores.mean()),
"std_r2": float(scores.std()),
}
if scores.mean() > results.get(self.best_degree_, {}).get("mean_r2", -999):
self.best_degree_ = d
self.cv_results_ = results
return results
def predict(self, X: np.ndarray) -> np.ndarray:
"""预测"""
if self.ridge_model_ is None:
raise ValueError("模型未训练")
return self.ridge_model_.predict(X)
def predict_with_interval(self, X: np.ndarray,
y_train: np.ndarray,
X_train: np.ndarray,
confidence: float = 0.95) -> Tuple:
"""预测 + 置信区间(简化版)"""
pred = self.predict(X)
# 基于训练残差估计标准差
train_pred = self.predict(X_train)
residuals = y_train - train_pred
sigma = np.std(residuals)
# 正态近似
from scipy import stats
z = stats.norm.ppf((1 + confidence) / 2)
margin = z * sigma
return pred, pred - margin, pred + margin, sigma
</details>
<details>
<summary></summary>
"""模型评估 (scipy + sklearn)"""
import numpy as np
from typing import Dict
from scipy import stats
from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error
class ModelEvaluator:
"""回归模型评估"""
def __init__(self):
pass
def evaluate(self, y_true: np.ndarray,
y_pred: np.ndarray) -> Dict:
"""计算评估指标"""
r2 = r2_score(y_true, y_pred)
mse = mean_squared_error(y_true, y_pred)
rmse = np.sqrt(mse)
mae = mean_absolute_error(y_true, y_pred)
residuals = y_true - y_pred
# 残差正态性检验
shapiro_stat, shapiro_p = stats.shapiro(residuals)
# Durbin-Watson (自相关)
dw = self._durbin_watson(residuals)
return {
"r2": round(r2, 4),
"mse": round(mse, 6),
"rmse": round(rmse, 4),
"mae": round(mae, 4),
"shapiro_stat": round(shapiro_stat, 4),
"shapiro_p": round(shapiro_p, 6),
"durbin_watson": round(dw, 4),
"residuals": residuals,
}
def _durbin_watson(self, residuals: np.ndarray) -> float:
"""Durbin-Watson 统计量"""
diff = np.diff(residuals)
dw = np.sum(diff ** 2) / np.sum(residuals ** 2)
return dw
def feature_importance(self, model, feature_names: list) -> Dict:
"""提取特征系数"""
importance = {}
try:
# 从 pipeline 中提取 ridge
if hasattr(model, "named_steps"):
ridge = model.named_steps.get("ridge")
poly = model.named_steps.get("poly")
if ridge is not None and hasattr(ridge, "coef_"):
coefs = ridge.coef_
if poly is not None:
names = poly.get_feature_names_out(feature_names)
else:
names = feature_names
for name, coef in zip(names, coefs):
importance[name] = abs(float(coef))
else:
# 直接是 LinearRegression
if hasattr(model, "coef_"):
for name, coef in zip(feature_names, model.coef_):
importance[name] = abs(float(coef))
except Exception:
pass
return dict(sorted(importance.items(),
key=lambda x: abs(x[1]), reverse=True))
</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 TrajectoryVisualizer:
def __init__(self, results_dir: str = "results"):
self.results_dir = Path(results_dir)
self.results_dir.mkdir(exist_ok=True)
def scatter_regression(self, X: np.ndarray, y: np.ndarray,
y_pred: np.ndarray,
best_degree: int, r2: float):
"""距离-误差散点+回归曲线"""
fig, ax = plt.subplots(figsize=(10, 7))
ax.scatter(X, y, c="#3498DB", alpha=0.6, s=50,
edgecolors="black", linewidth=0.5,
label="实际误差", zorder=3)
# 排序画曲线
X_sorted = np.sort(X.flatten())
ax.plot(X_sorted, y_pred[np.argsort(X.flatten())],
"r-", linewidth=2.5, label=f"Ridge 拟合 (deg={best_degree})",
zorder=4)
ax.set_xlabel("运行距离 (m)", fontsize=12)
ax.set_ylabel("定位误差 (mm)", fontsize=12)
ax.set_title(f"运行距离 vs 定位误差 (R²={r2:.3f})",
fontsize=13, fontweight="bold")
ax.legend(fontsize=11)
ax.grid(alpha=0.3)
plt.tight_layout()
plt.savefig(self.results_dir/"scatter_regression.png",
dpi=150, bbox_inches="tight")
plt.close()
def residual_analysis(self, residuals: np.ndarray,
shapiro_p: float):
"""残差分析"""
fig, axes = plt.subplots(1, 2, figsize=(14, 6))
# 残差直方图
axes[0].hist(residuals, bins=15, color="#3498DB",
edgecolor="black", alpha=0.7, density=True)
mu, sigma = np.mean(residuals), np.std(residuals)
x = np.linspace(mu - 3*sigma, mu + 3*sigma, 100)
from scipy import stats
axes[0].plot(x, stats.norm.pdf(x, mu, sigma), "r-", linewidth=2,
label="正态拟合")
axes[0].axvline(0, color="red", linestyle="--", linewidth=1.5)
axes[0].set_xlabel("残差 (mm)")
axes[0].set_ylabel("密度")
axes[0].set_title(f"残差分布 (Shapiro p={shapiro_p:.4f})",
fontsize=11, fontweight="bold")
axes[0].legend()
axes[0].grid(alpha=0.3)
# Q-Q 图
stats.probplot(residuals, dist="norm", plot=axes[1])
axes[1].set_title("Q-Q 图", fontsize=11, fontweight="bold")
axes[1].grid(alpha=0.3)
plt.suptitle("残差分析", fontsize=14, fontweight="bold")
plt.tight_layout()
plt.savefig(self.results_dir/"residual_analysis.png",
dpi=150, bbox_inches="tight")
plt.close()
def feature_coefficients(self, importance: Dict):
"""特征系数条形图"""
fig, ax = plt.subplots(figsize=(10, 6))
names = list(importance.keys())[:8]
vals = [importance[n] for n in names]
colors = plt.cm.viridis(np.array(vals) / max(vals))
ax.barh(range(len(names)), vals[::-1], color=colors[::-1],
edgecolor="black", height=0.6)
ax.set_yticks(range(len(names)))
ax.set_yticklabels(names[::-1], fontsize=10)
ax.set_xlabel("系数绝对值")
ax.set_title("特征重要性 (系数绝对值)", fontsize=13, fontweight="bold")
ax.grid(axis="x", alpha=0.3)
plt.tight_layout()
plt.savefig(self.results_dir/"feature_coefficients.png",
dpi=150, bbox_inches="tight")
plt.close()
def degree_comparison(self, cv_results: Dict):
"""多项式阶数对比"""
fig, ax = plt.subplots(figsize=(8, 6))
degrees = list(cv_results.keys())
means = [cv_results[d]["mean_r2"] for d in degrees]
stds = [cv_results[d]["std_r2"] for d in degrees]
ax.bar(degrees, means, yerr=stds, color="#3498DB",
edgecolor="black", alpha=0.8, capsize=8)
ax.set_xticks(degrees)
ax.set_xlabel("多项式阶数")
ax.set_ylabel("交叉验证 R²")
ax.set_title("多项式阶数 vs 模型性能", fontsize=13, fontweight="bold")
ax.grid(axis="y", alpha=0.3)
plt.tight_layout()
plt.savefig(self.results_dir/"degree_comparison.png",
dpi=150, bbox_inches="tight")
plt.close()
def prediction_band(self, X: np.ndarray, y_pred: np.ndarray,
lower: np.ndarray, upper: np.ndarray):
"""预测误差带"""
fig, ax = plt.subplots(figsize=(10, 7))
X_sorted = np.sort(X.flatten())
idx = np.argsort(X.flatten())
ax.plot(X_sorted, y_pred[idx], "b-", linewidth=2.5,
label="预测均值", zorder=3)
ax.fill_between(X_sorted, lower[idx], upper[idx],
alpha=0.2, color="blue", label="95% 置信区间")
ax.set_xlabel("运行距离 (m)", fontsize=12)
ax.set_ylabel("预测定位误差 (mm)", fontsize=12)
ax.set_title("定位误差预测带", fontsize=13, fontweight="bold")
ax.legend(fontsize=11)
ax.grid(alpha=0.3)
plt.tight_layout()
plt.savefig(self.results_dir/"prediction_band.png",
dpi=150, bbox_inches="tight")
plt.close()
def inference_network(self):
"""推理链路网络"""
fig, ax = plt.subplots(figsize=(12, 8))
G = nx.DiGraph()
nodes = [
("原始数据", "input"),
("特征工程", "process"),
("多项式展开", "process"),
("标准化", "process"),
("Ridge回归", "model"),
("误差预测", "output"),
("置信区间", "output"),
]
for n, nt in nodes:
G.add_node(n, ntype=nt)
edges = [
("原始数据", "特征工程"),
("特征工程", "多项式展开"),
("多项式展开", "标准化"),
("标准化", "Ridge回归"),
("Ridge回归", "误差预测"),
("Ridge回归", "置信区间"),
]
G.add_edges_from(edges)
pos = nx.spring_layout(G, seed=42, k=2)
color_map = {
"input": "#3498DB", "process": "#F39C12",
"model": "#9B59B6", "output": "#27AE60"
}
node_colors = [color_map[G.nodes[n]["ntype"]] for n in G.nodes()]
nx.draw_networkx_nodes(G, pos, node_color=node_colors,
node_size=2500, alpha=0.85, ax=ax)
nx.draw_networkx_edges(G, pos, arrows=True, arrowsize=15,
edge_color="gray", alpha=0.6, ax=ax)
nx.draw_networkx_labels(G, pos, font_size=9, ax=ax)
ax.set_title("推理链路", fontsize=14, fontweight="bold")
ax.axis("off")
plt.tight_layout()
plt.savefig(self.results_dir/"inference_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 SyntheticTrajectoryGenerator:
"""
80条轨迹误差记录
误差 = 0.05 + 0.08×d + 0.03×d² + 噪声
"""
def __init__(self, rng: Optional[np.random.RandomState] = None):
self.rng = rng or np.ran
利用AI解决实际问题,如果你觉得这个工具好用,欢迎关注长安牧笛!
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)