Repository navigation
Stars: precession on by default, ledger re-solved; ellipsoidal bearings; landmark check - #16
Merged
Merged
Conversation
geom.bearing_deg was the spherical great-circle bearing evaluated at geodetic latitudes. The sphere gives a degree of latitude and a degree of longitude the same length and the ellipsoid does not (the ratio is about 1 - e^2 cos^2 lat), so on diagonal bearings it was off by up to 0.135 deg at 40-60 km across San Diego County. bearing_deg now takes the direction in the camera's local east-north-up frame from Earth-centred WGS84 coordinates, and a vectorised bearing_grid does the same for a ground grid. The spherical formula had been copied by hand into geolocate, accumulate and bias; those now call the shared functions. A test that placed a point exactly 45 deg off at the equator assumed the sphere; (1, 1) sits at 45.19 deg on the ellipsoid, so it steps north. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lved The star catalog held J2000 positions and the solver used them as if they were of date. By 2026 the sky has turned ~0.36 deg against them, and every star solve absorbed that into its pose: about -0.28 deg of azimuth on the four cameras of a whole-night study, and a residual that drifts across a night because a pose can absorb a fixed rotation but not one that changes with sidereal time. Skyfield (IAU 2000A, aberration) agrees with the precessed positions to 0.005 deg and with the J2000 ones only to 0.32 deg; that comparison is now a test. Catalog: bright_stars.json now carries a header -- frame (ICRS), equinox and epoch (2000.0) -- plus Hipparcos proper motions joined from HYG v3. catalog.py places a star through the chain the header implies: proper motion from the epoch, IAU 1976 precession from the equinox, alt/az, then refraction scaled for site elevation. Any other frame or equinox raises rather than mixing. MODEL switches each step (all on by default) and catalog.using() scopes a change to one block. Every solve records catalog.model_id(); pose_ledger entries carry it as sky_model and load() refuses a ledger that mixes models. stars/resolve_ledger.py re-solved the 86 ledger sequences with the solver each was accepted by (falling back to solve_wide where a grid solve fails, as vo-e-mobo-m needs). All 86 pass; d_az moved by a median of -0.21 deg (-0.04 to -0.32, less for older solves), star counts are unchanged and the median residual improved by 0.07 px. Whole-night tooling behind the study: nights.fetch_night and _N pseudo-sequences, collect() that can drop decoded frames and close lost tracks, solve windows, and a prune bar capped at 45 frames (unchanged for <= 90-frame blocks). stars/window_ablation.py and fig_window_ablation.py are the 600-solve study; its figure is docs/figures/star_window_ablation.jpg. With both terms on, a 15-minute window predicts the rest of the night about as well as the whole night does, except on north-facing cameras. Geolocation outputs have not been re-run against the new ledger. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…poses landmarks.py checks star-solved poses against objects located without the sky: FCC Antenna Structure Registration towers (4,518 within 80 km of an HPWREN site, 451 lit), the 73 HPWREN sites, and Lake Sutherland from OpenStreetMap (ODbL, attributed in the file). Directions are exact (ECEF -> local ENU, checked against Vincenty to 0.001 deg), line of sight runs through the DEM, and static lights are clustered from each night block's frames. Each block is solved under the pre-2026-09 model and with precession and refraction, and matched lights are scored under both. The result is inconclusive, and NOTES.md says why. Automatic matching picked up marine-layer texture, fire glow and antenna farms (per-match spread ~0.3 deg, the size of the effect). A hand review of 168 candidate crops kept 12 unambiguous lights (data/meta/landmarks_verified.json); their median azimuth residual is +0.11 deg under the old pose and -0.11 under the precessed one. That selection leans toward the precessed pose and site coordinates are not mast positions, so it cannot decide between them. The precession correction rests on the Skyfield comparison. The Lake Sutherland outline lands on the reservoir under both poses but cannot resolve their ~7 px difference. Co-Authored-By: Claude Opus 5.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.
Three commits. Each passes
pyteston its own.1. Bearings on the WGS84 ellipsoid (
6253b85)geom.bearing_degcomputed a spherical great-circle bearing at geodetic latitudes and was off by up to 0.135° on diagonal bearings at 40–60 km. It now uses the exact east-north-up direction, and a vectorisedbearing_griddoes the same for ground grids.geolocate,accumulateandbiaseach had their own copy of the sphere formula and now call these.2. Catalog-declared frame; precession on by default; ledger re-solved (
784c97f)bright_stars.jsonnow states its frame (ICRS), equinox and epoch (2000.0), and carries Hipparcos proper motions. The solver applies proper motion, precession and refraction as that header implies, and refuses any frame or equinox it can't handle.catalog.model_id(). Ledger entries carry it, andpose_ledger.loadrefuses a ledger that mixes models.stars/resolve_ledger.pyre-solved the same 86 sequences. All 86 still pass.d_azmoved by a median of −0.21° (range −0.04 to −0.32; older solves move less). Star counts are unchanged.stars/window_ablation.py) are included; the figure isdocs/figures/star_window_ablation.jpg. With both corrections on, a 15-minute window predicts the rest of the night about as well as the whole night does, except on north-facing cameras.3. Landmark check, inconclusive and documented (
1cd2a3b)NOTES.mdexplains why.Not in this PR: the README's geolocation numbers. They will move with the new ledger and the bearing fix, and will be re-run on
mainafter merge soruns.jsonlcites a merged commit.🤖 Generated with Claude Code