fix(dc_measurements): retract the QR in-plane rotation limitation - #359
Merged
Minipada merged 2 commits intoAug 18, 2026
Merged
Conversation
Minipada
force-pushed
the
feature/297-zxing-c-fails-to-decode-some-qr-codes-ro
branch
from
August 18, 2026 07:59
1cb505e to
64774ef
Compare
Minipada
added a commit
that referenced
this pull request
Aug 18, 2026
…cally Two halves of the same gap, both found by #359's Format failure. CI ran prek over the whole tree on every PR, so a PR paid for files it never touched. It now runs `--from-ref origin/<base> --to-ref HEAD`, checking only what the PR changed; a push to jazzy still re-checks everything, so nothing a PR never touched can rot unnoticed. The checkout needs full history for the base ref to exist to diff against. Locally, `prek run --all-files` means all *tracked* files -- a new file that is not staged yet is skipped silently, which is exactly how #359's unformatted test file passed a local run and failed CI. CLAUDE.md's documented command stages first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L6PGKrx3v8rc8E1b6yrNpd Signed-off-by: David Bensoussan <d.bensoussan@proton.me>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## jazzy #359 +/- ##
=======================================
Coverage 67.20% 67.20%
=======================================
Files 96 96
Lines 5981 5981
=======================================
Hits 4019 4019
Misses 1962 1962
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
30-45 degrees in-plane. There is no such failure. The benchmark behind it rotated dc_simulation's demo texture inside the texture's own 290x365 bounds; the printed label offsets the 210 px code from the centre it turns about, so between 30 and 75 degrees a corner of the code -- finder pattern and all -- leaves the frame. A QR the frame has clipped is unreadable at any angle by any decoder. Confirmed against libzxing-dev 2.2.1-3, the version rosdep resolves on Noble/Jazzy, calling ZXing::ReadBarcodes the way camera.cpp does: fully framed, it decodes at every angle from 0 to 90 degrees; rotated inside the texture's bounds it misses at exactly the angles that clip a corner. The PyPI bindings at 2.3.0 and 3.1.1 behave identically, so there is nothing for a newer release to fix, and the rotation-retry mitigation the issue floated would not have worked -- re-rotating an image whose corner was cropped cannot put the pixels back. test_barcode_rotation locks both halves down: decoding at every 5 degrees when fully framed, and decoding iff all four module corners stay inside the frame when not, so the test pins the cause rather than the symptom. camera.md's warning about a library defect becomes an info block about the framing requirement that does matter. No change to camera.cpp: nothing to mitigate, so no new parameter and no per-frame cost. Closes #297 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L6PGKrx3v8rc8E1b6yrNpd Signed-off-by: David Bensoussan <d.bensoussan@proton.me>
…cally Two halves of the same gap, both found by #359's Format failure. CI ran prek over the whole tree on every PR, so a PR paid for files it never touched. It now runs `--from-ref origin/<base> --to-ref HEAD`, checking only what the PR changed; a push to jazzy still re-checks everything, so nothing a PR never touched can rot unnoticed. The checkout needs full history for the base ref to exist to diff against. Locally, `prek run --all-files` means all *tracked* files -- a new file that is not staged yet is skipped silently, which is exactly how #359's unformatted test file passed a local run and failed CI. CLAUDE.md's documented command stages first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L6PGKrx3v8rc8E1b6yrNpd Signed-off-by: David Bensoussan <d.bensoussan@proton.me>
Minipada
force-pushed
the
feature/297-zxing-c-fails-to-decode-some-qr-codes-ro
branch
from
August 18, 2026 08:35
1c42efe to
f75c6d8
Compare
Minipada
deleted the
feature/297-zxing-c-fails-to-decode-some-qr-codes-ro
branch
September 2, 2026 12:45
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
#297 asked three questions in order: does a newer ZXing-C++ fix the reported in-plane rotation failure, does it matter in practice, and if so is a bounded rotation-retry worth its per-frame cost.
The answers are no, no, and moot — the reported limitation does not exist. #123 and the
camera.mdwarning it left behind were both measuring the harness, not the library.What was actually happening
The benchmark rotated the demo texture inside its own 290x365 bounds.
qrcode_0001.png's module area is 210 px at (45, 100) — the printed label takes the rest of the height, so the code sits above the centre the rotation turns about. Swing that and a corner of the module area, finder pattern and all, leaves the frame.Forward-mapping the four module corners through the same
getRotationMatrix2Dthe harness used says exactly when:That is, to the angle, the reported pass/fail pattern. A QR the frame has cut a finder pattern off is unreadable at any angle by any decoder. The causes #297 ruled out — interpolation blur, module size, every
Binarizer,tryDownscale— were all ruled out correctly; the one variable nobody varied was the frame.Confirmed against the production library, not a binding
A standalone C++ program calling
ZXing::ReadBarcodesthe waycamera.cppdoes, compiled insidelocalhost/dc-workspace:latestagainst the exactlibzxing-dev 2.2.1-3thatrosdepresolves on Noble/Jazzy:The PyPI bindings at 2.3.0 and 3.1.1 give identical results in both columns. So there is nothing for a newer release to fix — no vendoring, no
rosdeppin — and the rotation-retry mitigation would not have worked anyway: re-rotating an image whose corner was already cropped cannot put the pixels back.What changed
dc_measurements/test/test_barcode_rotation.cpp(new) — two tests over the real reader, with nodc_simulationasset dependency; it reconstructs the texture's layout to the pixel with ZXing's own writer, the waytest_code_posealready does.DecodesACodeAtEveryInPlaneRotation— fully framed, decodes at every 5° from 0° to 90°. This is the assertion the retracted claim would fail.LosesACodeTheFrameClips— rotated inside the texture's own bounds, asserts decode succeeds iff all four module corners stay inside the frame, so the test pins the cause and not just the symptom.doc/src/dc/measurements/camera.md— the admonish block goes from awarningdescribing a library defect to aninfodescribing the framing requirement that actually matters: keep the whole code plus its quiet zone in the image, and in-plane angle is a non-issue. It also notesrotation_angleis unrelated, since whole quarter turns never crop. The perspective/tilt half of the Move QR/barcode detection to a more reliable C++ library (ZXing-C++) #123 comparison (100% vs. 0% forzbarat 35% skew) was independently measured and stands unchanged.camera.cpp— nothing to mitigate, so no new parameter and no per-frame cost.Verification
colcon build --packages-up-to dc_measurementsinlocalhost/dc-workspace:latestwith this worktree bind-mounted: clean.colcon test --packages-select dc_measurements --ctest-args -R "test_barcode_rotation |test_code_pose"→10 tests, 0 errors, 0 failures, 0 skipped(8 gtest cases across the two binaries plus their 2 ctest entries), againstlibzxing2.2.1.prek run --all-files --skip build-doc→ all 24 hooks pass, includingclang-formatand the REUSE licence check on the new file.Closes #297
🤖 Generated with Claude Code
https://claude.ai/code/session_01L6PGKrx3v8rc8E1b6yrNpd