Skip to content

Pose rotation-error tail — lessons

Status: RESOLVED for single-frame — model-edge pose refinement shipped in v0.7.0 (high_accuracy); corner-level levers remain trade-bound. Last updated: 2026-07-19 Owning code: crates/locus-core/src/model_edge.rs and the pose LM stack (pose.rs / pose_weighted.rs).

TL;DR

The residual rotation-p99 tail on high_accuracy Accurate-mode pose (≈0.60° at 1080p) was first read as a physical law — the IPPE planar-pose ambiguity that any 4-corner PnP inherits. That belief was refuted: the tail is not physics but corner localization, and it concentrates in a handful of scenes (removing the worst 2 tags already hits the target). We then chased it at the corner level — GWLF/apriltag-edge refit, per-corner repair, per-tag switching (even an oracle), and internal fusion — and every one proved trade-bound: rotation improved only by adopting a common-mode corner profile that structurally regressed translation (e.g. GWLF: rot p99 0.600°→0.398° but trans p99 18.6→63.0 mm). The reframe that finally won was to stop reshaping the same 4 corners and add independent information: refine the 6-DoF pose against the decoded tag's ~40 internal bit-grid edges. That over-constrains rotation without disturbing corner-anchored translation, cutting rot p99 47–76% across resolutions (1080p 0.600°→0.249°, under OpenCV apriltag's 0.376°) at Locus's best-in-class translation. It shipped on by default in high_accuracy in v0.7.0.

The saga (what was hypothesized, tried, and concluded)

# Hypothesis Test Verdict Evidence
1 The rot-p99 tail is a physical law — IPPE planar-pose ambiguity intrinsic to any 4-point PnP; not fixable single-frame. Phase-0 diagnostic forensics on locus_v1_tag36h11_1920x1080 (50 scenes), high_accuracy + Accurate. Refuted. The tail is a small set of outlier scenes, not a distribution-wide physics floor; substituting good corners collapses the error. Phase-0: rot p50 0.057° / p95 0.473° / p99 0.771°; tail carried by ~2 scenes (scene_0008 0.87°, scene_0005 0.66°). Corpus-relative reclassification found corner_geometry_outlier / ppm_starved / sigma_miscalibration modes — corner-localization and calibration, not an irreducible ambiguity.
2 Reframe: the tail is corner localization — a few EdLines Phase-1 arc-partition gross failures, correctable by better sub-pixel corners. Sort shipped rot errors, drop worst-k tags; corner-error decomposition vs GT. Confirmed as diagnosis. Removing the worst 2 tags lands at the apriltag target (p99 0.600°→0.384°); p95 (0.385°) is already competitive. The gap is a handful of gross corner failures (tag 563 / scene_0008: one corner 3.83 px off), not the other 47 tags. refine_variants_20260714.md Result 2.
3 Corner-level refit (GWLF = apriltag-style gradient-weighted edge-line fit → intersect) closes rotation. Route high_accuracy large markers through GWLF; measure rot/trans vs shipped EdLines. Trade-bound. Rotation nearly reaches target but translation regresses 3.4× (49/50 tags worse). GWLF corners are ~3× worse in absolute position (mean RMSE 0.63 vs 0.21 px — the ~0.6 px edge-line floor on Blender PSF) but more consistent; consistency pulls rotation in, absolute error inflates translation. rot p99 0.600°→0.398°, trans p99 18.6→63.0 mm. refine_variants_20260714.md Result 1. Not shipped.
4 Selectively repair only failing corners (EdgeLineGated: snap to GWLF only when they disagree past a gate). Prototype CornerRefinementMode::EdgeLineGated, gate τ=1.5. Falsified. Gating (0.70°) beats no-handling (0.77°) but loses to the shipped outlier_drop (0.60°) — dropping a catastrophic corner beats correcting it to the 0.6 px floor — and neutralises outlier_drop. Reverted; no dead knob shipped. refine_variants_20260714.md Result 3.
5 Per-corner repair / per-tag switch / internal fusion can be steered to a Pareto win. Swap-worst-only; greedy per-tag GWLF switch (oracle); per-corner median of {EdLines, GWLF, ContourRdp+Erf}. Falsified — trade is fundamental at the per-tag level. One-corner swap is worse than all-four (you can't mix corner systems). Oracle per-tag switch reaches rot p99 0.377° only at trans p99 26.4 mm (+42%), and switch-worthy vs not overlaps fully (undetectable). Fusion drags to the offset cluster: trans p99 19.9→34.3 mm. refine_variants_20260714.md Result 4. Corner-refinement level exhausted; only remaining win = add independent information.
6 Phase C.5 post-decode re-refit (re-fit the 4 outer edges, intersect, re-solve homography) improves accuracy. Optional stage behind decoder.post_decode_refinement. Superseded. Real but marginal: means improve uniformly (ICRA RMSE −5.1%, render-tag −0.3…−0.7%) but p99 rotation stays within sub-1% noise — it does not close the tail. Also learned: writing the optimistic CRB covariance regressed render-tag p99 rotation 3–5%, so the covariance column is deliberately preserved. Same edge-intersection floor as GWLF; only touches the 4 outer edges. post_decode_refinement_20260426.
7 Add information: model-edge pose refinement — refine 6-DoF pose against the decoded tag's ~40 internal bit-grid edges, not just 4 corners. Opt-in Accurate-mode stage (model_edge.rs): measure→fit Nielsen-LM against 50%-intensity edge crossings under Huber δ=0.5 px + 7 samples/boundary; re-anchor translation to the 4 trusted corners; no-worse + χ² gates. WON — shipped v0.7.0. Over-constrains rotation from the interior without disturbing corner-anchored translation. Rot p99 −47…−76% at every resolution; reprojection RMSE falls everywhere; recall/precision 100%/100%; corner RMSE unchanged by construction. model_edge_refinement_20260715.md. 1080p rot p99 0.600°→0.249° (p95 0.385°→0.180°), under OpenCV apriltag's 0.376°, at trans p99 ~20 mm vs apriltag ~55 mm. Larger win on degraded imagery (p99 −56…−84%). On by default in high_accuracy; left off in standard (no χ² gate there → tail would drift).

Durable conclusion

Every "reshape the same 4 corners" lever is trade-bound because a corner-refinement method has a fixed error profile: you can trade Locus's low-absolute-error/high-variance EdLines corners for apriltag/GWLF's high-absolute-error/low-variance corners, buying rotation consistency at the cost of translation bias — but you cannot escape the frontier, because rotation and translation are read off the same four observations. The only way to improve both at once is to add observations the corners don't carry. Model-edge refinement does exactly that: the decoded interior pattern supplies ~40 independent, interior-distributed edge constraints that pin orientation an order of magnitude better than 4 corners, while translation stays anchored to the trusted corners. Adding information beat reshaping information.

Still open / re-attempt only if

  • Corner-level refinement remains exhausted / trade-bound — do not re-attempt GWLF replacement, per-corner gated repair, per-tag switching, or internal corner fusion without new evidence; all are empirically falsified (see MEMORY anti-patterns and refine_variants_20260714.md).
  • Translation carries a bounded, gated trade in the model-edge stage — concentrated in t p95 at high resolution (1080p +1.1 mm, 2160p +4.9 mm) where a large rotation correction pulls the corner-anchored translation. Gated and opt-in; revisit only if a real-camera regression appears.
  • Multi-tag and temporal levers are not yet pursued — board joint-solve and multi-frame/SE(3) fusion are the next "add-info" tier above single-tag corner refinement; open for the residual t-p95 trade and for standard's gross-outlier tail.
  • standard tail is unaddressed — enabling model-edge there needs the full package (edge refinement + χ² consistency gate + outlier-drop) plus its own recall/precision benchmark (ICRA included); deferred past v0.7.0. standard's real gap is the absent pose gates, not corner refinement.
  • Absolute-unit constants (Huber δ, NielsenConfig::POSE grad_tol/damping_floor) are tuned on synthetic Blender data — make them scale-relative first if real-camera data ever shows a regression.

Live references (not superseded)

Provenance

Distilled 2026-07-19 from (removed; see git history): rotation_tail_diagnostic_phase0_20260502, rotation_tail_diagnostic_phase0_20260503, post_decode_refinement_20260426. Related: MEMORY anti-patterns on rotation-tail levers.