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,145 @@
# Default configuration for coupler panel measurement pipeline.
# All numeric units in mm / degree unless otherwise stated.
# Override fields by passing a dict or a YAML path with the same nested shape.
schema_version: "1.0"
# --- CAD parsing & GT extraction --------------------------------------------
cad:
# OpenCASCADE tessellation quality.
linear_deflection_mm: 0.5
angular_deflection_rad: 0.1
# Hole topology classification.
# The four locating holes are expected to be small and equal-radius;
# the central pass-through hole is expected to be much larger.
locating_hole_radius_mm: [4.0, 12.0] # [min, max] of expected locating hole radius
central_hole_radius_min_mm: 20.0 # any circle larger than this is treated as the centre hole
rectangle_aspect_tol: 0.15 # tolerance for "the 4 hole centres form a rectangle"
# --- Sampling ---------------------------------------------------------------
sampling:
method: poisson_disk # uniform_area | poisson_disk | adaptive | grid_spacing
# Use either spacing_mm OR num_points; if both set, spacing_mm wins.
spacing_mm: 1.0
num_points: 100000
seed: 42
adaptive:
curvature_weight: 1.0
min_spacing_factor: 0.25 # smallest spacing = spacing_mm * factor
max_spacing_factor: 4.0
# --- Simulated scan (optional) ----------------------------------------------
scan_simulator:
enabled: false
view_origin: [10000.0, 0.0, 0.0] # camera position in CAD frame, mm
hpr_radius_mm: 50000.0 # hidden-point-removal radius
# --- Panel deflection injection (the SIGNAL the algorithm should measure) --
# This rotates the panel (and its 4 locating holes) by a known small angle.
# After running the pipeline, theta_right_deg / theta_ref_deg in the result
# should match these values within the algorithm's recovery accuracy.
panel_deflection:
enabled: false
theta_right_deg: 0.0 # atan2(n_y, n_x) target (rotation around z)
theta_ref_deg: 0.0 # atan2(n_z, n_x) target (rotation around -y)
# --- Synthetic noise --------------------------------------------------------
# Realistic LIDAR / structured-light noise on a ~2 m × 2 m panel is ≈ 50-80
# µm = 0.05-0.08 mm. Larger sigma is mostly to test robustness, not to
# match a real sensor.
noise:
enabled: true
sigma_mm: 0.05
mode: isotropic # isotropic | along_normal
seed: 43
# --- Synthetic scan-pose perturbation ---------------------------------------
# Mounting / scanner-stage jitter. 4-hole Kabsch should cancel this; if it
# leaks into the final angles that's a registration error, not a measurement
# of panel deflection. Set rotation_deg=0, translation_mm=0 for "ideal pose"
# experiments that isolate the deflection-recovery accuracy.
transform:
enabled: true
rotation_deg: 0.5 # magnitude; axis is randomised
rotation_axis: random # random | x | y | z | [ax, ay, az]
translation_mm: 2.0 # magnitude; direction is randomised
translation_dir: random
seed: 44
# --- Denoise pipeline -------------------------------------------------------
# Steps are executed in the listed order. Set steps to [] to disable.
denoise:
steps:
- type: passthrough
bbox_padding_mm: 50.0
- type: voxel
voxel_mm: 0.5
- type: statistical
nb_neighbors: 30
std_ratio: 2.0
- type: radius
nb_points: 8
radius_mm: 2.0
# Optional MLS smoothing (requires open3d ≥ 0.18 with ml extras).
smoothing:
enabled: false
search_radius_mm: 2.0
polynomial_order: 2
# --- Registration -----------------------------------------------------------
registration:
method: kabsch_four_holes # only this method is implemented; documented & enforced
# The four GT hole centres come from CAD; the four scan hole centres come
# from the detection module. Pairing is by greedy nearest-neighbour after
# a coarse PCA-based pre-alignment of the centroid.
pre_align: pca_centroid
refuse_if_residual_above_mm: 5.0 # quality flag if RMS pairing residual exceeds this
# --- 4-hole detection in point cloud ----------------------------------------
detection:
# Local panel-plane projection.
panel_normal_seed: from_cad # from_cad | pca | given
panel_normal_pca_kth: 1 # use k-th smallest PCA eigenvector as panel normal
# 2D occupancy grid.
grid_pixel_mm: 0.5
panel_min_area_ratio: 0.4 # largest connected component must be ≥ this fraction of bbox
hole_min_area_mm2: 30.0
hole_max_area_mm2: 800.0
# Circle fitting on hole boundary.
circle_fit:
method: algebraic_then_lsq # algebraic_then_lsq | hyper | taubin
inlier_residual_mm: 0.5
# Selection.
select_top_k_by_radius_match: 4
rectangle_aspect_tol: 0.20
# --- Panel ROI extraction ---------------------------------------------------
roi:
hole_dilate_mm: 3.0 # exclude points within (hole_radius + dilate)
central_hole_dilate_mm: 5.0
edge_buffer_mm: 5.0 # shrink ROI rectangle inward by this
chamfer_normal_dot_min: 0.85 # exclude points whose normal deviates more than acos(0.85) from panel normal
outlier_z_score: 3.0
# --- Plane fit --------------------------------------------------------------
plane_fit:
method: ransac_svd
ransac_iterations: 200
ransac_inlier_thresh_mm: auto # auto = 3*sigma_mm
min_inlier_ratio: 0.6
enforce_nx_positive: true
# --- Metrics ----------------------------------------------------------------
metrics:
# If your right axis is +y, leave this 1. If right is -y, set to -1.
right_axis_sign: 1
# Angles smaller than this are clamped to 0 (purely cosmetic; raw value is
# always in the report).
angle_clamp_deg: 0.0
# --- Output / artifacts -----------------------------------------------------
artifacts:
save_intermediate: true
ply_format: binary # binary | ascii
image_dpi: 150
heatmap_colormap: viridis

View File

@@ -0,0 +1,17 @@
# Profile: high-density scan (≈100w points, sub-mm spacing).
sampling:
spacing_mm: 0.25
num_points: 1000000
denoise:
steps:
- type: passthrough
bbox_padding_mm: 50.0
- type: voxel
voxel_mm: 0.25
- type: statistical
nb_neighbors: 50
std_ratio: 2.0
detection:
grid_pixel_mm: 0.25
plane_fit:
ransac_iterations: 500

View File

@@ -0,0 +1,18 @@
# Profile: low-density scan (≈1w points, ≈2 mm spacing).
sampling:
spacing_mm: 2.0
num_points: 10000
denoise:
steps:
- type: passthrough
bbox_padding_mm: 50.0
- type: voxel
voxel_mm: 1.0
- type: statistical
nb_neighbors: 15
std_ratio: 2.5
detection:
grid_pixel_mm: 1.0
hole_min_area_mm2: 20.0
plane_fit:
ransac_iterations: 100

View File

@@ -0,0 +1,106 @@
# Profile tuned for the lu1-M000004835653_AF4_ASMP072708187_N_AF4.stp panel.
#
# Topology summary (from cad/iter_circular_edges):
# - locating holes: r = 16 mm × 4 corners at (y=±100, z=±180)
# - central hole: r = 100 mm at (y≈1, z=0)
# - panel size: ~200 × 360 mm in y-z, ~76 mm thick along x
#
# Use:
# coupler-measure --stp <path> --out-dir <dir> --profile lu1_af4
cad:
linear_deflection_mm: 0.5
angular_deflection_rad: 0.1
# CAD-side: strict band that selects only the r=16 mm corner holes.
locating_hole_radius_mm: [14.0, 18.0]
central_hole_radius_min_mm: 80.0
rectangle_aspect_tol: 0.30
sampling:
method: poisson_disk
spacing_mm: null
num_points: 500000
seed: 42
# Critical: simulate a single-view "+x looking at -x" scan. Without this,
# back-face points project into the hole regions and detection fails.
scan_simulator:
enabled: true
view_origin: [10000.0, 0.0, 0.0]
hpr_radius_mm: 200000.0
# --- Panel deflection injection -------------------------------------------
# This is the *signal* we want the algorithm to recover. By default it is
# off — sweeps override these.
panel_deflection:
enabled: true
theta_right_deg: 0.5 # rotation around z so n_y > 0
theta_ref_deg: 0.3 # rotation around -y so n_z > 0
# --- Realistic LiDAR / structured-light noise -----------------------------
noise:
enabled: true
sigma_mm: 0.05 # ≈ 50 µm; matches typical industrial scanners
mode: isotropic
seed: 43
# --- Scanner-pose jitter --------------------------------------------------
# Modest values: 4-hole Kabsch should remove this completely.
transform:
enabled: true
rotation_deg: 0.5
translation_mm: 2.0
rotation_axis: random
translation_dir: random
seed: 44
denoise:
steps:
- type: passthrough
bbox_padding_mm: 50.0
- type: voxel
voxel_mm: 0.5 # finer voxel for low-noise data
- type: statistical
nb_neighbors: 20
std_ratio: 2.5
detection:
panel_normal_seed: pca # critical: use cloud's own PCA, not CAD seed
grid_pixel_mm: 2.0
closing_iters: 0
fill_bg_below_mm2: 100.0
panel_min_area_ratio: 0.15
hole_min_area_mm2: 600.0
hole_max_area_mm2: 5000.0
locating_hole_radius_mm: [14.0, 22.0]
circle_fit:
method: algebraic_then_lsq
inlier_residual_mm: 1.5
rectangle_aspect_tol: 0.40
roi:
hole_dilate_mm: 5.0
central_hole_dilate_mm: 10.0
edge_buffer_mm: 8.0
chamfer_normal_dot_min: 0.80
outlier_z_score: 3.0
plane_fit:
ransac_iterations: 300
ransac_inlier_thresh_mm: auto
min_inlier_ratio: 0.5
enforce_nx_positive: true
metrics:
right_axis_sign: 1
angle_clamp_deg: 0.0
artifacts:
save_intermediate: true
ply_format: binary
image_dpi: 150
heatmap_colormap: viridis
registration:
method: kabsch_four_holes
refuse_if_residual_above_mm: 5.0

View File

@@ -0,0 +1,94 @@
# Profile for the train_2 coupler mounting panel measured from a full-vehicle
# scan (train_2_1T.ply, cropped to the coupler ROI).
#
# Part topology (measured from the 1T cloud, dataset frame x=length,
# y=height, z=width):
# - a wide base plate with a RAISED central square mounting plate
# - the central plate has 4 corner bolt holes, r≈15.6 mm,
# rectangle 360 mm (z) × 200 mm (y), at z=±180, y=835/1035
# - NO central pass-through hole
# - the ROI box also slices a roof truss + the base plate behind the
# raised plate, so a normal-direction layer isolation is required
#
# Use:
# run_coupler_measurement_pipeline(input_cloud=roi.ply,
# profile="train2_coupler", roi_spec=<bbox>) # no CAD, no Kabsch
# --- CAD block (not used for STP parse here; kept for radius thresholds) ---
cad:
linear_deflection_mm: 0.5
angular_deflection_rad: 0.1
locating_hole_radius_mm: [11.0, 19.0] # r≈15.6 corner bolt holes
central_hole_radius_min_mm: 999.0 # this part has NO central hole
rectangle_aspect_tol: 0.40
# --- Normal-direction layer isolation (the key pre-processing step) -------
# Isolate the frontmost dominant layer = the raised central plate, so the
# back plate + truss don't fill the holes / pollute the plane fit.
layer_select:
enabled: true
normal_seed: pca # pca | from_cad
half_width_mm: 8.0 # slab half-thickness around the chosen layer
pick: frontmost # frontmost (toward scanner) | densest
bins: 240
# --- Denoise: drop the density-fragile radius filter (sparse-ish scan) ----
denoise:
steps:
- type: passthrough
bbox_padding_mm: 50.0
- type: voxel
voxel_mm: 0.5
- type: statistical
nb_neighbors: 20
std_ratio: 2.5
# --- 4-hole detection tuned for r≈15.6 mm bolt holes ----------------------
detection:
panel_normal_seed: pca
grid_pixel_mm: 2.0
closing_iters: 1
fill_bg_below_mm2: 60.0
panel_min_area_ratio: 0.15
hole_min_area_mm2: 300.0 # r=15.6 -> ~765 mm²; floor well below
hole_max_area_mm2: 1400.0 # ceil above; excludes larger back-layer holes
locating_hole_radius_mm: [11.0, 19.0]
rectangle_aspect_tol: 0.40
circle_fit:
method: algebraic_then_lsq
inlier_residual_mm: 1.5
# --- Panel ROI extraction -------------------------------------------------
roi:
hole_dilate_mm: 5.0
central_hole_dilate_mm: 10.0
edge_buffer_mm: 8.0
chamfer_normal_dot_min: 0.80
outlier_z_score: 3.0
# --- Plane fit ------------------------------------------------------------
plane_fit:
ransac_iterations: 400
ransac_inlier_thresh_mm: 1.0
min_inlier_ratio: 0.3
enforce_nx_positive: true
# --- Metrics --------------------------------------------------------------
# NOTE: this dataset's frame is x=length, y=height, z=width — i.e. y and z
# are swapped relative to the package's nominal (y=width, z=height). The
# angle formulas are symmetric in form; here theta_right = atan2(n_y,n_x)
# is the tilt toward car-height and theta_ref = atan2(n_z,n_x) is the tilt
# toward car-width. Both are ~0 for an undeflected panel.
metrics:
right_axis_sign: 1
angle_clamp_deg: 0.0
registration:
method: kabsch_four_holes
refuse_if_residual_above_mm: 5.0
artifacts:
save_intermediate: true
ply_format: binary
image_dpi: 150
heatmap_colormap: viridis