Legacy DLT
On prod today, extrinsics are often still produced with calibrate.py: click image pixels, enter matching LiDAR , solve a free 3×4 projection matrix by Direct Linear Transform (DLT), write projection_matrix_{l|r}.
For each correspondence , the homogeneous model rearranges into two linear rows in the 12 unknowns of :
Stack ≥6 point pairs (the script asks for more; default minimum is 10), take the SVD of the design matrix, and reshape the singular vector for the smallest singular value into . Hartley normalization helpers exist in the file but are commented out in the current solve path.
Unlike the feature-branch path, this is not forced to equal for a particular . The free can absorb extrinsic error, residual distortion, and click noise in one matrix.
Post-solve adjuster
Section titled “Post-solve adjuster”dlt_proj_adjuster.py fine-tunes an existing :
- Rotation: right-multiply the left 3×3 block: , so the delta acts on incoming LiDAR points.
- Pixel shift: add to row 0 and to row 1. Because , that yields a depth-independent pixel offset (same for ).
Runs after calibrate.py for small rotation and pixel-offset corrections.
Comparison
Section titled “Comparison”Click DLT (calibrate.py) | Multi-pose board (calibrate_extrinsics.py) | |
|---|---|---|
| Status | Common on prod | feature/perc/physical-calibration |
| Inputs | Manual 3D–2D pairs | Synced images + dense /lidar_points |
| Model | Free | |
| Failure mode | Bad clicks / sparse geometry | Bad planes, labeling consensus, observability |
Feature-branch math: extrinsics, projection.
