feat: 算法升级、整车配准集成与性能分析文档

算法更新: delivery v1.2.1、平整度v1.5、测距v2.2、整车配准v1.3
适配器: vehicle-registration 新增、各算法 manifest 和 adapter 更新
后端: taskCadFiles/source 字段迁移、derivedPointClouds 注册、取消任务联动
前端: ElapsedTime 时长显示、两步算法流程、canRun 逻辑修复
文档: 新增5份算法性能分析报告
This commit is contained in:
2026-06-25 08:22:20 +00:00
parent cec0766e67
commit 29f1d45d66
266 changed files with 1311475 additions and 2846 deletions

View File

@@ -0,0 +1,104 @@
from __future__ import annotations
from copy import deepcopy
from pathlib import Path
from typing import Any
import yaml
DEFAULT_CONFIG: dict[str, Any] = {
"paths": {
"cad": "CAD/11.step",
"mesh": "Mesh/11.stl",
"pointcloud": "PointCloud/11.ply",
"noisy_pointcloud": "Noise_PointCloud/11_noisy.ply",
"output_mesh": "Mesh/11.stl",
"curvature_output": None,
},
"cad": {
"precision": 1.0,
"enabled": False,
},
"noise": {
"enabled": True,
"std": 4.0,
"seed": None,
},
"filters": {
"enabled": True,
"methods": ["SOR"],
"sor_neighbors": 20,
"sor_std_ratio": 2.0,
"ror_points": 5,
"ror_radius": 20.0,
"voxel_size": 0.05,
"pass_axis": "z",
"pass_min": None,
"pass_max": None,
"bf_sigma_s": 0.01,
"bf_sigma_r": 0.1,
},
"registration": {
"voxel_size": 10.0,
"roll": 10.0,
"pitch": 10.0,
"yaw": 10.0,
"trans_range": 0.0,
"random_seed": None,
},
"evaluation": {
"chunk_size": 2048,
"triangle_chunk_size": 4096,
"cad_mesh_deflection": 0.1,
},
"curvature": {
"radius": 2.0,
"max_nn": 30,
"color_scale": 3.0,
},
"plane": {
"size_mm": 1000.0,
"noise_std_mm": 0.5,
"num_points": 10000,
"threshold_mm": 0.5,
"max_iterations": 2000,
},
"visualization": {
"enabled": True,
},
}
def deep_update(base: dict[str, Any], updates: dict[str, Any]) -> dict[str, Any]:
result = deepcopy(base)
for key, value in updates.items():
if isinstance(value, dict) and isinstance(result.get(key), dict):
result[key] = deep_update(result[key], value)
else:
result[key] = value
return result
class ConfigLoader:
"""Load YAML config and merge it with project defaults."""
def __init__(self, default_config: dict[str, Any] | None = None) -> None:
self.default_config = default_config or DEFAULT_CONFIG
def load(self, config_path: str | None = None) -> dict[str, Any]:
config = deepcopy(self.default_config)
if not config_path:
return config
path = Path(config_path)
if not path.exists():
raise FileNotFoundError(f"Config file not found: {path}")
with path.open("r", encoding="utf-8") as f:
user_config = yaml.safe_load(f) or {}
if not isinstance(user_config, dict):
raise ValueError("Config file must contain a YAML mapping at the top level.")
return deep_update(config, user_config)