feat: initial commit - massive-cloud point cloud processing system
This commit is contained in:
145
alg/点云测距v1.1/train_measurement_system/CLAUDE.md
Normal file
145
alg/点云测距v1.1/train_measurement_system/CLAUDE.md
Normal file
@@ -0,0 +1,145 @@
|
||||
# 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
|
||||
```bash
|
||||
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
|
||||
Reference in New Issue
Block a user