Hybrid alignment: SEP fallback serves in-progress alignments (stacked on #566) - #567
Draft
hjoungjoo wants to merge 6 commits into
Draft
Hybrid alignment: SEP fallback serves in-progress alignments (stacked on #566)#567hjoungjoo wants to merge 6 commits into
hjoungjoo wants to merge 6 commits into
Conversation
sep is the C Source Extractor library behind the SEP fallback detector (next commits). Optional at runtime: every import site degrades to the existing cedar-only behaviour when the module is missing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… mapping Two self-contained modules, no wiring yet: * sep_detect: detects stars on the UNCROPPED 12-bit raw frame -- 2x2 binning, sep mesh-background subtraction (removes light-pollution gradients / cloud glow that defeat a global threshold), matched-filter extraction, then field-measured quality gates: edge margin (vignette), saturation guard, point-source shape gate (semi-major axis / npix; cloud texture is extended, stars are compact), isolation gate (sep deblends bright cloud edges into tight clumps; real stars at this plate scale measured zero neighbours within 50 px), and an optional static warm-pixel mask (single-pixel sensor defects dominated empty-sky counts in field data). * solver_frame_map: maps between the production rotated-512 solver frame and the rotated full-sensor frame. Because the crop is centred and the resize isotropic, target_pixel mapping reduces to a scale about the frame centre. Rotation conventions are pinned by tests against PIL Image.rotate; the stage-5 rule reads camera_interface's SCREEN_ROTATE_AMOUNTS as its single source. sep stays optional: detect_stars returns None when the module is missing, callers degrade to cedar-only behaviour. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
sep_warm_map builds the static warm-pixel map sep_detect masks with: same-channel neighbour excess recurring at a fixed position across many dark frames (stars move with the sky, defects do not). Thresholds were validated on a field corpus: the map covered every recurring empty-sky detection cell while masking ~0.14% of the frame. The equivalence test projects tetra3's own catalog stars onto a synthetic full sensor and solves the same sky through both paths (production crop-512 vs rotated full frame); Roll must agree to 0.05 deg and camera/aligned pointing to a fit residual -- the proof that detecting on a different frame cannot disturb tracking or push-to. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…g-gated) When solver_shadow_detect or solver_sep_fallback is enabled, the Pi camera publishes each exposure's UNCROPPED raw mosaic (profile rotation applied, crop skipped) alongside the existing cropped cam_raw, with the frame's actual exposure/gain metadata. The solver-side SEP path detects on this frame; the production 512 pipeline is untouched. Both keys default to off, in which case no extra copy or publish happens -- captures are byte-for-byte the current behaviour. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…iled solves The production path is unchanged and keeps priority: every attempt still runs cedar-detect on the processed 512 frame first. When that solve fails and the SEP full-frame detector found enough stars (>= 5), the attempt is rescued by solving the SEP centroids in the rotated full frame; the solution carries production 512-frame semantics (Roll, target_pixel pointing) via solver_frame_map, so the pointing chain downstream cannot tell which detector solved. Extras: * Exponential backoff on failed rescues (a failed fallback burns up to solve_timeout of CPU; indoors/thick cloud would pay it every attempt), re-armed instantly when the SEP count jumps 1.5x -- a cloud gap opening on stars is never delayed. * Shadow CSV (solver_shadow_detect): one row per attempt comparing both detectors, for offline A/B without affecting the solve. * In-progress alignments are excluded from the rescue: alignment resolves through the production frame only (a follow-up PR maps the alignment coordinate through the SEP frame as well). Both config keys default to off; with them off no SEP code runs and no full frame is published. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…gnments Lifts the alignment exclusion from the SEP rescue: when an alignment is pending and the production (cedar) solve cannot complete -- exactly the sky this path exists for -- the SEP solve now resolves the alignment coordinate. tetra3 answers target_sky_coord in the rotated full-frame canvas; the y/x_target it returns is mapped back into rotated-512 space (map_frame_pixel_to_target, the inverse of the proven centre-scale relation), so the downstream alignment chain (AlignedResult, persisted target_pixel) consumes it unchanged and cannot tell which detector served it. The equivalence test extends to the alignment direction: solving the same target_sky_coord through both paths must land on the same 512-space pixel within 1 px. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Stacked on #566 — this branch is #566 plus one commit; only the last commit (
feat(solver): hybrid alignment) is new here. Review #566 first; this PR will rebase to a one-commit diff once it lands.What this adds
#566 deliberately excludes in-progress alignments from the SEP rescue: alignment resolves through the production frame only. But the sky where the rescue matters is exactly the sky where cedar cannot complete an alignment at all — under heavy light pollution, a user cannot align, which blocks push-to entirely.
This PR lifts that exclusion:
target_sky_coord.y/x_targetin the rotated full-frame canvas;map_frame_pixel_to_target(the exact inverse of the centre-scale relation Hybrid solving: SEP full-frame rescue when cedar-detect finds no stars (light-polluted skies) #566's equivalence test proves) maps it back into rotated-512 space.AlignedResult, persistedtarget_pixel) consumes the result unchanged — it cannot tell which detector served the alignment.Cedar keeps absolute priority: this path only runs on attempts where the production solve already failed.
Proof
The solve-equivalence test extends to the alignment direction: solving the same
target_sky_coordthrough the production 512 path and the SEP full-frame path must land on the same 512-space target pixel within 1 px (~84″ at this plate scale). Verified against tetra3's own catalog stars projected onto a synthetic sensor.Field: alignment through the SEP path was confirmed working on the fielded imx462 device under a light-polluted Seoul sky (2026-07-28 session — the first time alignment succeeded at all under that sky). Precision validation on a real telescope + push-to chain is listed as remaining work in the field notes.
Testing
pytest -m unit --ignore=tests/websiteandpytest -m smokegreen on this branch (same environment note as Hybrid solving: SEP full-frame rescue when cedar-detect finds no stars (light-polluted skies) #566 for the one cedar-shmem test).ruff/mypyclean on touched files.🤖 Generated with Claude Code