Busabase
Busabase is an open-source (MIT) database and workspace for AI agents — data, docs, skills, and apps in one place. Run it locally, self-host it inside your network, or use Busabase Cloud, and turn age
翻譯準備中
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證A self-improving ML pipeline for UAV low-light visual geolocalization with a Claude-driven autoresearch loop that trains per-area scene-coordinate models targeting a <$5 ESP32-P4.
翻譯準備中
正在載入完整 README。 以下為已儲存的摘錄。
Can a UAV learn a city by heart? Given a geographic bounding box, this
repo trains a compact per-area model that takes a single downward camera
frame from a UAV and returns
estimate_position(frame) -> (lat, lon, confidence) — no reference imagery
on the aircraft, no connectivity, targeting an ESP32-P4 companion board.
The interesting part: the model-side code is improved by an autonomous
research loop (Karpathy autoresearch-style) that designs experiments,
rewrites architecture/loss/training, and keeps or reverts by a single frozen
metric. Full context: CLAUDE.md.檢視完整 README ↗Can a UAV learn a city by heart? Given a geographic bounding box, this
repo trains a compact per-area model that takes a single downward camera
frame from a UAV and returns
estimate_position(frame) -> (lat, lon, confidence) — no reference imagery
on the aircraft, no connectivity, targeting an ESP32-P4 companion board.
The interesting part: the model-side code is improved by an autonomous
research loop (Karpathy autoresearch-style) that designs experiments,
rewrites architecture/loss/training, and keeps or reverts by a single frozen
metric. Full context: CLAUDE.md.
| Path | Status | What |
|---|---|---|
pipeline/ | FROZEN | bbox-generic fetch of one or several captures per area (independent open-licensed photographs of the same ground on one grid — see pipeline/common.py), 6-bucket synthetic low-light relighting (collapsed to a daytime pass-through in the current berlin-slim configuration), deterministic split holding out viewpoints, not regions (training covers the whole bbox; eval frames sit 11-17 m off the nearest training vantage — see pipeline/dataset.py for why a region-based holdout was wrong) and, since 2026-09-28, the photograph itself (the eval capture is never trained on), §6 scoring — the mission score, (1 - usable_fix_rate) + false_fix_rate, which is the product requirement rather than an error statistic — with ESP32-P4 deployment gates |
areas.yaml | FROZEN | 4 development areas + hamburg blind holdout; per-area capture lists (Berlin: 3 training photographs + 1 held out) |
model/ | agent-editable | model architecture + training procedure (the loop's playground) |
autoresearch/ | mostly frozen | loop.sh harness, SQLite schema + logger, gallery renderer, per-iteration agent prompt |
FROZEN | — | the exact list of files the loop may never touch (enforced by loop.sh via git revert) |
runs/ | generated | per-experiment artifacts (models, metrics, heatmaps, samples) |
experiments.sqlite | generated | full experiment lineage: hypothesis, method, expected outcome, result, conclusion, all metrics |
gallery/ | generated | self-refreshing pages: research log (index.html, samples + error heatmaps), model designs (inference-paths.html, every experiment's pre-registered architecture figure), experiment lineage, research evolution, lab notebook and flight path; the overview is index.html at the repo root |
sim/ | tool, not frozen | virtual UAV flight simulator (flightsim.py) — flies the exported champion with its fixes as the only position source — six further mission types (missions.py: return home, tour, loiter, survey, cold start, Spree corridor), and the flight-path page renderer (render_flightpath.py). Reads the frozen pipeline, never modifies it |
infra/ | tooling | remote training launchers (aws_train.py is the primary one), site build and asset freezing |
uv venv --python 3.12 .venv
uv pip install --python .venv/bin/python numpy pillow rasterio pystac-client torch onnx onnxruntime pyyaml
# Frozen pipeline — any bbox works, named areas are just presets:
.venv/bin/python -m pipeline.fetch --area berlin # or: --name x --bbox w,s,e,n
# fetches every capture in areas.yaml; existing ones are reused
.venv/bin/python -m pipeline.relight --area berlin # one relight/<bucket>.png per capture x lighting condition
.venv/bin/python -m model.train --area berlin --out-dir runs/test --epochs 3
.venv/bin/python -m pipeline.score --areas berlin --model-dir runs/test/models --out runs/test/metrics.json
.venv/bin/python -m autoresearch.gallery # open gallery/index.html
Bootstrap proving runs: experiment #1 (commit 15b43a2) ran berlin +
prignitz on 10 m Sentinel-2 data → 2926 m. Experiment #3 (commit c0a1bdf,
pipeline data v2) re-proved the harness on 1 m/px DOP imagery across all
four development areas → 2765.67 m worst-case median error, coverage 1.0
(historical: that bootstrap run predates the current metric — the primary
score is now the §6 mission score, not a median; see pipeline/score.py)
in all 24 area×bucket cells (target ≤ 20 m; a center-guess on a ~7 km box is
~2.8 km — the baseline is deliberately naive). All deployment gates passed.
The §6 anti-abstention gate was exercised for real en route: two confidence
calibrations collapsed dark-bucket coverage and were correctly scored FAIL.
Current configuration:
berlin-slim(merged intomain2026-07-31), capture-holdout era (branchcapture-holdout, opened 2026-09-28). Berlin only, raw daytime imagery, no synthetic relighting, pivot gate off, and every experiment gets its architecture figure (DRAW_FIGURES=1, the default). The model trains on three open survey photographs of Berlin and is scored on a fourth it never sees — because the 0.040 champion, scored on any other photograph of the same ground, scored 1.8-2.0 (random, and confident). Best so far on that ruler: experiment 20, 0.078 (93.0% usable, 0.75% false fixes on the held-out 2024 photograph). Design and implementation agents both run on Opus 5.5. See CLAUDE.md's "CAPTURE-HOLDOUT ERA" and "SCOPE OVERRIDE" for what each supersedes and why. Merged intomainand published on 2026-11-03 (issue #23).
REMOTE_TRAIN=1 ./autoresearch/loop.sh 12 # run until the DB holds 12 experiments, training on AWS
./autoresearch/loop.sh 12 # same, training locally on the M1 (~3-4x slower)
SKIP_AGENT=1 ./autoresearch/loop.sh 1 # smoke-test the harness without an agent
touch state/stop # graceful stop after the current experiment
./autoresearch/dashboard.sh # the loop's dashboard: current experiment, progress,
# recent results, activity; s = graceful stop, q = close
The dashboard is read-only and can be opened and closed at any time from any
terminal; it reads the files the loop writes (state/phase.json, the run
directory's training log, experiments.sqlite) once a second. --once
prints a single frame for checking the layout.
Data for berlin is already fetched and relit; the other areas are only needed if you restore the full four-area scope:
for a in prignitz munich frankfurt hamburg; do
.venv/bin/python -m pipeline.fetch --area $a
.venv/bin/python -m pipeline.relight --area $a
done
Per experiment the design agent pre-registers title / category / hypothesis / method / expected_outcome (written to the run's experiment.json); the
harness appends the measured result and a kept/reverted conclusion, logs
to SQLite, snapshots model/*.py into runs/<id>/model_src/ whatever the
outcome, and commits kept improvements so git history is the research trail.
Watch progress: open gallery/index.html (re-rendered when a design lands
and again when the experiment finishes), or
sqlite3 experiments.sqlite "SELECT id,title,primary_metric,kept FROM experiments ORDER BY id DESC LIMIT 10;"
Training runs on AWS since 1 November 2026 (REMOTE_TRAIN=1;
REMOTE_BACKEND defaults to aws): infra/aws_train.py starts a
throwaway GPU machine per experiment (g6.xlarge, NVIDIA L4, eu-central-1,
spot first, on-demand if no spot capacity), ships it the code and only
the training photographs (it refuses to pack the eval capture), and
brings back the ONNX. Credentials in .env. The machine has no git, no
AWS credentials and no open ports, and switches itself off after
AWS_MAX_MINUTES (480) no matter what. That limit guards against a
forgotten machine and is not a training budget: a run that hits it is
recorded as not tested, never as a refuted idea (issue #22). So are
cloud failures such as no GPU capacity (issue #13).
Without REMOTE_TRAIN=1 training runs locally on the M1
(model/train.py auto-selects cuda > mps > cpu), roughly 50 minutes per
experiment for the champion's architecture.
Two older remote paths are dormant:
| status | |
|---|---|
Modal (REMOTE_BACKEND=modal) | stateless per-area trainer, never touches git, and like the AWS path refuses to ship the eval photograph. Backup only, capped at its $30 monthly free credit. |
RunPod (infra/runpod.sh, REMOTE_BACKEND=runpod) | abandoned 2026-07-23 after three days of stuck commits and merge conflicts. It still rsyncs all of data/berlin, the held-out eval photograph included, so it must not be used on this branch. Scripts kept for reference; do not restart it without reading docs/infra.md first. |
The rule that came out of that period and still holds: one git writer, always. The laptop commits; a remote may only train and hand back artifacts. Two writers on one branch was the root cause of the whole mess, not the provider.
sim/) — does the champion actually get a UAV from a to b?A virtual-UAV flight simulator closes the loop on the mission score's own
premise (§2: the vision fix is the only drift correction). A point-mass
fixed-wing flies through wind, gusts and gyro bias its navigator cannot see;
every fix interval the sim crops the held-out 2024 photograph (the eval
capture, a photograph the model never trained on) at the aircraft's
true pose, runs the exported champion ONNX, and hands the answer to a
dead-reckoning navigator that accepts false fixes like any other. Arrival is
declared on the navigator's estimate and scored against the truth. Honesty
rules are documented at the top of sim/flightsim.py; the known best-case
caveats (the camera is another aerial survey, not a drone camera; fixed
1 m/px altitude) are stated on the results page rather than hidden.
Headline (experiment 20, 100 flights, seed 1): 95/100 arrive within 100 m, median declared miss 47 m, worst 212 m, nothing lost off the map; the dead-reckoning control arrives 0/100 (median miss 823 m).
Six more mission types (sim/missions.py, 40 flights each, with a
no-camera control in the same weather): return home 88%, waypoint tour 55%,
loiter 90%, survey grid 75%, cold start 98%, Spree corridor 50%. The error
does not build up over a mission; what fails one is nearly always a single
confident wrong fix, and those cluster at a few places (on the Spree, 126
of 128 sit in two kilometres of river).
Results are rendered as the gallery/flight-path.html page (replay with a
mission picker, estimation-error sawtooth, 100-flight record, the missions
table).
.venv/bin/python -m sim.flightsim --seed 6 --start 350,350 --target 6800,6600 \
--save-crops --out sim/out/showcase.json # the page's showcase flight
.venv/bin/python -m sim.flightsim --flights 100 --seed 1 --out sim/out/mc.json
.venv/bin/python -m sim.flightsim --flights 100 --seed 1 --no-vision --out sim/out/mc_dr.json
.venv/bin/python -m sim.missions --mission all --flights 40 --seed 1 \
--flight-dir sim/out/mission_flights # the six missions (+ --no-vision control)
.venv/bin/python -m sim.render_flightpath # rebuild the page from sim/out/
Fetching is driven by a source registry (pipeline/sources.yaml,
frozen): for any bbox, the finest open-licensed auto-pickable source
covering it wins, falling back to global Sentinel-2. An area may also list
captures in areas.yaml — several independent photographs of the same
bbox, each from a named source, all warped onto one shared grid
(data/<area>/captures/<name>.tif) so a crop at the same pixel shows the
same ground in every one. role: train captures are what the model sees;
the role: eval capture is a photograph it never sees and the §6 score is
computed on it. The pipeline code stays fully bbox-generic — regional
knowledge is config, not code.
| Source | Covers | Native | License / attribution |
|---|---|---|---|
| BB-BE DOP20 WMS | Brandenburg + Berlin | 20 cm | dl-de/by-2-0 — © GeoBasis-DE/LGB |
| Berlin TrueDOP 2022 / 2023 / 2024 WMS (named captures only) | Berlin | 20 cm | dl-de/zero-2-0 — Geoportal Berlin |
| Bavaria DOP40 WMS | Bavaria (Munich) | 40 cm | CC BY 4.0 — © Bayerische Vermessungsverwaltung |
| Hesse DOP20 WMS | Hesse (Frankfurt) | 20 cm | dl-de/by-2-0 — © HVBG Hessen |
| Hamburg DOP WMS | Hamburg | 20 cm | dl-de/by-2-0 — © FHH LGV |
| Sentinel-2 L2A (Earth Search STAC → AWS COGs) | global fallback | 10 m | Copernicus — "Contains modified Copernicus Sentinel data" |
Everything is server-resampled to a 1 m/px reference grid (target_gsd_m
in the registry): a 128 px model crop = 128 m ground footprint, matching a
typical UAV camera at ~100 m AGL — so training imagery scale ≈ deployment
imagery scale. No Google/Bing tiles anywhere. Expect roughly 0.5–3 GB of
imagery per area on disk after relighting.
Buy-now, documented-working stack:
Still open (stretch): a true STARVIS2/IMX585-class starlight sensor on the P4 has no documented pairing — IMX585 typically wants 4-lane MIPI (P4 has 2) and a custom driver. Path: prove the full system on SC2336 first; invest in starlight bring-up only if night accuracy turns out sensor-limited. (The ams MIRA220 NIR example shows third-party sensor bring-up on the P4 is feasible.)
.venv/bin/python -m pipeline.fetch --name myarea --bbox 9.10,48.70,9.20,48.76
then relight/train/score as above — nothing in the pipeline knows about
specific areas. Only add entries to areas.yaml if it should become part of
the frozen evaluation set (that's a human decision, not the loop's).
GPL-3.0-or-later (see LICENSE). The choice is deliberate: the point of
this project is that anyone can generate their own tiny, self-contained,
geo-boxed localization model — so the pipeline that makes that possible must
stay free. Copyleft guarantees it: you may use, study, modify and
redistribute everything here, but a distributed fork — improved or otherwise
— must remain under the GPL. Freedom is the priority here, not adoption.
Two boundaries, spelled out in NOTICE:
runs/ and site_assets/) carry their
geodata sources' attribution terms (dl-de/by-2-0, CC BY 4.0, Copernicus)
independent of the code license.The repository was MIT-licensed before 2026-08-01; the relicense was made by the sole copyright holder.