Skip to content

fix(motion): validate homography and renormalize the accumulator - #560

Draft
AlexBodner wants to merge 1 commit into
developfrom
fix/motion-homography-validation
Draft

fix(motion): validate homography and renormalize the accumulator#560
AlexBodner wants to merge 1 commit into
developfrom
fix/motion-homography-validation

Conversation

@AlexBodner

Copy link
Copy Markdown
Collaborator

Problem

Two defects that compound into a permanently broken world frame.

HomographyTransformation.__init__ inverts the matrix with no guard, so a singular or non-finite matrix surfaces a bare LinAlgError from inside numpy, even though the class already validates shape with a clear ValueError.

MotionEstimator._estimate_homography accumulates H_current @ H_total without renormalizing. The projective scale compounds every frame and drifts toward a degenerate matrix. Worse, the accumulator is assigned before the transformation is constructed, so once a bad matrix lands there it is never cleared and every later frame inherits it.

Fix

  • HomographyTransformation raises ValueError for non-finite and singular matrices, so the class has one documented failure mode.
  • The accumulated scale is pinned back to 1 after each accumulation, keeping the accumulator bounded over long sequences.
  • The accumulator is only committed once the matrix proves invertible. If it does not, the world frame is re-baselined with a warning instead of raising mid-sequence.

Tests

Adds tests/motion/test_transformation.py — the module had no coverage at all.

  • Singular (all-zero, rank-one, duplicate-row) and non-finite (NaN, inf) matrices raise ValueError.
  • Round-trip and identity behaviour is pinned.
  • Accumulating from a non-unit scale renormalizes to 1 (stayed at 4.0 before the change).
  • A degenerate accumulator re-baselines to identity (raised LinAlgError before the change).

tests/motion and tests/utils pass at 288.

Notes

The estimator swallows the ValueError and re-baselines rather than propagating, because tracking should survive a bad frame. The public constructor still raises, which is what a direct caller wants.

Made with Cursor

Two defects that compound into a permanently broken world frame:

`HomographyTransformation.__init__` inverted the matrix with no guard, so
a singular or non-finite matrix surfaced a bare `LinAlgError` from deep
inside numpy. It now raises `ValueError` like the existing shape check,
so the class has one documented failure mode.

`MotionEstimator._estimate_homography` accumulated `H_current @ H_total`
without renormalizing, so the projective scale compounded every frame and
drifted toward a degenerate matrix. It also assigned the accumulator
before constructing the transformation, so once a bad matrix landed there
it was never cleared and every later frame inherited it.

The scale is now pinned back to 1 after each accumulation, and the
accumulator is only committed once the matrix proves invertible; if it
does not, the world frame is re-baselined with a warning instead of
raising mid-sequence.

Adds tests/motion/test_transformation.py, which had no coverage.

Co-authored-by: Cursor <cursoragent@cursor.com>
@Borda
Borda requested a balanced review from Copilot August 12, 2026 18:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Improves homography validation and prevents invalid motion accumulation from permanently corrupting the world frame.

Changes:

  • Validates finite and invertible homography matrices.
  • Renormalizes accumulated homographies and re-baselines invalid state.
  • Adds transformation and estimator regression tests.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/trackers/motion/transformation.py Adds homography validation.
src/trackers/motion/estimator.py Normalizes and safely commits accumulated motion.
tests/motion/test_transformation.py Tests transformation behavior and validation.
tests/motion/test_estimator.py Tests normalization and recovery.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +253 to +255
scale = accumulated_homography[2, 2]
if np.isfinite(scale) and abs(scale) >= _MIN_HOMOGRAPHY_SCALE:
accumulated_homography = accumulated_homography / scale
Comment on lines +108 to +113
try:
self.inverse_homography_matrix = np.linalg.inv(self.homography_matrix)
except np.linalg.LinAlgError as error:
raise ValueError(
f"Homography matrix is singular and cannot be inverted, got:\n{self.homography_matrix}"
) from error
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants