refactor: remove --metrics-json from refine_ground_plane.py
This commit is contained in:
@@ -150,8 +150,9 @@ uv run calibrate_extrinsics.py ... --save-depth output/calibration_depth.h5
|
||||
- `meta/`: Global metadata (schema version, units=meters).
|
||||
- `cameras/{serial}/`:
|
||||
- `intrinsics`: Camera matrix (3x3).
|
||||
- `pooled_depth`: The aggregated depth map used for verification (gzip compressed).
|
||||
- `resolution`: [width, height].
|
||||
- `pooled_depth`: The aggregated depth map used for verification (gzip compressed).
|
||||
- `raw_frames/`: (Optional) Individual frames if pooling wasn't used.
|
||||
|
||||
This allows `refine_ground_plane.py` to run repeatedly with different parameters without re-processing the raw SVO files.
|
||||
|
||||
@@ -227,3 +228,65 @@ The system now explicitly sets `InitParameters.coordinate_units = sl.UNIT.METER`
|
||||
If `refine_depth` shows `success: false` but `nfev` (evaluations) is high, the optimizer may have hit a flat region or local minimum.
|
||||
- **Check**: Look at `termination_message` in the JSON output.
|
||||
- **Fix**: Try enabling `--use-confidence-weights` or checking if the initial ArUco pose is too far off (reprojection error > 2.0).
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### 1. Depth Data Structure (`--save-depth`)
|
||||
|
||||
The system uses HDF5 for efficient, compressed storage of depth data required for decoupled refinement.
|
||||
|
||||
**File Structure:**
|
||||
- **`meta/`**: Global metadata.
|
||||
- `schema_version`: Integer version (currently 1).
|
||||
- `units`: Explicitly "meters".
|
||||
- `coordinate_frame`: "world_from_cam".
|
||||
- **`cameras/{serial}/`**: Per-camera data.
|
||||
- `intrinsics`: 3x3 camera matrix.
|
||||
- `resolution`: [width, height].
|
||||
- `pooled_depth`: Aggregated depth map (gzip compressed, level 4).
|
||||
- `raw_frames/`: (Optional) Individual frames if pooling wasn't used.
|
||||
|
||||
This structure allows `refine_ground_plane.py` to load pre-processed depth maps without needing the original SVO files or re-running the ArUco detection pipeline.
|
||||
|
||||
### 2. Ground Plane Refinement Pipeline
|
||||
|
||||
The `refine_ground_plane.py` tool implements a robust multi-camera consensus algorithm to align the floor plane.
|
||||
|
||||
**Core Algorithm (`aruco/ground_plane.py`):**
|
||||
|
||||
1. **Per-Camera Plane Detection**:
|
||||
- **Unprojection**: Converts the depth map to a point cloud in the *world frame* using the initial ArUco extrinsics.
|
||||
- **RANSAC**: Uses Open3D's `segment_plane` to find the dominant plane.
|
||||
- **Quality Gates**:
|
||||
- `min_inliers`: Requires at least 500 points.
|
||||
- `normal_vertical_thresh`: Normal must be roughly vertical (>0.9 dot product with Y-axis).
|
||||
|
||||
2. **Robust Consensus**:
|
||||
- Computes the **geometric median** of all valid plane normals and distances to reject outliers.
|
||||
- **Outlier Rejection**: Discards planes deviating >15° in angle or >0.5m in distance from the median.
|
||||
- **Weighted Average**: Computes the final consensus plane from the remaining inliers.
|
||||
|
||||
3. **Correction Calculation**:
|
||||
- Computes a rigid transform $T_{corr}$ for each camera to align its detected floor to the consensus plane (or absolute Y=0).
|
||||
- **Constraints**:
|
||||
- **Rotation**: Corrects only pitch and roll to align the normal. Yaw is preserved.
|
||||
- **Translation**: Corrects only vertical height. X/Z positions are preserved.
|
||||
- **Consensus-Relative Correction**: By default, aligns cameras to the *consensus plane* to ensure relative consistency.
|
||||
- **Safety Bounds**: The correction is **rejected** if it exceeds safety limits (default: 5° rotation, 0.1m translation).
|
||||
|
||||
### 3. Observed Behavior & Tuning
|
||||
|
||||
**Real-World Performance:**
|
||||
- **Legacy/Unstable Behavior**: In early versions (before unit standardization), the system often reported 0 corrections or attempted extreme translations (>1m) due to mm/m confusion or depth noise.
|
||||
- **Hardened Behavior**: In validated runs, the system now applies small, precise corrections (e.g., max ~0.078m translation, < 1° rotation), effectively "snapping" the floor to a consistent level without disrupting the lateral calibration.
|
||||
|
||||
**Why No ICP?**
|
||||
Iterative Closest Point (ICP) is **not enabled** by default for ground plane alignment.
|
||||
- **Reason**: ICP on featureless planar surfaces is ill-constrained; it can "slide" along the floor, introducing drift in X/Z.
|
||||
- **Approach**: Plane-to-plane alignment is analytically exact for the vertical dimension and rotation, which are the only degrees of freedom we want to correct.
|
||||
|
||||
**When to Escalate:**
|
||||
If the ground plane refinement fails or produces large corrections (>5°), it usually indicates:
|
||||
1. **Poor Initial Calibration**: The ArUco markers were moved or poorly detected. Re-run `calibrate_extrinsics.py`.
|
||||
2. **Non-Planar Floor**: The floor has significant slopes or steps.
|
||||
3. **Obstacles**: Large objects are occluding the floor in the depth map.
|
||||
|
||||
Reference in New Issue
Block a user