Skip to content

fix: estimatePose misaligned ids and corners when other markers are in view - #116

Merged
petercorke merged 2 commits into
mainfrom
fix/fiducial-estimatepose-id-corner-alignment
Oct 3, 2026
Merged

petercorke merged 2 commits into
mainfrom
fix/fiducial-estimatepose-id-corner-alignment

Conversation

@petercorke

Copy link
Copy Markdown
Owner

Summary

Closes #52.

FiducialCollection.estimatePose() filtered markers by board ID with:

cornerss = [... for corners, id in zip(cornerss, ids) if id in self._ids]
ids = [id for corners, id in zip(cornerss, ids) if id in self._ids]   # cornerss is already filtered!

The second zip pairs the already-filtered corners with the original ids. As soon as a marker not on this board was detected before one that is (exactly the multi-board case the docstring advertises), the lists went out of step. Now each marker's corners and id are filtered together in one pass.

Also raises the documented ValueError when no marker on this board is detected; previously that case gave a TypeError (ids is None) or a raw cv2.error.

Tests

The existing test_estimatePose only exercises Image.fiducial(); FiducialCollection.estimatePose() had no coverage. Two new tests:

  • test_board_estimatePose_ignores_other_markers: a 2x2 board plus two larger extraneous markers (OpenCV returns detections largest-first, so these arrive before the board's markers, which is the order that exposes the bug). Asserts only the board's ids are reported, the pose and RMSE equal the board-only reference, and each id keeps its own corners.
  • test_board_estimatePose_no_board_markers: ValueError for a scene containing only other markers, and for a blank scene.

Verification

Clean isolated venvs, Python 3.12, OpenCV 4.14.0 and 5.0.0:

  • Both new tests fail before the fix (raw cv2.error from aruco_board.cpp) and pass after, on both versions.
  • tests/test_image_fiducials.py: 9 passed on both.
  • Full suite: 945 passed / 94 skipped (OpenCV 4), 944 passed / 95 skipped (OpenCV 5); the skips are open3d and ros-extra tests that aren't installed in those venvs.

Note: I could only provoke a crash, not a silent misalignment, because OpenCV rejects the length mismatch. The per-id corner comparison in the test would also catch a silent one.

Checklist

  • PR title follows Conventional Commits
  • Tests pass locally
  • Added/updated tests for this change
  • CI green

🤖 Generated with Claude Code

The ID filter zipped the already-filtered corners list against the original,
unfiltered ids, so as soon as a marker not on the board was detected before
one that was, the two lists got out of step (OpenCV then failed in
aruco_board.cpp with a corners/ids length mismatch). Filter each marker's
corners and id together in a single pass.

Also raise the documented ValueError when no marker on this board is
detected, instead of a TypeError (ids is None) or a raw cv2.error.

Adds the first test coverage of FiducialCollection.estimatePose(): the
existing test_estimatePose exercises Image.fiducial() only.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 9 complexity · 2 duplication

Metric Results
Complexity 9
Duplication 2

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@petercorke
petercorke merged commit 43c5980 into main Oct 3, 2026
37 checks passed
@petercorke
petercorke deleted the fix/fiducial-estimatepose-id-corner-alignment branch October 3, 2026 20:33
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.

FiducialCollection.estimatePose: ids/cornerss zip misaligns after ID filtering

1 participant