The Overnight Boresight
On the morning of 2026-09-06 an operator opened huntingtonlake-cam01 and the ridge lines floated a finger's width above the mountains. The night before, a pipeline had "calibrated" that camera from a week of its own frames, and the numbers it produced looked excellent: 92 % of skyline columns agreeing, a spread of a tenth of a degree. The picture said otherwise.


Same camera, same night, same solve. Left: the render was drawn on a frame whose recorded tilt was 0.0° — a pano-sweep transit — while the camera was really at 2.88°. Right: the held view. The solve was right; the frame was a lie.
This page is the story of how the pipeline learned to tell those apart, and what a result has to survive before it can touch an operator's screen. If the ray cast itself is new to you, start with Boresight by Raycast; the runtime auto-align in the browser is told in The Peak Finder Overlay, and this is its offline, fleet-wide sibling.
Chapter 1 · One pan, one night
Start with the smallest thing that works. Take one camera, one pan it held all week, and a handful of its frames. Find the skyline in each photo, compute where the terrain model puts that ridge for the camera's recorded pose, and the constant vertical gap between the two is the mount's . Wide zoom only, daylight only, and only skyline columns whose terrain is at least 8 km away, because a near ridge carries tree canopy the model doesn't know about.
That is the whole solver in one sentence, and on a clear day it works to a few hundredths of a degree. Everything after this chapter is about the days that are not clear, and the frames that are not what they claim to be.
Chapter 2 · A week of frames beats two
The first version took the two newest frames of each pan. Then it got a week of history and the results got worse, because "newest" meant late afternoon, and late afternoon over a valley means haze. The detector finds an edge on the top of a haze band just as happily as on a ridge, and a solve on that edge moves the ridge line a full degree.
Two things fixed it. The edge now has to be a real step in brightness: on boucher-cam08 ridges measure 70–110 on the 0–255 scale, haze tops 17–23, and anything under 28 is refused. And a pan is solved from every clear frame of the week, up to twelve spread across days, with the fit seeing per column the frame whose residual is the across them.
The two newest frames are both haze, so their answer is the haze band. The per-column median still sees 10 clear frames out of 12 and lands on the terrain.
What you just felt: a minority of bad frames cannot move a median, and a majority can — which is exactly why the contrast gate throws haze out before the median, not instead of it.
Time-ordering is a quality filter in disguise. Whatever the air does at the end of the day is what "newest" selects. Spread candidates across days, then rank by clarity.
Chapter 3 · A pose is a pan and a tilt
Back to the opening picture. An external system sweeps every camera through six fixed positions at tilt 0 every few minutes for its panorama. Each position is visited for exactly one frame, and on the way back the metadata records the destination tilt before the camera has arrived. huntingtonlake's week had 19,873 frames; about 9,000 were those. One of them landed within a degree of the working pan, carried tilt 0.0 against the real 2.88°, was the clearest frame at that pan, and became the render. A lone sweep frame at pan 210 solved cleanly on its own and put a +2.15° row and a −2.48° azimuth offset into the fleet.
So a pose is a pan and a tilt and a zoom. Within a pan, only the largest tilt/zoom group — the held view — is solved. A pose needs at least two frames, because one frame cannot be checked against anything. And after the fit, a frame whose own residual sits more than half a degree from its pose's is dropped and the pose refit. The frames endpoint that feeds the solver drops single-frame visits before any of this, the same dwell rule the timelapse has always used.
pan 144.1 · tilt −0.3 · zoom 1 (FOV 65°) · 10 frames at this pose · edge contrast 75 · residual centre +0.02°
Chapter 4 · The working view must solve
A camera's table of corrections is only as good as its coverage. A tilted base makes pitch and roll change with pan, so the solver publishes a row per solved pan and the overlay interpolates between rows less than 60° apart. The failure that bit boucher-cam08 was a table built entirely from excursion pans while the pan operators actually use had failed on haze: the overlay applied the nearest excursion row, 26° away and itself wrong, to the working view.
Two rules close that. The solver refuses to publish unless the camera's most-visited pan is among the solved pans, with the failing pan's reason in the report. And the overlay trusts a table row only within 30° of the current pan; beyond that it falls back down the precedence ladder to a manual, runtime or seeded value rather than guess from a distant row.
Chapter 5 · Nobody's overlay changes until a human says so
The solver never writes the fleet store. Each solved camera is submitted to the Admin API as a candidate with every pan's numbers, the frames it used and one render per solved pan — red for the photo skyline, grey for the ridge at the encoder pose, green for the ridge with the proposed correction. A reviewer approves when green sits on red across the whole frame; approval writes the fleet entry as an offline solve, which outranks manual and runtime ones.


What a reviewer sees. Grey is how far off the overlay is today; green is the proposal. Both are approvals.
The queue only holds decisions worth making. A result that merely reproduces the approved entry is counted as a confirmation; one that is clearly weaker is dropped; a rejected answer that comes back unchanged stays rejected; anything else that differs goes to the reviewer, who can approve or reject in bulk.
approved · MAD 0.141° · 365 inliers · pans 24, 54, 144, 170MAD 0.144° · 459 inliers · pans 24, 54, 144 · pan-170 row gone, others within 0.05°The first intake rule required a lower MAD or a new pan. boucher-cam08's cleaner solve — one haze row gone, more inliers — lost on a 0.003° MAD tie and was discarded. Only clearly weaker results are dropped now; equal quality that disagrees is precisely what a reviewer should see.
The evidence
Every solver change is run on the same twelve prd cameras against approved values and shipped seeds before it ships. After the changes above:
| Camera | Solver | Reference |
|---|---|---|
| boucher-cam01 | −0.59° | −0.58° |
| boucher-cam02 | +0.58° | +0.62° |
| magicmountain-cam02 | +1.52° / 0.97° | +1.52° / 0.96° |
| rechepeak-cam01 | +0.65° | +0.67° |
| breckenridgepeak-cam01 | −1.74° | −1.75° |
| bealville-cam02 | +1.54° / 1.11° | +1.56° / 1.10° |
Working-view pitch, and roll where fitted. huntingtonlake's bogus row and azimuth are refused; mebane, condorridge and sawmillkern are rejected with reasons (haze, a far skyline too narrow) rather than guessed.
Wrapping up
A boresight is a measurement, and a measurement is only as good as the frames behind it: which ones you let in, how many you use, and whether the pose they claim is the pose they were taken at. The pipeline's job is to be suspicious on your behalf — of haze, of sweep frames, of lone frames, of pans that solved while the working view did not — and then to show a person its evidence and wait. Read next: the engineer's reference for the render contract and every error source, in Aligning PeakFinder to a Photograph.