“Not all who wander are lost”

Can a UAV learn a city by heart — no GPS, no map on board, just a $4 flight computer?

The bottom line

Yes! We found a special-purpose neural memory architecture that ‘remembers’ an exact geo-location, given an in-flight daytime picture of Berlin. No GPS, no internet, no map on board, just a 3.1 MB file of weights. It works on 96.5% of camera frames, and it took 81 experiments and $364 to find.

96%of camera frames give a usable position fix 0% — never50%100% — every frame

confident and within 100 m. The loop minimises the mission penalty: 0.040 = 4% no fix + 0.5% wrong fix — a confident error counts double.

5research eras
81experiments
$364.64total cost
Download the Berlin model ↓ berlin.onnx · 3.1 MB · one function: estimate_position(frame) → (lat, lon, confidence)
What we tried

We tried: ImageNet-pretrained backbones, separate day and night specialists behind a dispatcher, contrastive pretraining on the imagery itself, retrieval against a stored fingerprint of the city, dense per-patch coordinate voting, learned relighting, calibrated abstention, and more.

Our first 76 experiments failed. Hard. The flaw was the harness itself; fixing it unlocked the ‘memory-in-weights’ architecture.

1

The question

One frame, no map, no internet — and it has to know when it doesn’t know.

A UAV flies over a city it has trained on. Its camera takes one picture straight down. From that picture alone: where is it?

And — how much should the aircraft trust the answer? A wrong fix flown with confidence is worse than no fix at all. The model has to know when it doesn't know.

what the UAV sees — one real 128 m frame. No map aboard, no internet, no GPS.
lat52.49995
lon13.35294
confidencehigh
what it must return — the true answer for that frame, computed on board.

The first baseline answered this frame 2.01 km away at confidence 0.99 — confident and wrong, the one answer a UAV must never get. The current model answers that same frame within 24.1 m.

This, on a map, is the goal. Every dot is one held-out viewpoint: ground the model trained on, framed from a position and heading it has never seen. Left is where this started. Right is where it is now. Turning red into green — without ever being confidently wrong — is the whole project.

where this started — measured
mission score 2.001 · usable fixes 0%
Red is a miss beyond 250 m. The baseline is confident on every frame and wrong on every frame — the worst value the metric allows, because for a UAV a confident wrong answer is worse than silence.
where we are — measured
mission score 0.040 · usable fixes 96.5%
The identical test points, answered by the current model. Green is a fix inside 100 m — close enough to correct the aircraft's drift. Nothing about the test changed; only the answers did.
2

The answer

Stop asking for a coordinate. Ask which tile.

INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone daytime framefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×328²×160160-dGAPFC → 2,970 cell logitssoftmaxprobability field55×54 map cells · 128 m each3×3 pooled centroidmass-weighted balance point of the winning cell + 8 neighbourswithin-cell offsettanh · ½ cellfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1= pooled mass over the whole 3×3 blockmay abstain instead of guessingsoft cross-entropy vs a bilinear tent over the 4 nearest cell centres — border views taught the split their decode producesoffset target = the residual the pooled centroid leaves (±½ cell), not the position that centroid already encodesdeployed graph byte-identical to the previous experiment — only the training targets changed

The champion, drawn by the design agent before it was allowed to train. One camera crop enters at the left; the trunk squeezes it to a short vector; the wide fan is the choice over all 2,970 map tiles; the small head after it is the nudge inside the winning tile. Grey is the harness's frozen contract, red is what this experiment changed, and the ochre lane at the bottom is training-only scaffolding that never boards the aircraft. Click to enlarge, or see every proposal on the model designs page.

Ask a network for latitude and longitude and it fails badly: when it is unsure it has no way to say so, and hedging toward the middle of the map is what keeps its average error down. Our first attempt was confident on every frame and wrong on every frame.

So we stopped asking for a coordinate and asked a multiple-choice question instead. Berlin is cut into 2,970 tiles of 128 m and the network points at one. Now the answer carries its own certainty: sure, and the belief piles onto a single tile; lost, and it smears across the city — and the UAV says nothing instead. A second output nudges the fix to a precise point inside the chosen tile.

The result is one file of 3.1 MB that answers in 1.6 ms. Nothing is looked up, nothing is matched — the map is the weights. Each refinement on the way is its own experiment in the research log, with the figures on the model designs page.

One model per area, by design. Asked about a block of Berlin held out of training entirely, the same model returns 0% usable fixes — the map lives in the weights, so ground it was never shown is ground it cannot place. The pipeline takes any bounding box; each trained model knows only its own. Night flying is scoped out for now: everything here is raw daytime imagery.

128 m aerial tile at 52.52377, 13.32644
tile 280 of 2,97052.52377 N · 13.32644 E
128 m aerial tile at 52.52471, 13.39433
tile 316 of 2,97052.52471 N · 13.39433 E
128 m aerial tile at 52.5079, 13.34402
tile 1,059 of 2,97052.50790 N · 13.34402 E
128 m aerial tile at 52.50861, 13.39492
tile 1,086 of 2,97052.50861 N · 13.39492 E
128 m aerial tile at 52.49342, 13.3785
tile 1,792 of 2,97052.49342 N · 13.37850 E
128 m aerial tile at 52.47938, 13.36205
tile 2,443 of 2,97052.47938 N · 13.36205 E
128 m aerial tile at 52.47732, 13.37909
tile 2,562 of 2,97052.47732 N · 13.37909 E
128 m aerial tile at 52.47755, 13.39605
tile 2,571 of 2,97052.47755 N · 13.39605 E

Eight of the 2,970 answers. Every tile is 128 m of real Berlin and owns one coordinate, so “which tile is this?” is the same question as “where am I?” — a river bend is easy; the empty field at the end is why the model must also know when not to answer.

3

How our research works

The model was found, not designed — by a loop of coding agents.

INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone daytime framefrozen contractthe experiment goes herearchitecture · feature extraction · decode · confidence — the agent may redraw all of iteach figure below is one proposal for the inside of this boxwhatever fills the box must export to one ONNX file ≤ 4 MiB and answer in ≤ 250 msfrozen contract(lat, lon, confidence)position fix + confidencelosses · supervision targets · samplersscaffolding that shapes the weights during training — torn down before flight, never in the exported model

The search space. The gray endpoints are frozen — one camera crop in, one (lat, lon, confidence) answer out — and the dashed box is everything an experiment may change. Every design in the model designs gallery is one way of filling it.

No human designed the champion. A Karpathy-style autoresearch loop did: each round, a coding agent reads the full experiment history, proposes one focused change, and pre-registers its hypothesis and expected outcome before any code is written. The harness trains it, scores it, and keeps it only if it beats the champion.

Two roles, split clean. The agents own the experiments. The frozen harness owns the exam: the data pipeline, the held-out viewpoints and the scorer are read-only, so the loop can rewrite the model but never the ruler it is measured by. We supervise from outside — set the levers, curate the inspiration, and decide when an era is over.

THE LOOP experiment after experiment PROPOSE one focused change 1 2 TRAIN on the whole city 3 SCORE the mission penalty 4 KEEP only if it beats the champion HUMAN SUPERVISOR sets the levers, curates the inspiration FROZEN RULER pipeline, eval set, scorer — read-only to the agents

Each round keeps only what beats the best so far, and the next experiment builds on it.

Pre-registered, one change at a time

Hypothesis, method and expected outcome are written down before implementation, and each experiment makes exactly one focused change — so every verdict in the record says something.

Pivoting on patience

A run has a patience: spend it on reverted experiments and the next design must abandon the current backbone for a genuinely different one — enforced by reading the resulting source, not by asking nicely.

A frozen ruler

The score is the product requirement — usable fixes minus confidently-wrong ones — and the agent cannot touch it. When a score and the product disagree, the ruler gets fixed and the lineage is re-measured, never quietly erased.

Everything is recorded

Every experiment is a git commit, a database row and a gallery entry — kept and reverted alike. The lineage, evolution graph and lab notebook are rendered from that record, not written after the fact.

Our model designs

Every experiment's model design, drawn by the design agent itself before it was allowed to train — camera frame entering on the left, (lat, lon, confidence) leaving on the right, red marking what that experiment changed. All fifty-nine that carry a figure, kept and reverted alike; the model designs page has each at full size:

INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone daytime framefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×328²×160160-dGAPFC → 2,970 cell logitssoftmaxprobability field55×54 map cells · 128 m each3×3 pooled centroidmass-weighted balance point of the winning cell + 8 neighbourswithin-cell offsettanh · ½ cellfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1= pooled mass over the whole 3×3 blockmay abstain instead of guessingsoft cross-entropy vs a bilinear tent over the 4 nearest cell centres — border views taught the split their decode producesoffset target = the residual the pooled centroid leaves (±½ cell), not the position that centroid already encodesdeployed graph byte-identical to Fig. 4 — only the training targets changed
5.5 · champion · Decode-consistent training targets
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone daytime framefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×328²×160160-dGAPFC → 2,970 cell logitssoftmaxprobability field55×54 map cells · 128 m each3×3 pooled centroidmass-weighted balance point of the winning cell + 8 neighbourswithin-cell offsettanh · ½ cellfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1= pooled mass over the whole 3×3 blockmay abstain instead of guessingcross-entropy on the one true cell + smooth-L1 offset — unchanged from Fig. 3full-lattice coverage, fresh rotations, cosine LR — byte-identical to Fig. 3; only the deployed decode moved
5.4 · kept · Local belief pooling decode
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone daytime framefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×328²×160160-dGAPFC → 2,970 cell logitssoftmaxprobability field55×54 map cells · 128 m eachargmax over 2,970 cellsone winning cell → its centre, nudged by the offsetwithin-cell offsettanh · ½ cellfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1= softmax mass on the winning cellmay abstain instead of guessingcross-entropy + offset loss unchanged — but every epoch is now one FULL pass over all 72,712 lattice positions581,696 views, ~196 per cell (12× Fig. 2) · fresh rotation per position per epoch · cosine LR 1e-3 → 1e-4architecture restored verbatim from Fig. 2 — the training schedule is the change
5.3 · kept · Full-lattice coverage training for the map-cell classifier
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone daytime framefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×328²×160160-dGAPFC → 2,970 cell logitssoftmaxprobability field55×54 map cells · 128 m eachargmax over 2,970 cellsone winning cell → its centre, nudged by the offsetwithin-cell offsettanh · ½ cellfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1= softmax mass on the winning cellmay abstain instead of guessingcross-entropy on the true cell (label smoothing 0.05) + smooth-L1 on the within-cell offset6,000 of the 72,712 lattice positions redrawn each epoch with fresh headings — 48,000 views for 2,970 cells (~16 each)
5.2 · reverted · Map-cell classification decode
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone daytime framefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×128128-d vectorglobal avg poolFC 128 → 3sigmoidone shot — no map structurefrozen contract(lat, lon, confidence)position fix + confidencemean-squared error on (u, v)the whole map supervises one number pairBCE ×0.1 on confidencetarget: error < half the map extentstarting line — the harness's own code, no design agent involved
5.1 · kept · Baseline seed
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone daytime framefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×128128-d vectorglobal avg poolFC 128 → 1,024 cell logits + 1 confidencesoftmaxprobability field1,024 map cells · 32×32 · 217 m eachargmax over 1,024 cellsone winning cell → its centre, nudged by its own offsetwithin-cell offsetFC 128 → 1,024×(du,dv) · tanh ±½ cellfrozen contract(lat, lon, confidence)position fix + confidenceBCE ×0.1 on confidencethe baseline's free sigmoid, untouchedcross-entropy on the true cell + MSE on its own offsetteacher-forced; trunk, data and 8-epoch budget unchangeddrawn identically on purpose — a faithful rebuild of the experiment whose source a bad metric deleted
4.4 · kept · Re-implementation of lost experiment 2 — classify-then-refine
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone daytime framefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×128128-d vectorglobal avg poolFC 128 → 3sigmoidone shot — no map structurefrozen contract(lat, lon, confidence)position fix + confidenceevery presentation is now a different vantage at a fresh heading~48,000 distinct lattice positions streamed at the same 48,000 gradient stepsloss unchangedMSE on (u, v) + BCE ×0.1 on confidencethe graph is the baseline's, untouched — the data diet is the whole experiment
4.3 · reverted · Coverage over repetition
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone daytime framefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×128128-d vectorglobal avg poolFC 128 → 1,024 cell logits + 1 confidencesoftmaxprobability field1,024 map cells · 32×32 · 217 m eachargmax over 1,024 cellsone winning cell → its centre, nudged by its own offsetwithin-cell offsetFC 128 → 1,024×(du,dv) · tanh ±½ cellfrozen contract(lat, lon, confidence)position fix + confidenceBCE ×0.1 on confidencethe baseline's free sigmoid, untouchedcross-entropy on the true cell + MSE on its own offsetteacher-forced; trunk, data and 8-epoch budget unchanged
4.2 · kept · Classify-then-refine
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone daytime framefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×128128-d vectorglobal avg poolFC 128 → 3sigmoidone shot — no map structurefrozen contract(lat, lon, confidence)position fix + confidencemean-squared error on (u, v)the whole map supervises one number pairBCE ×0.1 on confidencetarget: error < half the map extentstarting line - the same naive baseline, re-measured on the corrected viewpoint holdout
4.1 · kept · Baseline seed on the corrected viewpoint-holdout split
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone daytime framefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×128128-d vectorglobal avg poolFC 128 → 4,096 cell logitssoftmaxprobability field4,096 map cells · 64×64 · 108 m eachsoft-argmax over 4,096 cellsevery cell centre, weighted by its probabilityfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1= heaviest 5×5-cell block of beliefmay abstain instead of guessingloss, head and schedule all unchanged — what moves is which 6,000 positions each pass is built fromre-drawn at random from all ~45,000 mapped vantages before every pass, instead of one frozen 6,000 draw reused 96 timesdeployed graph byte-identical to the experiment above it — only the training diet changed
3.5 · kept · Per-epoch position resampling
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone daytime framefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×1284×4×32 descriptor1×1 conv 128→32 · 2×2 poolFC 512 → 256 cell logitssoftmaxprobability field256 map cells · 16×16 · 434 m eachposterior-weighted blendevery cell's centre plus its own pointer, averaged by beliefper-cell pointerFC 512 → 256×(du,dv) · tanh ±¾ cellfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1= heaviest 2×2-cell block of beliefmay abstain instead of guessingsoft-label cross-entropy over the 256 coarse cells (σ = ½ cell) + MSE on the true cell's pointer + MSE on the blended (u, v)same 96-pass, fresh-heading schedule as the champion — the loss now grades 256 big squares and teaches a pointer inside eachthe descriptor moves with the decode: a pooled texture bag cannot say WHERE in a cell the frame sits
3.4 · reverted · Hierarchical decode
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone daytime framefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×128128-d vectorglobal avg poolFC 128 → 4,096 cell logitssoftmaxprobability field4,096 map cells · 64×64 · 108 m eachsoft-argmax over 4,096 cellsevery cell centre, weighted by its probabilityfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1= heaviest 5×5-cell block of beliefmay abstain instead of guessingsame cross-entropy and same soft labels — the study budget is the change: 96 passes, not 8cosine LR 1e-3 → 1e-5 · every crop re-drawn at a fresh random heading before every passthe head is restored verbatim from the gated-out experiment above it — only the training schedule is new
3.3 · kept · Re-land the validated 64x64 grid-classification head with a convergence-scale training budget (x12 epochs, cosine LR, fresh per-epoch rotations)
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone daytime framefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×128128-d vectorglobal avg poolFC 128 → 4,096 cell logitssoftmaxprobability field4,096 map cells · 64×64 · 108 m eachsoft-argmax over 4,096 cellsevery cell centre, weighted by its probabilityfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1= heaviest 5×5-cell block of beliefmay abstain instead of guessingcross-entropy against Gaussian-smoothed cell labels (σ = 1 cell) + a small L2 on the soft-argmax coordinate6,000 crops, one frozen rotation each, 8 epochs — the same budget the naive baseline was givengated FAIL — confident on only 10.8% of frames, under the harness's 20% coverage floor
3.2 · reverted · Reparameterize localization as 64x64 map-grid classification with in-graph soft-argmax
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone daytime framefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×128128-d vectorglobal avg poolFC 128 → 3sigmoidone shot — no map structurefrozen contract(lat, lon, confidence)position fix + confidencemean-squared error on (u, v)the whole map supervises one number pairBCE ×0.1 on confidencetarget: error < half the map extentstarting line — the harness's own code re-run on Berlin alone, no design agent involved
3.1 · kept · Baseline seed
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone night exposurefrozen contract×8 exact-pixel views (D4)rotations + mirror, shared weightsSqueezeNet1.1 Fire trunkstem + 4 fire blocks (BSD-3)mobilenet_v3_small banned this round63²×647²×384lumFiLM (γ, β) MLPmodulates feature map384-d descriptorGAP, D4-pooled avg1-ch layout1×1 squeeze, 49-d flatsingle Linear → 1,024gate + dual head deletedprobability field32×32 cells over the mapadaptive-β commitfrozen contract(lat, lon, confidence)position fix + confidenceβ = f(entropy, peak)learned per-example sharpeningconfidence 0–1384-d GAP + adaptive β + peak/entropy/gapGaussian-CE vs cell target (unchanged)σ = 1.5 cells over the 32×32 fieldL2 on decoded (u, v)expected-coordinate loss — now also trains the β gaugeconfidence BCE ×0.3 (unchanged loss)same hit-radius target, new head inputs
2.62 · reverted · Fire-module SqueezeNet1.1 trunk + FiLM-conditioned single field + D4 symmetry + adaptive-sharpening decode (forced pivot, mobilenet_v3_small banned)
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone night exposurefrozen contract×4 crop rotations (C4)0/90/180/270°, shared weightsdepthwise-separable trunkfrom-scratch, 4× wider64²×648²×320320-d descriptorGAP, C4-pooled avgunified FC → 1600 logitsQATLinear, weight fake-quantprobability field40×40 cells, finer than prior 32×32sharpen β=3 → soft-argmaxover the finer 1,600-cell gridfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1peak/entropy/gap of new fieldweight fake-quant every stepround(w/scale)·scale — straight-through gradint8 export, post-trainingdynamic quantization — 1 B/weight, real roundingGaussian-CE vs cell target (unchanged)σ = 1.5 cells, now over the 40×40 fieldL2 on decoded (u, v)expected-coordinate loss, unchangedconfidence BCE ×0.3unchanged hit-radius target
2.61 · reverted · Quantization-freed capacity
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone night exposurefrozen contractillumination-invariant channellog-luminance − own Gaussian blur (fixed math, no gradient)concat128²×4 input×4 crop rotations (C4)0°/90°/180°/270°, shared weightsfrom-scratch conv encoderConv 3×3 s2 ×4 · BN+ReLU — pretrained trunk banned this round128²×48²×128128-d descriptorGAP, C4-pooled avgunified FC → 1024 logitsgate + dark-expert head deletedprobability field32×32 cells, same layout-code concatsharpen β=3 → soft-argmaxdecode mechanism unchangedfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1peak/entropy/gap of new fieldsame recipe, no gate-derived inputs leftlighting-partner cropsame spot & heading, other buckettrain-onlyshared trunkf partner2nd forward passL2 consistency loss ×0.1 (new)same spot, 2 lighting buckets → match descriptorswatch: across-location variance must stay healthyGaussian-CE vs cell target (unchanged)σ = 1.5 cells, same GRID_K=32 fieldL2 on decoded (u, v) (unchanged)confidence BCE ×0.3 (unchanged loss)same hit-radius target, new field inputs
2.60 · reverted · Corrected exp-38 retry
INFERENCE PATH — WHAT FLIES (both specialists always run; the gate blends, never branches)TRAINING — THREE PHASES, NEVER JOINT128²×3camera frameone of 6 lighting bucketsfrozen contractday-specialist trunkfrom-scratch · day buckets onlyday field + decode16×16 grid, soft-argmaxday (u,v,conf)3 pixel statsmean · spread · dark%MLP(8)no trunk, no featuresgate gday-like ↔ night-likedispatchernight-specialist trunkindependent copy, own weights · night buckets onlynight field + decode16×16 grid, soft-argmaxnight (u,v,conf)blendg·day + (1−g)·nightconf nudged down when g is unsurefrozen contract(lat, lon, confidence)position fix + confidencephase 1 — day trunk+field+decode+conffresh optimizer · Gaussian-CE + L2 + 0.3× conf BCE, day buckets onlyphase 2 — night trunk+field+decode+confseparate fresh optimizer · same loss · zero gradient crosses into phase 1phase 3 — freeze both specialiststrain only the gate (~40 params) · Huber/L2 + 0.3× conf BCE, all 6 bucketsconfusability sampler runs twice, independentlyday draw and night draw never mix
2.59 · reverted · Independently-trained day/night specialist twins with a trunk-free brightness dispatcher
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — JOINT EVERY STEP, NEVER FLY128²×3camera frameone of 6 lighting bucketsfrozen contractrotation fan4× C4 views, shared netconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×64layout summaryspatial code + texture avgFC → 1024 logitssingle unified scorerprobability field32×32 field, gate removedsoft-argmax decodereads one unified field, sharpening unchangedfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1peak / entropy / gap+ raw crop brightness (new)may abstain instead of guessingreconstruction decoderConvTranspose 4×4 ×4 — reads row 0, un-rotated8²×6464²×16repainted crop128²×3, sigmoiddiscarded before exportreference.tif twinsame cx, cy, angleclean daytime, any bucketL1 pixel-reconstruction loss, weight 1.0every crop, every bucket, every step — not a pretrain phaseGaussian-CE on field + L2 on (u,v) + BCE on confidenceloss formula itself unchanged — only the field it grades is unified nowone shared LR (1e-3) for all paramsfrom-scratch trunk — no pretrained-feature 10× discount to protect
2.43 · reverted · Joint reconstruction-canonicalization trunk
INFERENCE PATH — WHAT FLIESPHASE 0 — SELF-SUPERVISED PRETRAINING (TRAIN SPLIT ONLY, RUNS FIRST)PHASE 2 — SUPERVISED TRAINING (UNCHANGED LOSS FORMULA, NEW SCHEDULE)128²×3camera frameone night exposurefrozen contractC4 rotation fanshared net, feeds SSL viewsfrom-scratch conv trunk4× conv3×3 s2 + BN + ReLU, no ImageNet weights128²×38²×64layout summaryspatial code + texture avgFC → 1024 logitssingle unified scorerprobability field32×32 field, gate removedsoft-argmax decodeanswer = Σ probability · cell-centerconfidence 0–1peak/entropy/gap + brightness (new)may abstain instead of guessingfrozen contract(lat, lon, confidence)position fix + confidenceview Alighting/heading draw 1view Blighting/heading draw 2same physical location — uniform random draw, 128 locs/stepshared trunksame weights as aboveproj head64→128→64, L2-norm in losssame place → pull togetherother batch places → push apartNT-Xent (InfoNCE)temperature 0.1, batch 128schedule: 150 contrastive steps (3×50), 128 locs/step, then usual supervised epochs (count unchanged)trunk LR gap to head relaxed 10× → 2× (5e-4 vs 1e-3) — pretrained trunk needs less protectionGaussian-CE on field + L2 on decoded (u,v) — loss formula itself unchangedconfusability-weighted sampler (exp 35) still feeds THIS stage only, not pretraining
2.42 · reverted · Domain-native contrastive pretraining replaces the ImageNet trunk (corrected re-attempt)
INFERENCE PATH — WHAT FLIESPHASE 0 — SELF-SUPERVISED PRETRAINING (TRAIN SPLIT ONLY, RUNS FIRST)PHASE 2 — SUPERVISED TRAINING (UNCHANGED LOSS FORMULA, NEW SCHEDULE)128²×3camera frameone night exposurefrozen contractC4 rotation fanshared net, feeds SSL viewsfrom-scratch conv trunk4× conv3×3 s2 + BN + GELU, no ImageNet weights128²×38²×64layout summaryspatial code + texture avgFC → 1024 logitssingle unified scorerprobability field32×32 field, gate removedlearned βsoftplus, init 3.0soft-argmax decodeanswer = Σ probability · cell-centerconfidence 0–1peak/entropy/gap + brightness (new)may abstain instead of guessingfrozen contract(lat, lon, confidence)position fix + confidenceview Alighting/heading draw 1view Blighting/heading draw 2same physical location — confusability-weighted sampler (exp 35)shared trunksame weights as aboveproj head64→64→32, L2-normsame place → pull togetherother batch places → push apartNT-Xent (InfoNCE)temperature 0.15, batch 128schedule: 3 SSL epochs (cosine→0), then 24 supervised epochs (count unchanged)trunk/head LR ratio relaxed 10× → 3.3× (3e-4 vs 1e-3) — domain prior needs less protectionGaussian-CE on field + L2 on decoded (u,v) — loss formula itself unchangedsame confusability-weighted sampler (exp 35) feeds this stage too
2.41 · reverted · Domain-native contrastive pretraining replaces the ImageNet trunk
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone night exposurefrozen contractrotation fan×4 turns, C4 votefeature extractorMobileNetV3-S, 2 taps↓ stride-8 tap feeds the fine field belowcoarse localization field8×8 cells ≈875 m, shared 1×1 convfine offset fieldper-cell (Δu,Δv,logσ), ONE shared headdecodeβ-sharpened mean of (cell center + own offset)frozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1peak/entropy shape + fine field's own logσ — may abstaincoarse Gaussian-CE over 8×8 cells (was 32×32)gradient now shared through ~100 conv weights, not 1,024 free rows+ fine offset Huber loss, gathered at the TRUE cell onlyunimodal regression — coarse stage already picked the place+ L2 on final decode + conf BCEtraining data: confusability sampler (exp 35)recomputed at the new 8×8 granularityschedule: 2-epoch warmup, fresh offset head
2.40 · reverted · Coarse-to-fine geolocalization
INFERENCE PATH — WHAT FLIES128²×3Camera frameone of 6 lighting rendersfrozen contract4×128²×3Rotation fanvotes the new similarity map64²×168²×48Feature extractorMobileNetV3-Small, +NEW stride-8 tap16²×24skip GAP · 24-dNEW tapGAP 48 + layout 512kept descriptor pairCrop embedding64-d, L2-normalized — NEWlighting FiLMγ,β from brightness+GAPProbability mapcosine sim. × cells, C4-avgFourier(u, v)shared 2-layer MLP generates all 1,024cell embeddings — not 1,024 free rowsDecodeβ-sharpened soft-argmax (kept form)frozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1peak-vs-2nd-peak margin — NEWtraining-only — never fliesGaussian-bump CE on the temperature-scaled cosine-simfield (kept CE form; logits are bounded sim × learned scale, not raw FC output)+ coord L2 + conf BCE (kept, unchanged math) — training data/schedule belowkept, unchanged: confusability-weighted location sampler (rd 35)kept, unchanged: 3 seeded relight realizations per bucket (rd 17)kept, unchanged: 24-pass fresh-draw epochs, cosine LR glide to zero (rd 25)removed: dark-expert head + brightness gate (rd 12) — folded into FiLM above
2.39 · reverted · Coordinate-generated map field
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone night exposurefrozen contract6-ch inputRGB ⊕ retinexillumination-invariant channellog(I) − large-σ Gaussian blur, fixedRotation fan4×90° turns, 6chMobileNetV3-Small trunk (9 blocks)pretrained · stem widened, rest frozen64²×68²×48stem re-init 3→6chRGB weights kept + 0.1× copy48-d GAPtexture avg, unchangedlayout squeeze1×1 conv, 8ch512-d layout codeNEW: L2-norm per cellprobability mapgated 2-expert blend, unchangedβ-sharpened decodeC4-voted, unchangedfrozen contract(lat, lon, confidence)position fix + confidenceconfidence: field-shape gauge, unchangedtraining data: confusability draw (kept, exp 35) + NEW per-crop sharpness jitter50% chance Gaussian blur (σ 0.3–1.5px) else unsharp-mask — the blur-riding shortcut can no longer carry location signaltraining schedule: NEW 5%-of-steps linear warm-up before the exp-25 cosine decayprotects the freshly re-initialized stem weights from early large gradientstraining signal: Gaussian-CE + coord L2 + conf BCEunchanged
2.38 · reverted · Illumination-invariant retinex channel joins raw RGB from the pixel level through the trunk
Camera frame128²×3 · ~1 m/pxfrozen contractC4 rotation fan4 exact 90° turns4×128²×364²×1616²×248²×48MobileNetV3-Small trunkpretrained, gently fine-tunedGAP 48layout 512Multi-hypothesis head8 learned points, softmax weightno separate expert4-view weighted voteweight-argmax point per heading, softmax-blendedconf: 4-view agreement × winning weight(lat, lon, confidence)frozen contracttraining-only — never fliescell-descriptor mapfrom reference.tif, offline, once per areaconfusability-weighted samplingfar, look-alike cells drawn ~2x more often per epochhalf the draw stays uniform — full coverage kept (kept · rd 35)still 6,000 places/bucket/epoch, fresh-drawn (rd 20 · reweighted only)3 seeded relight realizations per bucket (kept · rd 17)24 passes · cosine LR glide to zero (kept · rd 25)+ winner-take-all: nearest of 8 hyps gets the L2 grad, others ε=0.05 (NEW)weight head trained by cross-entropy vs. the nearest-hypothesis index (8-way, not 1024-way)winner-take-all regressionnearest hyp wins the gradient; rest share ε=0.05
2.37 · reverted · Multi-hypothesis coordinate regression replaces the 1024-cell field
Camera frame128²×3 · ~1 m/pxfrozen contractC4 rotation fan4 exact 90° turns4×128²×364²×1616²×248²×48MobileNetV3-Small trunkpretrained, gently fine-tunedGAP 48layout 512lighting gatebrightness-blended pair of scorersσprobability field32×32 cells, C4-vote averagedcommitted decodeβ-sharpened soft-argmax (unchanged)conf: field-shape hit predictor(lat, lon, confidence)frozen contracttraining-only — never fliescell-descriptor mapfrom reference.tif, offline, once per areaconfusability-weighted samplingfar, look-alike cells drawn ~2x more often per epochhalf the draw stays uniform — full coverage kept (kept · rd 35)still 6,000 places/bucket/epoch, fresh-drawn (rd 20 · reweighted only)3 seeded relight realizations per bucket (kept · rd 17)24 passes · cosine LR glide to zero (kept · rd 25)+ hardest-impostor margin hinge on C4-voted logits (NEW)hardest-impostor margin hinges_neg (Cheb>3) pushed below s_pos (Cheb≤1)
2.36 · reverted · Hardest-impostor margin hinge, retested on the confusability-weighted champion
Camera frame128²×3 · ~1 m/pxfrozen contractC4 rotation fan4 exact 90° turns4×128²×364²×1616²×248²×48MobileNetV3-Small trunkpretrained, gently fine-tunedGAP 48layout 512lighting gatebrightness-blended pair of scorersσprobability field32×32 cells, C4-vote averagedcommitted decodeβ-sharpened soft-argmax (unchanged)conf: field-shape hit predictor(lat, lon, confidence)frozen contracttraining-only — never fliescell-descriptor mapfrom reference.tif, offline, once per areaNEW — confusability-weighted samplingfar, look-alike cells drawn ~2x more often per epochhalf the draw stays uniform — full-map coverage keptstill 6,000 places/bucket/epoch, fresh-drawn (rd 20 · reweighted only)3 seeded relight realizations per bucket (kept · rd 17)24 passes · cosine LR glide to zero (kept · rd 25)Gaussian-bump CE + coord L2 + conf BCE (kept · unchanged)
2.35 · kept · Confusability-weighted location sampling
Camera frame128²×3 · ~1 m/pxfrozen contractC4 rotation fan4 exact 90° turns4×128²×364²×1616²×248²×48MobileNetV3-Small trunkpretrained, gently fine-tunedGAP 48layout 512lighting gatebrightness-blended pair of scorersσprobability field32×32 cells, C4-vote averagedcommitted decodeβ-sharpened soft-argmax (unchanged)conf: field-shape hit predictor(lat, lon, confidence)frozen contracttraining-only — never fliesfresh 6,000-place draw per bucket per epoch (kept · rd 20)3 seeded relight realizations per bucket (kept · rd 17)24 passes · cosine LR glide to zero (kept · rd 25)Gaussian-bump CE + coord L2 + conf BCE (kept · unchanged)NEW — hardest-impostor margin · λ 0.5best-scoring cell outside the 7×7 ring around truthmust trail the 3×3 truth block by ≥ 1.0 logittruth 3×3hardest impostor
2.34 · reverted · Hardest-impostor margin loss
Camera frame128²×3 · ~1 m/pxfrozen contractC4 rotation fan4 exact 90° turns4×128²×364²×1616²×248²×48MobileNetV3-Small trunkpretrained, gently fine-tunedGAP 48layout 512lighting gatebrightness-blended pair of scorersσprobability field32×32 cells, C4-vote averagedcommitted decodeβ-sharpened soft-argmax (unchanged)conf: field-shape hit predictor(lat, lon, confidence)frozen contracttraining-only — never fliescrispas todaydefocusedNEW — per-crop sharpness roll¼ pin-sharp (no resample) · ½ extra defocus σ∈U(0.4,1.4) pxfresh 6,000-place draw per bucket per epoch (kept · rd 20)3 seeded relight realizations per bucket (kept · rd 17)24 passes · cosine LR glide to zero (kept · rd 25)Gaussian-bump CE + coord L2 + conf BCE
2.33 · reverted · Sensor-sharpness nuisance randomization
INFERENCE PATH — WHAT FLIESTRAINING-TIME CALIBRATION — NEVER FLIES128²×3camera frameone of 6 lighting rendersfrozen contractrotation fanfour 90° turnsMobileNetV3-Small trunkpretrained, 9 blocks8²×48crop descriptor512-d layout + 48-d GAPprobability field32×32 cells · two experts · C4 voteβ-sharpened decode — balance point of the hottest modefrozen contract(lat, lon, confidence)position fix + confidencefield-shape statisticspeak · entropy · decode gapself-trust score z− regime abstention bar (interpolated)confidence 0–1conf < 0.3 → 'no fix' (must answer ≥20%)frame brightnesssix regime anchorsabstention bar per regime, blended by frame brightnessfenced calibration blocks~10% of train blocks by stable hash — excluded from everytraining draw, same halo rule as eval blocks (grey);errors are measurable there, terrain is honestly unseenmedian errorq* ≥ 0.26keep rateper-regime operating pointeach lighting regime's keep rate picked at the low pointof its fenced risk–coverage curve (floor 0.32) — the sixthresholds become the anchor row above
2.32 · reverted · Risk-controlled abstention
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone of 6 rendersfrozen contractrotation fan4 turns, voted at the field64²×168²×48MobileNetV3-Small trunkpretrained, gently fine-tuned4×4×8crop fingerprint1×1 conv + 2×2 pool · each tap = 32 m of groundbright/dark variants blended by the kept gateslide across the map8 ch × ~217×~213learned neural map32 m per cell · lives in the weightsmatch-score field~45,000 positions · softmax32 m pitch — was 217 msharpened soft-argmaxcommit to the hottest mode (unchanged)frozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1reads the map's shape — may abstainGaussian-CE + decode L2 + conf BCE — unchangedsame σ (≈330 m tolerance) in map units, graded on the ~45k-position fieldtraining data, sampler & 24-epoch cosine schedule unchanged
2.31 · reverted · Neural-map correlation field
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone of 6 rendersfrozen contractC4 rotation fan4 turns, logits voted64²×168²×48MobileNetV3-Small trunkImageNet-pretrained, blocks 0–88×8 layout squeeze1×1 conv → 512-dGAP 48-d560-d560-d descriptor48 texture ⊕ 512 layoutday specialistFC 560 → 1,024 eachdusk specialistnight specialist× w₁× w₂× w₃lighting dispatchersoftmax → w₁,w₂,w₃crop brightnessprobability field32×32 cells · C4 logit voteβ-sharpened soft-argmaxcommits to the dominant modefrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1may abstain instead of guessingcross-entropy on the routing weights vs the TRUE lighting bucketbuckets group as day / dusk / night — the labels are free at train timespecialists' FC weights ride int8 in the exported ONNXexport-only pack — ~7 m cost measured (exps 26/29); 3 full heads fit the 4 MiB gateGaussian-CE + decode L2 + conf BCE — unchangedtraining data & schedule also unchanged (24 fresh-draw passes)
2.30 · reverted · Supervised lighting dispatcher
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone of 6 lighting rendersfrozen contractC4 rotation fan4 turns, logits averaged64²×168²×4816²×24MobileNetV3-Small trunkImageNet-pretrained blocks 0–8 — unchanged1×1 conv 24 → 4 ch · flatten → 1,024-dGAP · 1×1 layout squeezecrop summary — 1,584-d48-d GAP + 512-d 8×8 layout (as before)+ 1,024-d stride-8 fine code — newnight gate blends a 48-d dark scorer per crop (unchanged)FC 1,584 → 1,024 logitsweight tables fly int8 — measured ±7 mprobability field32×32 cells · C4 logit vote (unchanged)β-sharpened soft-argmaxcommit to the dominant mode (unchanged)frozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1reads its own field shapeGaussian-CE (σ=1.5 cells) + decode-L2 + conf-BCE — unchangedtraining procedure unchanged — 24 fresh-draw epochs, cosine LR → 0
2.29 · reverted · Stride-8 fine-layout tap
Camera frame128²×3, ~1 m/pxfrozen contractRotation fanfour 90° turns×4stem + early64²×16mid blocks16²×24blocks 4–88²×48blocks 9–10 — reinstateddilated — 8²×96layout code608-dint8 FC store — reinstatedquantized at export · ~7 m effectσlighting gateProbability map32×32 cells, C4 voteDecodesharpened balance pointConfidenceabstains on smeared maps(lat, lon,confidence)frozen contractabstain bar set on held-back ground — new~10% of train blocks never enter a training draw;the bar is tuned on ground as unseen as the exam'straining-only lane — losses and schedule unchanged: Gaussian-CE map target · committed-coord L2 · conf BCE · 24 fresh-draw epochs, cosine LR → 0
2.28 · reverted · Rerun, never scored
Camera frame128²×3, ~1 m/pxfrozen contractRotation fanfour 90° turns×4stem + early64²×16mid blocks16²×24blocks 4–88²×48blocks 9–10 — reinstateddilated — 8²×96layout code608-dint8 FC store — reinstatedquantized at export · ~7 m effectσlighting gateProbability map32×32 cells, C4 voteDecodesharpened balance pointConfidenceabstains on smeared maps(lat, lon,confidence)frozen contractabstain bar set on held-back ground — new~10% of train blocks never enter a training draw;the bar is tuned on ground as unseen as the exam'straining-only lane — losses and schedule unchanged: Gaussian-CE map target · committed-coord L2 · conf BCE · 24 fresh-draw epochs, cosine LR → 0
2.27 · reverted · Unseen-ground confidence calibration unlocks the reinstated 3×-capacity trunk
Camera frame128²×3, ~1 m/pxfrozen contractRotation fanfour 90° turns×4stem + early64²×16mid blocks16²×24blocks 4–88²×48blocks 9–10 — newdilated — 8²×96layout code608-dint8 FC store — newquantized at export · ~7 m effectσlighting gateProbability map32×32 cells, C4 voteDecodesharpened balance pointConfidenceabstains on smeared maps(lat, lon,confidence)frozen contracttraining-only lane — unchanged: Gaussian-CE map target · committed-coord L2 · conf BCE · 24 fresh-draw epochs, cosine LR → 0
2.26 · reverted · Deployment-envelope capacity scaling
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3 · ~1 m/pxcamera frameone of six lighting rendersfrozen contractshared weights ×4rotation fan0°·90°·180°·270° — exact pixel turnsMobileNetV3-Small trunkImageNet init (BSD-3) · gently fine-tuned8²×48 ×41024 logits ×4four field mapssame gated two-expert head reads each turn32×32 cellsvoted probability fieldmean of four logit maps = geometric-mean voteβ-sharpened soft-argmaxcommits to the hottest mode (unchanged)frozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1reads the voted map’s shape (unchanged)may abstainposition + confidence losses — all unchangedGaussian-CE + decode L2 + conf BCE — still graded at the true centreepoch 1epoch 2… epoch 24a fresh draw of 6,000 locations per bucket, every epochevery epoch, training restarts on a freshly drawn set of placesLRbefore: constant LR, hard stop at epoch 8now: cosine glide to zero across a 3× longer runconvergence-scaled training — 3× the steps, annealed to zeroThe fresh-draw sampler (kept, left) made memorizing crops useless — but theschedule still stops at 8 passes, loss still falling, LR never lowered.A probe shows pure underfit: train crops now localize no better thaneval crops (~1 km both). This run trains 24 fresh-draw passes with theLR gliding down a cosine — the same sampler, finally trained to converge.
2.25 · kept · Convergence-scaled training
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3 · ~1 m/pxcamera frameone of six lighting rendersfrozen contractshared weights ×4rotation fan0°·90°·180°·270° — exact pixel turnsMobileNetV3-Small trunkImageNet init (BSD-3) · gently fine-tuned8²×48 ×41024 logits ×4four field mapssame gated two-expert head reads each turn32×32 cellsvoted probability fieldmean of four logit maps = geometric-mean voteβ-sharpened soft-argmaxcommits to the hottest mode (unchanged)frozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1reads the voted map’s shape (unchanged)may abstainposition + confidence losses — all unchangedGaussian-CE + decode L2 + conf BCE — still graded at the true centreepoch 1epoch 2… epoch 8a fresh draw of 6,000 locations per bucket, every epochevery epoch, training restarts on a freshly drawn set of placeskept from exp 20 — unchangedtrunk feature grid 8²×48identity turn · read before pooling16²32²64²throwaway upsampling decoder8²→64² · ~55k params · never exported64²×3redrawn daytime viewfrom features alone64²×3daytime reference cropsame spot & heading, free from simL1 ×0.3NEW — daytime-redraw auxiliaryfrom its own features, the netmust redraw this spot in cleandaylight; all six renders shareone daytime answer, so seeingthrough grain and darkness is thecheapest fit — decoder never flies
2.24 · reverted · Daytime-redraw auxiliary, rerun
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3 · ~1 m/pxcamera frameone of six lighting rendersfrozen contractshared weights ×4rotation fan0°·90°·180°·270° — exact pixel turnsMobileNetV3-Small trunkImageNet init (BSD-3) · gently fine-tuned8²×48 ×41024 logits ×4four field mapssame gated two-expert head reads each turn32×32 cellsvoted probability fieldmean of four logit maps = geometric-mean voteβ-sharpened soft-argmaxcommits to the hottest mode (unchanged)frozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1reads the voted map’s shape (unchanged)may abstainposition + confidence losses — all unchangedGaussian-CE + decode L2 + conf BCE — still graded at the true centreepoch 1epoch 2… epoch 8a fresh draw of 6,000 locations per bucket, every epochevery epoch, training restarts on a freshly drawn set of placeskept from exp 20 — unchangedtrunk feature grid 8²×48identity turn · read before pooling16²32²64²throwaway upsampling decoder8²→64² · ~55k params · never exported64²×3redrawn daytime viewfrom features alone64²×3daytime reference cropsame spot & heading, free from simL1 ×0.3NEW — daytime-redraw auxiliaryfrom its own features, the netmust redraw this spot in cleandaylight; all six renders shareone daytime answer, so seeingthrough grain and darkness is thecheapest fit — decoder never flies
2.23 · reverted · Daytime-redraw auxiliary
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3 · ~1 m/pxcamera frameone of six lighting rendersfrozen contractshared weights ×4rotation fan0°·90°·180°·270° — exact pixel turnsMobileNetV3-Small trunkImageNet init (BSD-3) · gently fine-tuned8²×48 ×41024 logits ×4four field mapssame gated two-expert head reads each turn32×32 cellsvoted probability fieldmean of four logit maps = geometric-mean voteβ-sharpened soft-argmaxcommits to the hottest mode (unchanged)frozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1reads the voted map’s shape (unchanged)may abstainposition + confidence losses — all unchangedGaussian-CE + decode L2 + conf BCE — still graded at the true centreepoch 1epoch 2… epoch 8a fresh draw of 6,000 locations per bucket, every epochevery epoch, training restarts on a freshly drawn set of placeskept from exp 20 — unchangedtrunk feature grid 8²×48identity turn · read before pooling64 per-patch map fields — 3 of 64 shownone shared 1×1 conv 48→1024 · training-only, deleted before exportNEW — per-patch place supervisionevery feature cell must place ITS OWN16 m patch of ground on the map, gradedby a Gaussian bump at that patch's truespot = crop centre + rotated cell offset.64 graded answers per crop instead of 1.The flying network is untouched — theaux head never ships.
2.22 · reverted · Train-only per-patch place supervision
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3 · ~1 m/pxcamera frameone of six lighting rendersfrozen contractshared weights ×4rotation fan0°·90°·180°·270° — exact pixel turnsMobileNetV3-Small trunkImageNet init (BSD-3) · gently fine-tuned8²×48 ×41024 logits ×4four field mapssame gated two-expert head reads each turn32×32 cellsvoted probability fieldmean of four logit maps = geometric-mean voteβ-sharpened soft-argmaxcommits to the hottest mode (unchanged)frozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1reads the voted map’s shape (unchanged)may abstainposition + confidence losses — all unchangedGaussian-CE + decode L2 + conf BCE — still graded at the true centreepoch 1epoch 2… epoch 8a fresh draw of 6,000 locations per bucket, every epochevery epoch, training restarts on a freshly drawn set of placesper-epoch location resampling — same training budget, 8× the places seenthe last kept model studied the SAME 36,000 crops for all 8 epochs — same places, same headings,same simulator rolls — so memorizing each crop was the easiest way down the training loss.Now every epoch redraws its 6,000 locations per bucket (fresh headings and render mix): ~30k of the45k train places get seen, each only ~1–2×. Memorizing single crops stops paying; only cues thattransfer between places do — the skill an eval crop over never-trained terrain actually demands.
2.20 · kept · Per-epoch training-set resampling
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3 · ~1 m/pxcamera frameone of six lighting rendersfrozen contractshared weights ×4rotation fan0°·90°·180°·270° — exact pixel turnsMobileNetV3-Small trunkImageNet init (BSD-3) · gently fine-tuned8²×48 ×41024 logits ×4four field mapssame gated two-expert head reads each turn32×32 cellsvoted probability fieldmean of four logit maps = geometric-mean voteβ-sharpened soft-argmaxcommits to the hottest mode (unchanged)frozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1reads the voted map’s shape (unchanged)may abstainposition + confidence losses — all unchangedGaussian-CE + decode L2 + conf BCE — still graded at the true centrehalf of each bucket’s training crops are patched before batchingcrop from elsewheresame lighting bucketlift a 48–96 px blockpatched training croplabel: still the true centreoff-site distractor patching — p = 0.5, training onlyeval crops sit on never-trained blocks: the centre terrain is always unfamiliar, familiar terrainpokes in from an edge (~76% of eval crops contain some trained pixels). The probe behind exp 18:train-split crops localize to 267–400 m, eval-split to 708–1153 m — a ~3× structural gap, in every bucket.Training crops were always 100% familiar, so the whole-crop head never practised partial recognition;patched crops force it to answer from the content consistent with one place and down-weight the rest.
2.19 · reverted · Off-site distractor patching
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone of six lighting rendersfrozen contractrotation fan0°·90°·180°·270°shared weights ×4MobileNetV3-Small trunkImageNet init (BSD-3)8²×48 ×4patch votersevery cell = one voter64 per-patch field votesshared 1×1 MLP 48→128→1024 — one field per patch⋯ ×64 votes, each × learned weight wᵖ (softmax over patches)voted probability fieldweighted blend of 64 patch votesmean over 4 turns (unchanged)β-sharpened soft-argmaxcommits to the hottest mode (unchanged)frozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1reads the voted map's shape (unchanged)may abstaindense per-patch supervision — 64 graded answers per cropeach patch's vote is graded against a Gaussian bump on the map cell of ITS OWN ground content,computed exactly at train time as crop center + R(heading)·patch offset — a place can no longer berecognized by one whole-crop gestalt: all 64 voters must independently know where their ground sitsprobe, midday, matched headings: train-crop median 267–400 m vs held-out 708–1153 m — the global template head memorizes but does not generalizefused-field Gaussian-CE + decode L2 + conf BCE — unchanged · three-realization training renders (exp 17) — unchanged · calibration unchanged
2.18 · reverted · Dense per-patch field voting
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone of six lighting rendersfrozen contractrotation fan0°·90°·180°·270° — exact pixel turnsshared weights ×4MobileNetV3-Small trunkImageNet init (BSD-3) · gently fine-tuned8²×48 ×4four field mapssame gated two-expert head reads each turn32×32 cellsvoted probability fieldmean of four logit maps = geometric-mean voteβ-sharpened soft-argmaxcommits to the hottest mode (unchanged)frozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1reads the voted map's shape (unchanged)may abstainGaussian-CE + decode L2 + conf BCE — all unchangedthe losses now grade the voted answer — train what fliesseed₀= the eval renderseed₁fresh dice rollseed₂fresh dice rolleach training crop is drawn from one of three seeded realizationsnuisance-randomized training rendersthe frozen relight sim rolls dice for sensor noise + lamp thinning; the stored night render freezes ONE roll,≈ half that image's content (mean |Δpx| 29/255 between rolls vs 6/255 at midday; render mean 60/255)→ the 1024-way head memorizes roll-specific texture that cannot transfer to held-out locations.Training now draws each bucket's crops from three seeded rolls (⅓ each), so only the seed-stablestructure — roads, buildings, where the lit areas sit — stays discriminative between locations.eval renders, model, losses, decode, calibration: all unchanged — train-time only
2.17 · kept · Nuisance-randomized training renders
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone of six lighting rendersfrozen contractrotation fan0°·90°·180°·270° — exact pixel turnsshared weights ×4MobileNetV3-Small trunkImageNet init (BSD-3) · gently fine-tuned8²×48 ×4four field mapssame gated two-expert head reads each turn32×32 cellsvoted probability fieldmean of four logit maps = geometric-mean voteβ-sharpened soft-argmaxcommits to the hottest mode (unchanged)frozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1reads the voted map's shape (unchanged)may abstaininvariance by construction, not by dataexp 6 taught headings by example — reverted; this builds them inGaussian-CE + decode L2 + conf BCE — all unchangedthe losses now grade the voted answer — train what flies
2.16 · kept · C4 rotation-vote field
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLYred = this experiment: field-shape confidence + calibrated abstention — unsure crops return no fix128²×3camera frameone night exposurefrozen contractMobileNetV3-Small trunkImageNet-pretrained · stem + 8 inverted-residual blocks, unchanged128²×38²×48layout code1×1 conv, unchanged8²×848-d GAPunchanged∑/nraw-pixel mean brightnesslighting gatetiny MLP → σ, unchangedg ∈ [0,1]bright headFC 560→1024dark headFC 48→1024 · GAP-only, unchangedblend(1−g)·b + g·dprobability field32×32 cellsβ·logitssharpened fieldsoftmax(β·logits)β = 3 — unchangedsoft-argmax over the sharpened fieldcommits to the dominant peak — unchangedfrozen contract(lat, lon, confidence)position fix + confidenceGaussian-CE on the field + L2 on the committed decodeboth unchanged — localization trains exactly as beforepeak massentropymode−mean gap0.3confidence head — learns when to abstaintiny MLP on field shape · calibrated to the frozen 0.3 barbelow the bar → no fix, coast on last estimateconfidence BCE — did the committed fix land within ~350 m?detached head — cannot disturb localizationper-bucket threshold calibration≥40% keep a fix in every lighting bucket
2.15 · kept · Selective prediction
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLYred = this experiment: β-sharpened peak-commit decode replaces mean-of-map averaging128²×3camera frameone night exposurefrozen contractMobileNetV3-Small trunkImageNet-pretrained · stem + 8 inverted-residual blocks, unchanged128²×38²×48layout code1×1 conv, unchanged8²×848-d GAPunchanged∑/nraw-pixel mean brightnesslighting gatetiny MLP → σ, unchangedg ∈ [0,1]bright headFC 560→1024dark headFC 48→1024 · GAP-only, unchangedblend(1−g)·b + g·dprobability field32×32 cellsβ·logitssharpened field — NEWsoftmax(β·logits), β = 3peaks boosted, hedging suppressedsoft-argmax over the sharpened fieldcommits to the dominant peakfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1may abstain instead of guessingGaussian-CE on the unsharpened field (unchanged)the field keeps learning calibrated evidenceL2 on the SHARPENED decodethe loss now grades the committed answer that flies
2.14 · kept · Peak-commit decode
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone night exposurefrozen contractMobileNetV3-Small trunkImageNet-pretrained · stem + 8 inverted-residual blocks (exp 11, unchanged)128²×38²×48layout code1×1 conv, unchanged8²×848-d GAPunchanged∑/nraw-pixel mean brightnesslighting gatetiny MLP → sigmoidg ∈ [0,1]bright headFC 560→1024dark head — NEWFC 48→1024, GAP-onlyblend(1−g)b + g·dprobability field32×32 cells, unchangedsoft-argmax over ALL cellsanswer = Σ probability · cell-centerfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1may abstain instead of guessingcross-entropy + decode L2 (unchanged)gate + dark head train on the SAME lossesno lighting label — g learns from brightness ⊕ GAPred = this experiment: gated dark-expert head blended with the existing layout head
2.12 · kept · Luminance-gated dark-expert field head blended with the existing layout head
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone night exposurefrozen contractMobileNetV3-Small encoder — ImageNet-pretrainedstem + 8 inverted-residual blocks · depthwise conv + squeeze-excite64²×168²×481×1 conv → 8²×8 layout codekeeps what sits WHERE in the crop48-d GAPtexture average — as before512 ⊕ 48 = 560FC 560 → 1024 logitssoftmaxprobability field32×32 cells over the mapsoft-argmax over ALL cellsanswer = Σ probability · cell-centerfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1may abstain instead of guessingtrunk weights arrive from ImageNet (1.2M real photos) — not randomfine-tuned gently: trunk lr 1e-4 · fresh heads lr 1e-3 · BSD-3 licensedGaussian-CE + decode L2 + conf BCE — all unchangedhead, decode and training recipe identical to kept exp 10red = this experiment: an ImageNet-pretrained trunk replaces the from-scratch encoder
2.11 · kept · ImageNet-pretrained MobileNetV3-Small trunk replaces the from-scratch encoder
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone night exposurefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×1281×1 conv → 8²×8 layout codekeeps what sits WHERE in the crop128-d GAPtexture average — as before512 ⊕ 128 = 640FC 640 → 1024 logitssoftmaxprobability field32×32 cells over the mapsoft-argmax over ALL cellsanswer = Σ probability · cell-centerfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1may abstain instead of guessingGaussian-CE + decode L2 + conf BCE — all unchangedtraining recipe identical to kept exp 7; only the head's input changedred = this experiment: the field head reads an 8×8 layout code ⊕ texture average
2.10 · kept · Layout-aware field head
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone night exposurefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×128128-dGAPFC → 1024 logitssoftmaxprobability field32×32 cells over the mapsoft-argmax over ALL cellsanswer = Σ probability · cell-centerfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1may abstain instead of guessing=same placetraining batches become PAIRS — same place, two lighting renders, two headingsone shared 6,000-location set across all 6 renders · 32 places × 2 views per stepNT-Xent: pull the pair together, push 62 others apart64-d projection of the descriptor · τ 0.2 · head never fliesGaussian-CE + L2 + conf BCE — unchanged
2.9 · reverted · Cross-lighting contrastive pairs
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone night exposurefrozen contract+++residual encoder — 11 conv layersstem + 3 stride-2 stages, each ending in a residual block~973k params, 4.2× the old 4-conv stack3.7 of the 4.0 MiB flight-memory budget (was 0.9)64²×328²×160160-dGAPFC → 1024 logitssoftmaxprobability field32×32 cells over the mapsoft-argmax over ALL cellsanswer = Σ probability · cell-centerfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1may abstain instead of guessingGaussian-CE + L2 + conf BCE (unchanged)same lessons, same 36k crops, same 8 epochs — only the student grew
2.8 · reverted · Deployment-envelope residual encoder
Camera frame1 of 6 lighting renders128×128×364²×1632²×3216²×648²×128Feature extractor4 strided conv blocks · ~230k params128-d embeddingglobal average pool128 → 1024probability field32×32 map cells · ~220 m/cellsoft-argmaxexpected coordinate over cell centers(lat, lon, confidence)position + confidenceu,v ∈ [0,1] map coords → lat, lonconf head (linear + sigmoid)training onlywas: 800 places/bucketnow: 6,000 places/bucketof ~45,000 available×7.5 coverage — every map cell now trainedin every lighting bucket; ~4,500 steps (was 600)Gaussian-CE on smoothed cell target + coord L2 + conf BCE (unchanged)one static crop per place at one random heading (unchanged, per exp-6)
2.7 · kept · Scale training coverage 7.5x
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone night exposurefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×128128-dGAPFC → 1024 logitssoftmaxprobability field32×32 cells over the mapsoft-argmax over ALL cellsanswer = Σ probability · cell-centerfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1may abstain instead of guessingcrop rotations re-drawn EVERY epochfresh views of the same places each pass, not one frozen tensor reused 8×Gaussian-CE + L2 (unchanged)
2.6 · reverted · Per-epoch rotation resampling replaces the one-shot frozen training tensor
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone night exposurefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×128128-dGAPFC → 1024 logitssoftmaxprobability field32×32 cells over the mapsoft-argmax over ALL cellsanswer = Σ probability · cell-centerfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1may abstain instead of guessingsum-pool the SAME field to 16², 8², 4² — Gaussian-CE at every scalecoarse cells collect 10–40 positives each and steer the fine field (+ L2 on decode, unchanged)
2.5 · reverted · Hierarchical coarse-to-fine supervision of the probability field via probability pooling
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone night exposurefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×128dilated conv 3×3, d2~95 px context per cell64 per-patch coordinates1×1 conv + σ (8×8×2)mean of 64 answersone committee answer from 64 votesfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1may abstain instead of guessingsmooth-L1: each patch vs its OWN true coordinatecrop center + rotated offset → 64× denser supervision
2.4 · reverted · ACE-style dense per-patch scene-coordinate regression replaces global map-cell probability field
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone night exposurefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×128128-dGAPFC → 1024 logitssoftmaxprobability field32×32 cells over the mapargmax → 5×5 window soft-argmaxcommit to the hottest cell, refine locallyfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1may abstain instead of guessingcross-entropy vs Gaussian cell target (unchanged)L2 on the WINDOWED decodetrain on exactly what flies
2.3 · reverted · Argmax-anchored local soft-argmax decode replaces global expected-coordinate
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone night exposurefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×128128-dGAPFC → 1024 logitssoftmaxprobability field32×32 cells over the mapsoft-argmax over ALL cellsanswer = Σ probability · cell-centerfrozen contract(lat, lon, confidence)position fix + confidenceconfidence 0–1may abstain instead of guessingcross-entropy: match a Gaussian bump on the true cellσ = 1.5 cells — every cell gets a hotter/colder gradientL2 on the decoded (u, v)
2.2 · kept · DSNT-style spatial probability field over the map replaces direct (u,v) regression
INFERENCE PATH — WHAT FLIESTRAINING SIGNALS — NEVER FLY128²×3camera frameone night exposurefrozen contractconvolutional encoderConv 3×3, stride 2 ×4 · BN + ReLU64²×168²×128128-d vectorglobal avg poolFC 128 → 3sigmoidone shotfrozen contract(lat, lon, confidence)position fix + confidencemean-squared error on (u, v)the whole map supervises one number pairBCE ×0.1 on confidencestarting design — nothing changed yet
2.1 · kept · Starting baseline — naive TinyLocNet, from-scratch, frozen pipeline v1
Our training data

Everything the model knows, it learned from one picture: an open-licensed aerial orthophoto mosaic of Berlin from the Berlin/Brandenburg geoportal (© GeoBasis-DE/LGB, dl‑de/by‑2‑0, modified), fetched by the frozen pipeline and resampled to 1 m per pixel — 6,939 × 6,828 pixels covering the whole bounding box. No Google or Bing tiles anywhere: only open geodata, so the entire project can be published. Training crops 128 m frames from every position on that mosaic; the held-out eval frames stand on the same ground, framed from positions and headings training never used. A hundred of the 2,970 tiles:

128 m aerial training tile at 52.52829, 13.32061
52.52829 · 13.32061
128 m aerial training tile at 52.52845, 13.33192
52.52845 · 13.33192
128 m aerial training tile at 52.52858, 13.34135
52.52858 · 13.34135
128 m aerial training tile at 52.52874, 13.35267
52.52874 · 13.35267
128 m aerial training tile at 52.5289, 13.36398
52.52890 · 13.36398
128 m aerial training tile at 52.52903, 13.37342
52.52903 · 13.37342
128 m aerial training tile at 52.52918, 13.38473
52.52918 · 13.38473
128 m aerial training tile at 52.52934, 13.39605
52.52934 · 13.39605
128 m aerial training tile at 52.52946, 13.40548
52.52946 · 13.40548
128 m aerial training tile at 52.52962, 13.4168
52.52962 · 13.41680
128 m aerial training tile at 52.52139, 13.32087
52.52139 · 13.32087
128 m aerial training tile at 52.52155, 13.33218
52.52155 · 13.33218
128 m aerial training tile at 52.52168, 13.34161
52.52168 · 13.34161
128 m aerial training tile at 52.52184, 13.35293
52.52184 · 13.35293
128 m aerial training tile at 52.522, 13.36424
52.52200 · 13.36424
128 m aerial training tile at 52.52213, 13.37367
52.52213 · 13.37367
128 m aerial training tile at 52.52228, 13.38498
52.52228 · 13.38498
128 m aerial training tile at 52.52243, 13.3963
52.52243 · 13.39630
128 m aerial training tile at 52.52256, 13.40573
52.52256 · 13.40573
128 m aerial training tile at 52.52271, 13.41704
52.52271 · 13.41704
128 m aerial training tile at 52.51564, 13.32109
52.51564 · 13.32109
128 m aerial training tile at 52.5158, 13.3324
52.51580 · 13.33240
128 m aerial training tile at 52.51593, 13.34183
52.51593 · 13.34183
128 m aerial training tile at 52.51609, 13.35314
52.51609 · 13.35314
128 m aerial training tile at 52.51624, 13.36445
52.51624 · 13.36445
128 m aerial training tile at 52.51637, 13.37388
52.51637 · 13.37388
128 m aerial training tile at 52.51653, 13.3852
52.51653 · 13.38520
128 m aerial training tile at 52.51668, 13.39651
52.51668 · 13.39651
128 m aerial training tile at 52.51681, 13.40594
52.51681 · 13.40594
128 m aerial training tile at 52.51696, 13.41725
52.51696 · 13.41725
128 m aerial training tile at 52.50874, 13.32135
52.50874 · 13.32135
128 m aerial training tile at 52.5089, 13.33266
52.50890 · 13.33266
128 m aerial training tile at 52.50903, 13.34209
52.50903 · 13.34209
128 m aerial training tile at 52.50919, 13.3534
52.50919 · 13.35340
128 m aerial training tile at 52.50934, 13.36471
52.50934 · 13.36471
128 m aerial training tile at 52.50947, 13.37414
52.50947 · 13.37414
128 m aerial training tile at 52.50963, 13.38545
52.50963 · 13.38545
128 m aerial training tile at 52.50978, 13.39676
52.50978 · 13.39676
128 m aerial training tile at 52.50991, 13.40619
52.50991 · 13.40619
128 m aerial training tile at 52.51006, 13.4175
52.51006 · 13.41750
128 m aerial training tile at 52.50298, 13.32157
52.50298 · 13.32157
128 m aerial training tile at 52.50314, 13.33288
52.50314 · 13.33288
128 m aerial training tile at 52.50328, 13.34231
52.50328 · 13.34231
128 m aerial training tile at 52.50343, 13.35361
52.50343 · 13.35361
128 m aerial training tile at 52.50359, 13.36492
52.50359 · 13.36492
128 m aerial training tile at 52.50372, 13.37435
52.50372 · 13.37435
128 m aerial training tile at 52.50388, 13.38566
52.50388 · 13.38566
128 m aerial training tile at 52.50403, 13.39697
52.50403 · 13.39697
128 m aerial training tile at 52.50416, 13.40639
52.50416 · 13.40639
128 m aerial training tile at 52.50431, 13.41771
52.50431 · 13.41771
128 m aerial training tile at 52.49608, 13.32183
52.49608 · 13.32183
128 m aerial training tile at 52.49624, 13.33314
52.49624 · 13.33314
128 m aerial training tile at 52.49637, 13.34256
52.49637 · 13.34256
128 m aerial training tile at 52.49653, 13.35387
52.49653 · 13.35387
128 m aerial training tile at 52.49669, 13.36518
52.49669 · 13.36518
128 m aerial training tile at 52.49682, 13.3746
52.49682 · 13.37460
128 m aerial training tile at 52.49697, 13.38591
52.49697 · 13.38591
128 m aerial training tile at 52.49713, 13.39722
52.49713 · 13.39722
128 m aerial training tile at 52.49726, 13.40664
52.49726 · 13.40664
128 m aerial training tile at 52.49741, 13.41795
52.49741 · 13.41795
128 m aerial training tile at 52.49033, 13.32205
52.49033 · 13.32205
128 m aerial training tile at 52.49049, 13.33336
52.49049 · 13.33336
128 m aerial training tile at 52.49062, 13.34278
52.49062 · 13.34278
128 m aerial training tile at 52.49078, 13.35409
52.49078 · 13.35409
128 m aerial training tile at 52.49094, 13.36539
52.49094 · 13.36539
128 m aerial training tile at 52.49107, 13.37482
52.49107 · 13.37482
128 m aerial training tile at 52.49122, 13.38612
52.49122 · 13.38612
128 m aerial training tile at 52.49138, 13.39743
52.49138 · 13.39743
128 m aerial training tile at 52.4915, 13.40685
52.49150 · 13.40685
128 m aerial training tile at 52.49166, 13.41816
52.49166 · 13.41816
128 m aerial training tile at 52.48343, 13.32232
52.48343 · 13.32232
128 m aerial training tile at 52.48359, 13.33362
52.48359 · 13.33362
128 m aerial training tile at 52.48372, 13.34304
52.48372 · 13.34304
128 m aerial training tile at 52.48388, 13.35435
52.48388 · 13.35435
128 m aerial training tile at 52.48404, 13.36565
52.48404 · 13.36565
128 m aerial training tile at 52.48417, 13.37507
52.48417 · 13.37507
128 m aerial training tile at 52.48432, 13.38638
52.48432 · 13.38638
128 m aerial training tile at 52.48447, 13.39768
52.48447 · 13.39768
128 m aerial training tile at 52.4846, 13.4071
52.48460 · 13.40710
128 m aerial training tile at 52.48475, 13.41841
52.48475 · 13.41841
128 m aerial training tile at 52.47768, 13.32253
52.47768 · 13.32253
128 m aerial training tile at 52.47784, 13.33384
52.47784 · 13.33384
128 m aerial training tile at 52.47797, 13.34326
52.47797 · 13.34326
128 m aerial training tile at 52.47813, 13.35456
52.47813 · 13.35456
128 m aerial training tile at 52.47829, 13.36586
52.47829 · 13.36586
128 m aerial training tile at 52.47841, 13.37528
52.47841 · 13.37528
128 m aerial training tile at 52.47857, 13.38659
52.47857 · 13.38659
128 m aerial training tile at 52.47872, 13.39789
52.47872 · 13.39789
128 m aerial training tile at 52.47885, 13.40731
52.47885 · 13.40731
128 m aerial training tile at 52.479, 13.41861
52.47900 · 13.41861
128 m aerial training tile at 52.47078, 13.3228
52.47078 · 13.32280
128 m aerial training tile at 52.47094, 13.3341
52.47094 · 13.33410
128 m aerial training tile at 52.47107, 13.34352
52.47107 · 13.34352
128 m aerial training tile at 52.47123, 13.35482
52.47123 · 13.35482
128 m aerial training tile at 52.47138, 13.36612
52.47138 · 13.36612
128 m aerial training tile at 52.47151, 13.37554
52.47151 · 13.37554
128 m aerial training tile at 52.47167, 13.38684
52.47167 · 13.38684
128 m aerial training tile at 52.47182, 13.39814
52.47182 · 13.39814
128 m aerial training tile at 52.47195, 13.40756
52.47195 · 13.40756
128 m aerial training tile at 52.4721, 13.41886
52.47210 · 13.41886
4

How to use it

One file, one function, three steps.

1. Download the model: berlin.onnx (3.1 MB). It runs anywhere ONNX runs — a laptop, a Raspberry Pi, the ESP32‑P4 target.

2. Feed it camera frames, 3. trust it only when it is sure — the whole client is this:

# pip install onnxruntime opencv-python pyproj numpy
import cv2, numpy as np, onnxruntime as ort
from pyproj import Transformer

# the Berlin model's georeference (from the training raster's metadata)
ORIGIN = (385883.0, 5821316.0)          # UTM 33N of the map's top-left corner
SIZE   = (6939, 6828)                   # map size in px; 1 px = 1 m
to_wgs84 = Transformer.from_crs("EPSG:32633", "EPSG:4326")

sess = ort.InferenceSession("berlin.onnx")
cam  = cv2.VideoCapture(0)              # the downward-facing camera

ok, bgr = cam.read()                    # 1 - grab one frame
rgb = cv2.cvtColor(bgr, cv2.COLOR_BGR2RGB)
rgb = cv2.resize(rgb, (128, 128))       # frame should cover ~128 m of ground
x = rgb.astype(np.float32).transpose(2, 0, 1)[None] / 255.0

u, v, conf = sess.run(None, {"frame": x})[0][0]   # 2 - ask the network
lat, lon = to_wgs84.transform(ORIGIN[0] + u * SIZE[0],
                              ORIGIN[1] - v * SIZE[1])

if conf < 0.3:                          # 3 - trust it only when it is sure
    print("no fix - the model abstains")
else:
    print(f"{lat:.5f}, {lon:.5f}  (confidence {conf:.2f})")

The frame must look straight down over Berlin and cover roughly 128 m of ground (about 100 m altitude with a typical lens). Below confidence 0.3 the fix is discarded, exactly as the research scores it.

5

Explore the record

Every experiment, every design, every dead end.

The research log Every experiment ever run, failures included: pre-registered hypotheses, results, per-area × lighting scoreboards, the exact prompts the agents received, and one real worked example per experiment — the same held-out viewpoint through each model's actual deployed weights. Experiment lineage The family tree of the search: every experiment as one node in discovery order, arcs to the design it built on — hover any node to trace its ancestry, kept trunk and dead branches alike. Model designs The technical figures: each experiment's model design, drawn by the agent itself before training, in one shared visual language — frozen endpoints aligned so you can scroll and compare designs directly.
6

Proven alternatives

GPS-denied localisation is not unsolved — this just walks a different road.

GPS-denied visual localization is not an unsolved problem. The established, field-tested family matches live camera frames against georeferenced reference imagery carried on the aircraft — e.g. WildNav (Vision-based GNSS-Free Localization for UAVs in the Wild), which matches UAV photographs against satellite tiles with deep feature matching and demonstrated GNSS-comparable accuracy in real flights. If you need working GPS-denied navigation today, start there, not here.

This project deliberately walks a different road, for two reasons. Licensing: the strongest matchers in that stack — Magic Leap's SuperGlue / SuperPoint pretrained networks — are licensed for noncommercial research only, without the right to sublicense, which is incompatible with a fully open-sourceable, commercially usable system (permissive alternatives like LightGlue (Apache-2.0) exist, but the whole approach still means shipping reference imagery on the airframe — this project's hardest constraint rules that out). Curiosity: the actual motivation is ground-level research — can an autonomous loop of coding agents discover a genuinely different approach, with no reference imagery on board and the map living entirely in the network's weights, under a low-light premise? It may or may not end up competitive with the field-tested systems above. Saying so out loud is part of the experiment.

The vision, if it works: a novel algorithm that lets anyone draw a bounding box around a place they care about and generate their own tiny, punchy, self-contained geo-boxed model — reliable, personalized, and free. Open data in, open weights out; no reference imagery to license, no vendor to call, no cloud to depend on. The map is yours, and it lives in a few megabytes you own.

updated 2026-08-01 14:57 UTC · experiments run on a single local machine; the loop commits every result to git as it goes

scroll to zoom · drag to pan · double-click to reset
view on GitHub