Files
massive-cloud/alg/点云测距v1.1/train_measurement_system/CLAUDE.md

5.9 KiB

Train Measurement System - Developer Guide

Architecture Overview

This is a configuration-driven, plugin-based point cloud measurement system for train inspection. The core design principle: measurements are defined in YAML, not hardcoded in Python.

Key Design Decisions

Why configuration-driven?

  • Users need to measure 20+ different features per train scan
  • Measurement locations are consistent across scans but vary by train model
  • Non-programmers should be able to add new measurement tasks by editing YAML

Why plugin-based measurement types?

  • Three fundamentally different measurement algorithms: plane-to-plane, point-to-plane, point-to-point
  • Each type has different input requirements (ROI bboxes vs exact coordinates)
  • Easy to add new types (e.g., circle-to-circle) without modifying core logic

Why single large point cloud input?

  • Train scans are 100M points covering the entire vehicle
  • ROI extraction happens at runtime based on bbox parameters
  • Avoids pre-segmentation and maintains spatial context

Common Development Tasks

Running measurements

conda activate pcc-experiment
cd train_measurement_system
python main.py

Results: results/measurement_results_YYYYMMDD_HHMMSS.xlsx Visualizations: visualizations/*.ply

Adding a new measurement task

  1. Edit config/measurements.yaml - add task definition with appropriate type
  2. Set enabled: true and provide required parameters for that type
  3. Run python main.py - the task will execute automatically
  4. Check Excel results - verify mean, std dev, inlier ratio
  5. Inspect PLY files - confirm ROI extraction is correct

Adding a new measurement type

  1. Create src/measurements/your_type.py inheriting from BaseMeasurement
  2. Implement execute() -> MeasurementResult with your algorithm
  3. Register in src/measurements/__init__.py - add to __all__
  4. Update src/task_manager.py - add branch in _create_measurement_task()
  5. Document in README.md - add config example and parameter descriptions

Architecture Flow

YAML Config → TaskManager → [Measurement Plugin] → Excel + PLY
                ↓
         PointCloudLoader (cached)
                ↓
         ROIExtractor / PlaneFitter (shared utilities)

TaskManager orchestrates everything:

  • Loads point cloud once, caches in memory
  • Iterates through enabled tasks
  • Instantiates appropriate measurement class based on type field
  • Collects results and delegates to ExcelExporter

Measurement plugins are stateless:

  • Receive full point cloud + task config in constructor
  • Extract ROI, run algorithm, return MeasurementResult
  • No shared state between tasks

Critical Implementation Details

Coordinate System

  • Point cloud uses global coordinates (mm units)
  • Z-axis is vertical (up positive)
  • ROI bboxes are in global coordinates
  • No coordinate transformations applied during extraction

RANSAC Plane Fitting

  • inlier_ratio in results indicates ROI quality, not measurement accuracy
  • 100% inlier ratio = ROI perfectly contains only the target plane
  • Low inlier ratio (<70%) = ROI includes multiple surfaces or noise
  • Automatic downsampling: ROIs >10k points are sampled to 10k before SVD fitting (prevents memory explosion)

Point-to-Plane Distance

  • Two modes: exact_points (KDTree nearest neighbor) vs bbox_filtered (extract then filter)
  • exact_points is faster but requires knowing precise coordinates
  • bbox_filtered supports filters like max_abs_coordinate for finding extreme points

Plane-to-Plane Distance

  • Unidirectional sampling: samples points from source plane, measures to target plane
  • Not symmetric: swapping source/target may give different results if planes aren't parallel
  • Standard deviation indicates parallelism quality

Testing Strategy

When modifying measurement algorithms:

  1. Disable all tasks except one test case (enabled: false)
  2. Run and verify Excel output matches expected values
  3. Open PLY files in CloudCompare/MeshLab to visually verify ROI extraction
  4. Check console output for warnings (low inlier ratio, insufficient points)

When adding new measurement types:

  1. Start with a simple test case with known ground truth
  2. Verify the MeasurementResult.data dictionary contains all required fields
  3. Ensure visualization saves the relevant points (not the entire ROI)
  4. Test with edge cases: empty ROI, single point, coplanar points

Common Pitfalls

  • Forgetting to set enabled: true - task silently skipped
  • Wrong coordinate order - YAML uses [x, y, z], some tools use [z, y, x]
  • Bbox too large - includes multiple surfaces, low inlier ratio
  • Bbox too small - insufficient points for robust fitting
  • Missing visualization_dir - no PLY files generated (optional but recommended)
  • Modifying cached point cloud - reload by restarting Python process

Performance Notes

  • Point cloud loading: ~10-30 seconds for 100M points (cached after first load)
  • Single plane-to-plane task: ~5-10 seconds (ROI extraction + RANSAC + sampling)
  • Bottleneck is usually RANSAC iterations, not point cloud I/O
  • Visualization (PLY save) adds ~1-2 seconds per task

Extension Points

Want to add CAD-based ROI extraction?

  • Modify roi_extractor.py to accept plane parameters from CAD
  • Keep bbox-based extraction as fallback
  • Add roi_source: "cad" vs "bbox" in config

Want to add statistical outlier removal?

  • Add preprocessing step in measurement plugins before RANSAC
  • Make it optional via params.remove_outliers: true

Want to support multiple point cloud files?

  • Modify task_manager.py to accept per-task pointcloud_file override
  • Update pointcloud_loader.py to cache multiple files by path

Want to add 2D projections or cross-sections?

  • Create new measurement type cross_section_profile
  • Use roi_extractor to get 3D points, then project to 2D plane
  • Output profile data as additional sheet in Excel