# 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.3 panel_min_area_ratio: 0.4 # largest connected component must be ≥ this fraction of bbox hole_min_area_mm2: 10.0 hole_max_area_mm2: 1500.0 closing_iters: 2 # 原来没有,加形态学闭运算填补边界断裂 fill_bg_below_mm2: 5.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