Skip to content

Stars: precession on by default, ledger re-solved; ellipsoidal bearings; landmark check - #16

Merged
rharnish merged 3 commits into
mainfrom
star-sky-model
Sep 25, 2026
Merged

rharnish merged 3 commits into
mainfrom
star-sky-model

Conversation

@rharnish

Copy link
Copy Markdown
Owner

Three commits. Each passes pytest on its own.

1. Bearings on the WGS84 ellipsoid (6253b85)
geom.bearing_deg computed 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 vectorised bearing_grid does the same for ground grids. geolocate, accumulate and bias each had their own copy of the sphere formula and now call these.

2. Catalog-declared frame; precession on by default; ledger re-solved (784c97f)

  • The bug: the catalog's J2000 positions were used as if they were of date. By 2026 that is ~0.36° of sky rotation. Each solve absorbed it into its pose: about −0.28° of azimuth, plus a residual that drifts over the night.
  • Independent check: Skyfield agrees with the precessed positions to 0.005° and with the old ones only to 0.32°. This comparison is now a test.
  • Catalog header: bright_stars.json now 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.
  • Recorded sky model: every solve records catalog.model_id(). Ledger entries carry it, and pose_ledger.load refuses a ledger that mixes models.
  • Ledger: stars/resolve_ledger.py re-solved the same 86 sequences. All 86 still pass. d_az moved by a median of −0.21° (range −0.04 to −0.32; older solves move less). Star counts are unchanged.
  • Whole-night study: the tooling and the 600-solve window study (stars/window_ablation.py) are included; the figure is docs/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)

  • What it checks: FCC-registered towers, HPWREN sites and Lake Sutherland, tested against the star poses with exact geometry and a line-of-sight check through the terrain model.
  • Automatic matching picked up marine-layer texture and fire glow instead of tower lights.
  • Hand review: 12 unambiguous lights. They show a median azimuth residual of +0.11° under the old pose and −0.11° under the new one.
  • Why that doesn't decide it: the review leaned toward the new pose, and site coordinates aren't mast positions.
  • So the precession correction rests on the Skyfield comparison, not on these landmarks. NOTES.md explains 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 main after merge so runs.jsonl cites a merged commit.

🤖 Generated with Claude Code

rharnish and others added 3 commits September 24, 2026 22:58
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>
@rharnish
rharnish merged commit d9fd5ad into main Sep 25, 2026
1 check passed
@rharnish
rharnish deleted the star-sky-model branch September 25, 2026 07:00
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.

1 participant