fix: align calibration convention metadata and remove conversion path

This commit is contained in:
2026-02-09 04:24:09 +00:00
parent 136dadb31d
commit 287773e7e7
5 changed files with 103 additions and 45 deletions
+63 -1
View File
@@ -28,6 +28,18 @@ problem caused by trying to make Plotly (which defaults to Y-up) display OpenCV
---
## Current Policy Checklist (2026-02-09)
For engineers maintaining or using these tools:
- [x] **`calibrate_extrinsics.py`**: Outputs `T_world_from_cam` (OpenCV). Auto-aligns to **Y-down** (gravity along +Y). Writes `_meta` block.
- [x] **`visualize_extrinsics.py`**: Renders raw JSON data. Ignores `_meta`. Sets view camera up to `-Y`.
- [x] **`apply_calibration_to_fusion_config.py`**: Direct pose copy only. No `--cv-to-opengl` conversion.
- [x] **`compare_pose_sets.py`**: Symmetric inputs (`--pose-a-json`, `--pose-b-json`). Heuristic parsing.
- [x] **Conventions**: Always OpenCV frame (+X Right, +Y Down, +Z Forward). Units in meters.
---
## Ground Truth Conventions
### 1. Calibration Output: `world_from_cam`
@@ -65,7 +77,40 @@ Every camera's local frame follows the OpenCV pinhole convention:
The frustum is drawn along the camera's local +Z axis. The four corners of the
frustum's far plane are at `(±w, ±h, frustum_scale)` in camera-local coordinates.
### 3. Plotly Scene/Camera Interpretation Pitfalls
### 3. Metadata & Auto-Alignment (`_meta`)
`calibrate_extrinsics.py` now writes a `_meta` key to the output JSON. This metadata
describes the conventions used but is **optional** for consumers (like the visualizer)
which may ignore it.
```json
{
"_meta": {
"pose_convention": "world_from_cam",
"frame_convention": "opencv",
"auto_aligned": true,
"gravity_direction_world": [0.0, 1.0, 0.0],
"alignment": { ... }
},
"SN123": { ... }
}
```
- `pose_convention`: Always `world_from_cam`.
- `frame_convention`: Always `opencv` (+X Right, +Y Down, +Z Forward).
- `auto_aligned`: `true` if `--auto-align` was used.
- `gravity_direction_world`: The vector in world space that points "down" (gravity).
- For **Y-down** (current default), this is `[0, 1, 0]`.
- For **Y-up** (legacy/Fusion), this would be `[0, -1, 0]`.
**Auto-Alignment Target**:
The `--auto-align` flag now targets a **Y-down** world frame by default (`target_axis=[0, -1, 0]`
in internal logic, resulting in gravity pointing +Y).
- **Old behavior**: Targeted Y-up (gravity along -Y).
- **New behavior**: Targets Y-down (gravity along +Y) to match the OpenCV camera frame convention.
- **Result**: The ground plane is still XZ, but "up" is -Y and "down" is +Y.
### 4. Plotly Scene/Camera Interpretation Pitfalls
Plotly's 3D scene has its own camera model that controls **how you view** the data:
@@ -148,6 +193,23 @@ reference. All commits are on `visualize_extrinsics.py`.
---
## Known Pitfalls & Common Confusions
1. **Y-Up vs Y-Down**:
- **OpenCV/ArUco**: Y is **Down**. Gravity is `[0, 1, 0]`.
- **OpenGL/Fusion**: Y is **Up**. Gravity is `[0, -1, 0]`.
- **Pitfall**: Assuming "Y is vertical" is ambiguous. You must know the sign.
2. **Frame Mismatch vs Origin Mismatch**:
- Two pose sets can have the **same convention** (e.g., both Y-down) but different **world origins** (e.g., one at marker, one at camera 1).
- **Fix**: Use `compare_pose_sets.py` to align them rigidly before comparing errors.
3. **Visualizer "Inversion"**:
- The visualizer sets `camera.up = {y:-1}`. This makes the scene look "normal" (floor at bottom) even though the data is Y-down.
- **Pitfall**: Don't try to "fix" the data to match the view. The view is already compensating for the data.
---
## Canonical Rules Going Forward
1. **Single convention**: All visualization data is in OpenCV frame. No basis switching.