Störningskarta och exponering längs en rutt
kshana interference-map bygger en bild per dag av var flygplan och fartyg rapporterade försämrade navigeringsdata, utifrån öppet licensierade spårningsfiler som du tillhandahåller. kshana route-exposure anger sedan hur stor del av en planerad rutt som låg inom de påverkade cellerna varje dag.
Vad detta är: en beskrivning av hur publicerade positionsrapporter såg ut under tidigare dagar. Vad det inte är: en mätning av någon mottagare, en prognos eller ett bevis på störning. En försämrad eller avvikande cell har flera möjliga orsaker (listas nedan), och en cell utan post observerades helt enkelt inte.
Allt körs på lokala filer. Standardkommandona öppnar aldrig en nätverksanslutning; den enda valfria nedladdningshjälparen kräver en uttrycklig flagga.
Båda dagarna är de syntetiska exemplen i examples/interference-map/output/, var och en med en syntetisk rutt i examples/interference-map/input/; ruttexponeringsandelarna är vad kshana route-exposure skriver ut för dem. Ingenting i dem är en verklig plats, ett verkligt flygplan eller fartyg.
Data och licenser#
Endast de källor som granskats i data/INTERFERENCE-DATA-SOURCES.md är inbyggda, och väljs med --dataset:
--dataset |
Typ | Licens | Licensfält i utdata |
|---|---|---|---|
adsb-lol |
ADS-B | ODbL 1,0 | ODbL-1.0 |
noaa-marinecadastre |
AIS | Amerikansk allmän egendom (CC0 1,0 enligt utgivaren) | allmän egendom |
kystverket |
AIS | NLOD 2,0 | NLOD-2.0 |
custom |
endera | vad du än anger | --licence, --licence-url, --attribution krävs |
Varje utdatafil bäddar in licensen, licensens URL, den krävda källangivelsen och källans täckningsbegränsningar. Det finns ingen inbyggd post för källor vars villkor förbjuder kommersiell användning eller vidaredistribution av härledda kartor.
ODbL och Kshana-utgåvor. En ADS-B-fil per cell som görs av adsb.lol-data är en Derived Database och släpps under ODbL 1,0; dess fält licence säger det. Kshanas egen kod förblir AGPL-3.0. Kommersiella utgåvor av Kshana som skriver sådana filer bär samma notis, och den som återpublicerar filen måste behålla den. ADS-B- och AIS-resultat kombineras aldrig i en fil, så ODbL fäster inte vid AIS-lagret.
Täckningsbias. Kartor ärver sin källas täckning. adsb.lol följer frivilliga mottagare, så öppet hav och glest täckta regioner är glesa. Kystverkets öppna data utelämnar fiskefartyg under 15 m och fritidsbåtar under 45 m, så dess karta speglar större fartyg. MarineCadastre täcker bara amerikanska vatten.
Identifierare. Indataraderna bär en identifierare för flygplan eller fartyg. Den hashas i minnet med ett slumpmässigt salt per körning, används bara för att räkna distinkta flygplan eller fartyg och skrivs, loggas eller skrivs ut aldrig. Utdata är aggregerade: ingen identifierare förekommer någonstans i dem.
Undertryckning. En cell med färre än 5 distinkta flygplan eller fartyg observerade den dagen publiceras inte alls, och för AIS rapporteras ett flaggat antal på ett eller två i en publicerad cell som null. Inget publicerat värde kan peka ut ett flygplan eller ett fartyg.
Indataformat#
Vanlig CSV med en rubrikrad, kommaseparerad, utan citattecken, UTC-tider. Kolumnordningen är fri; okända kolumner ignoreras. En tidsstämpel är Unix-sekunder eller YYYY-MM-DDTHH:MM:SS[.fff]Z. Rader som inte kan tolkas räknas i utdatans metadata, och tappas inte tyst.
ADS-B (kshana interference-map adsb):
| Kolumn | Krävs | Betydelse |
|---|---|---|
timestamp |
ja | rapporttid |
aircraft_id |
ja | ogenomskinlig identifierare (hashas, sparas aldrig) |
lat, lon |
ja | grader |
alt_baro_ft |
ja | höjd i fot; ground eller tomt utesluter raden |
nic, nacp |
minst en | heltal 0 till 11; tomt betyder inte rapporterat |
source_type |
nej | om närvarande används bara värden som börjar med adsb (MLAT, TIS-B och liknande utesluts) |
adsb.lol readsb-historik, läst direkt. De dagliga arkiven är en delad tar av readsb-spårfiler. Packa upp ett som utgivaren beskriver (sammanfoga delarna, tar -xf -) och ge sedan Kshana den uppackade katalogen, en enskild trace_full_*.json-fil eller en CSV:
kshana interference-map adsb extracted-day/ --dataset adsb-lol --out maps/
En katalog genomsöks rekursivt efter trace_full_*-filer (andra filer, såsom trace_recent_*, ignoreras och symboliska länkar följs inte). Varje fil är gzip-komprimerad eller vanlig JSON, vilket avgörs av dess första byte, eftersom readsb skriver gzip under ett namn med .json; dekomprimeringen begränsas till 512 MiB per fil. Från varje spårpost läser Kshana tidsförskjutningen, latitud, longitud, höjd (markören ground utesluter posten), fälten nic och nac_p i flygplanets detaljobjekt samt positionskällans sträng (poster från något annat än ADS-B utesluts). En post utan detaljobjekt har inga noggrannhetsfält och räknas som utesluten. En fil som inte kan läsas räknas i trace_files_unreadable i utdatans metadata och hoppas över.
AIS (kshana interference-map ais):
| Kolumn | Krävs | Betydelse |
|---|---|---|
timestamp |
ja | rapporttid |
vessel_id |
ja | ogenomskinlig identifierare (hashas, sparas aldrig) |
lat, lon |
ja | grader; AIS-värdena ”inte tillgängligt” och (0, 0) kasseras |
sog_kn |
nej | fart över grund i knop; 102,3 (inte tillgängligt) behandlas som saknat |
Detektorn för land behöver en landpolygonfil (--land): GeoJSON Polygon eller MultiPolygon. Natural Earths landlager i 1:10 miljoner (allmän egendom) är den avsedda filen. Utan --land är detektorn av och utdata säger det. För att ladda ned den (den enda nätverksåtkomsten i den här funktionen):
kshana interference-map fetch-land --out ne_10m_land.geojson --allow-network
Detta kör systemets curl (som en argumentlista, inte via ett skal) över HTTPS, en gång, för en fil på en fast adress som namnger en enda incheckning i uppströmsförrådet. Nedladdningen behålls bara om dess SHA-256 är lika med värdet som är fastlåst i koden; en avvikelse raderar den och misslyckas. Om curl inte är installerat säger kommandot det och anger adressen och kontrollsumman så att filen kan hämtas för hand. Ingenting medföljer i förrådet.
Utdata#
En GeoJSON-fil per källa och UTC-dag, i katalogen --out, med namnet <source>-<dataset>-<YYYY-MM-DD>.geojson, där <source> är adsb eller ais, <dataset> är nyckeln --dataset (adsb-lol, noaa-marinecadastre, kystverket eller custom) och datumet är rapporternas UTC-dag: adsb-adsb-lol-2026-03-01.geojson, ais-kystverket-2026-03-01.geojson. Datamängden finns i namnet så att två datamängder av samma typ inte kan dela en fil, och Kshana skriver aldrig över en fil: om något mål finns misslyckas kommandot innan något skrivs. CLI skriver ut en rad per fil som skrivs. En läsare kan återskapa de tre delarna med ^(adsb|ais)-(.+)-(\d{4}-\d{2}-\d{2})\.geojson$; samma information finns inuti filen (source_kind, data.dataset, date). Syntetiska exempelfiler, en per källa, finns i examples/interference-map/output/, med kommandot som återskapar dem, för att bygga och testa en visare. En medlem på toppnivå, kshana_interference_map, innehåller schemanamnet, datum, rutnät, metod-id och varje parameter, siffrorna på dagsnivå, datalicensen och källangivelsen samt en notis. Varje objekt är en cellpolygon med cell_i, cell_j, status, degraded och de aggregerade antalen.
Rutnätet är fast: kvadratiska celler på --cell-deg grader (standard 0,5) i latitud och longitud, indexerade från (-90, -180). Bredden öst–väst krymper med latituden: cirka 55 km vid ekvatorn och cirka 28 km vid 60 grader för standardvärdet. Latitud 90 hör till den sista raden och longitud 180 är samma meridian som -180. De förhandsregistrerade metoderna är definierade på rutnätet med 0,5 grader. Ett annat --cell-deg körs, men är inte den förhandsregistrerade metoden: CLI säger det, och filen registrerar grid.preregistered_cell_deg och grid.is_preregistered (false) så att en visare också kan säga det.
Undanhållna antal. Varje antal per cell under publiceringsminimum (5) är null, noll inräknat, så null betyder aldrig ”inga” och inget publicerat tal kan peka ut ett flygplan eller ett fartyg. Fälten status och degraded anges fortfarande. I ADS-B-filer är aircraft_observed alltid minst 5 för en publicerad cell; aircraft_sampled och aircraft_affected är null under 5, och affected_share är null om inte båda är minst 5 (en andel skulle avslöja ett undanhållet antal). I AIS-filer är varje post i vessels_flagged null under 5.
Formatversion och fält#
Formatet är fastställt som schema: "kshana-interference-map/v1", format_version: 1. En ändring som tar bort eller byter namn på ett fält, eller ändrar vad ett fält betyder, höjer versionen; att lägga till ett fält gör det inte, så en läsare måste ignorera fält den inte känner till. Ett antal som är null är undanhållet, inte noll.
FeatureCollection
kshana_interference_map
schema, format_version, kshana_version, notice
source_kind "adsb" | "ais"
date "YYYY-MM-DD" (UTC)
grid { type: "fixed_lat_lon", cell_deg, preregistered_cell_deg, is_preregistered }
method { id, summary, parameters{...}, guards[], input_stats{...}, caveats[] }
day day-level figures (ADS-B: background_evaluated, background_share,
day_confounded, cells_published, cells_suppressed_below_min_distinct;
AIS: on_land_detector, cells_published, cells_suppressed_...)
data { dataset, name, licence, licence_url, attribution, coverage_notes[] }
features[] Polygon (one closed ring, [lon, lat], counter-clockwise)
properties cell_i, cell_j, status, degraded,
ADS-B: aircraft_observed, aircraft_sampled|null, aircraft_affected|null,
affected_share|null
AIS: vessels_observed, vessels_flagged{detector: n|null}, detectors[]
Värden för status: ADS-B degraded, not_degraded, insufficient_sample, withheld_day_confounded, withheld_no_background; AIS anomalous, not_anomalous. degraded är true endast för degraded och anomalous. Ruttexponeringsrapporten har sitt eget schema kshana-route-exposure/v1.
Observatoriet: den dagliga produkten#
kshana interference-map daily gör en UTC-dag av ADS-B-rapporter till observatoriets tre filer (GeoJSON, PNG och en JSON med incidentrapport) och ett hashmanifest, och kshana interference-map sensitivity spelar upp den dagen igen under ändringar av de förhandsregistrerade parametrarna en i taget. Kommandot upprätthåller utgivningsreglerna: minst 24 h efter att dagen slutat (--delay-hours får bara höjas), celler på 0,5 grader eller grövre, bara tre tillstånd (degraded, not_degraded, not_observed), ingen orsak tillskrivs och inga OpenSky-data. Metodnoten, filformaten och begränsningarna finns i observatory/METHOD.md. En regional körning (--bbox south,west,north,east) läser bara rapporterna i rutan och anger det i filen.
Specifikation av Studios kartsida#
För Studios kartsida, som läser in en GeoJSON-fil som användaren tillhandahåller (sidan byggs i Studios källkod, inte i det här förrådet). Ingenting laddas upp: filen läses i webbläsaren, och sidan gör inga anrop till någon datakälla.
Läsa en fil. Godta en fil bara om kshana_interference_map.schema börjar med kshana-interference-map/ och format_version är ett tal som sidan stöder; annars ska det sägas att filen inte är en Kshana-störningskarta som stöds. Läs fälten som listas ovan; ignorera okända. En fil innehåller en källa och en dag. Flera filer kan läsas in.
Celler. Rita varje objekts polygon. Färglägg efter status, och ange alltid vad varje färg betyder i en förklaring. Fyra tillstånd, av vilka inget får döljas eller slås ihop:
| Tillstånd | Betydelse | Var det kommer ifrån |
|---|---|---|
| Försämrad (eller avvikande för AIS) | en hög andel flygplan rapporterade låg noggrannhet, eller fartyg uppvisade avvikelser, den dagen | degraded är true |
| Fri | observerad med tillräckligt många flygplan eller fartyg och inte flaggad | status är not_degraded eller not_anomalous |
| Ej bedömd | observerad men inte tillräckligt många samplade flygplan, dagen var förvirrad, eller dagens bakgrund kunde inte uppskattas | status är insufficient_sample, withheld_day_confounded eller withheld_no_background |
| Inte observerad | för få flygplan eller fartyg, så cellen publicerades inte | inget objekt för den cellen |
”Inte observerad” är frånvaron av ett objekt: rita den neutralt (ingen fyllning, eller en snedstreckning), aldrig i färgen för ”fri”. Använd ett färgschema som inte enbart förlitar sig på rött mot grönt. Celldetaljer vid hovring eller markering visar antalen i properties som de anges, och varje antal null som ”undanhållet (färre än 5)”, aldrig som noll. En visare bör också säga, när grid.is_preregistered är false, att filen använder en cellstorlek utanför den förhandsregistrerade metoden.
Lager. ADS-B och AIS är separata lager med egna reglage, förklaringar och licensrader. Slå aldrig ihop dem till ett färgfält eller ett antal, rita dem aldrig som en kombinerad cell och summera aldrig deras celler. Olika dagar är olika filer: visa en dag i taget, med en dagsväljare, i stället för att lägga dagar över varandra.
Licens och källangivelse. För varje synligt lager ska du på kartan, och i varje export eller skärmbild, visa texten i data.attribution ordagrant, data.licence med en länk till data.licence_url, och data.coverage_notes. Om ett ADS-B-lager visas gäller dess ODbL-licens bara det lagret. Erbjud inte export av en kombinerad fil.
Metod. Erbjud metod-id och parametrar (method.id, method.parameters) och siffrorna för day i en detaljpanel, inklusive day_confounded (säg tydligt att ingen cell kallades försämrad på grund av dagens bakgrund) och input_stats.
Förbehåll att behålla (visa filens egna method.caveats och notice, och håll den här formuleringen eller dess motsvarighet synlig vid kartan):
- En försämrad eller avvikande cell är inte ett fynd av störning. Andra orsaker finns.
- En cell utan färg observerades inte. Det är inte evidens för att området var fritt.
- Det här är en beskrivning av tidigare positionsrapporter, inte en prognos och inte en mätning av någon mottagare.
- Täckningen följer datakällan; läs täckningsanmärkningarna.
Sidan får inte namnge eller visa något enskilt flygplan eller fartyg, och filerna innehåller inget.
Ruttexponering. Om sidan också läser in en kshana-route-exposure/v1-rapport ska den visa dess rader per dag och källa med de fyra andelarna (försämrad, fri, ej bedömd, inte observerad) tillsammans, aldrig enbart den försämrade andelen, plus rapportens caveats och varje rads map_licence och map_attribution.
Sändarområde (interference-map locate)#
kshana interference-map locate uppskattar var en störkälla kan finnas utifrån samma öppna ADS-B- eller AIS-rapporter: ett område vid angivna konfidensnivåer, en tyngdpunkt med en osäkerhetsellips och sessionerna i tid. Den returnerar aldrig en enskild punkt. MODELLED (registerrad VM-bc70cb57): fysiken är lärobokens radiosikt, områdenas trovärdighet är villkorad av modellen, och den enda externa kontrollen är Jammertest-jämförelsen som förhandsregistrerades i emitter-region/PREREGISTRATION.md. Att publicera sändarområden i det publika observatoriet är ett separat beslut av ägaren och är avstängt: observatoriet läser inte den här modulen, och ett test låser fast det.
kshana interference-map locate input.csv --source adsb --dataset adsb-lol --out regions/
kshana interference-map locate day-dir/ --source adsb --dataset adsb-lol --out regions/ # readsb traces
kshana interference-map locate ais.csv --source ais --dataset kystverket --land land.geojson --out regions/
Alternativ: --levels 0.5,0.9,0.95, --cell-km, --session-gap-min, --emitter-height-m min,max, --ship-height-m (AIS), --tdoa fix.json (sammanväg en TDOA-positionsbestämning; nedan). Varje alternativ som avviker från det förhandsregistrerade värdet anges som "inte den förhandsregistrerade metoden". Filer skrivs aldrig över.
Modell. Rapporter delas in i enheter (ett flygplan eller fartyg i en 2-minutersbin), var och en påverkad (ADS-B: minst hälften av dess rapporter har låg NIC eller NACp enligt kartans egen regel; AIS: en orimlig fart eller ett hopp, eller en position inåt land från kustlinjen) eller inte. Ett flygplan eller fartyg räknas bara med minst 5 goda rapporter i indata (samma skydd för utrustningens baslinje som kartan). Påverkade enheter grupperas i sessioner: ett glapp på mer än 30 minuter delar i tid, och inom ett tidskluster hör två enheter ihop när en sändare kunde nå båda. För en session får varje kandidatposition på ett rutnät en sannolikhet:
- Radiosikt. Ett flygplan på höjden
hoch en sändarantenn påh_eser varandra ut till4.122 (sqrt h + sqrt h_e)km på en 4/3-jordradie.h_emarginaliseras över 2 till 100 m (8 logaritmiskt fördelade värden). - Effekt. Sändarens effekt är okänd, så en effektiv räckvidd från 12 km till 426 km (steg om 1,25) eller "endast radiosikt" begränsar räckvidden, marginaliserad med lika vikt. Räckviddens kant är mjuk: en enhet räknas som inom räckhåll med en vikt som faller linjärt över 15 % av räckvidden på varje sida (minst tre fjärdedelar av en rutnätscell), eftersom terräng, antennmönster och väg inte är kända bättre än så.
- Påverkade och opåverkade. Ett flygplan eller fartyg är mottagligt med sannolikheten 0,6 (mottagarutrustning, antenn och signalväg skiljer sig åt), en enhet hos ett mottagligt inom räckhåll är påverkad med sannolikheten 0,9, och varje annan enhet är påverkad med bakgrundssannolikheten 0,03 (andra orsaker). Mottaglighet är en dold egenskap hos flygplanet, summerad bort per flygplan, liksom ett bestående utrustningsfel (sannolikhet 0,03: alla det flygplanets enheter är påverkade var det än befinner sig), vilket hindrar en felaktig transponder från att dra området ur läge. Så ett påverkat flygplan drar posteriorn mot positioner som når det, och ett opåverkat flygplan med radiosikt trycker emot positioner som skulle ha nått det med högst ett flygplans tyngd, hur många rapporter det än skickade, medan ett opåverkat flygplan utan radiosikt inte säger någonting.
- Terrängfritt. Terräng, kanalisering och diffraktion modelleras inte (terräng kan bara ta bort radiosikt).
- Temperering. Log-likelihooden multipliceras med 0,3 (en potensposterior). Modellens evidens är mer beroende och dess kanter mindre skarpa än det oberoende som likelihooden förutsätter, och på syntetiska data med de bristerna höll de otempererade områdena den verkliga källan klart under sin angivna andel; 0,3 valdes enbart på syntetiska data (härledningen finns i
docs/emitter-region/PREREGISTRATION.md, avsnitt 8).
Posteriorn ger områden med högst täthet vid de angivna nivåerna (nästlade; polygoner med hål där det behövs), den posteriorviktade tyngdpunkten och dess momentellips (skalad till 95 % under en gaussfördelning; polygonerna, inte ellipsen, är de kalibrerade nivåerna). Rutnätet är grovt (omkring 5 till 10 km) över hela området och varje grov cell som håller massa delas 4 gånger 4. Täckningsbias hanteras genom att betinga på var rapporter finns: ett område är brett där få flygplan fanns, och en session vars 95 %-område fyller mer än 80 % av sitt sökområde redovisas som unconstrained utan tyngdpunkt.
Sessioner och profil. Varje publicerad session har start, slut, varaktighet, arean av de 0,5-gradersceller som håller en påverkad enhet och minst 5 skilda flygplan eller fartyg, antalen skilda påverkade och observerade, och motbeviset (skilda opåverkade med radiosikt till tyngdpunkten; undanhållet under 5). En session med färre än 5 skilda påverkade flygplan eller fartyg undanhålls och räknas. Profilen ger, per UTC-timme på dygnet, de skilda påverkade flygplanen (null under 5) och minuterna av sessionstid, samt timmar av sessionstid per UTC-dygn.
Valfri TDOA-fusion. --tdoa fix.json tar {"receivers": [[lat, lon, height_m], ...], "tdoa_s": [...], "sigma_s": 1e-7, "start": [lat, lon]} (minst tre mottagare; tdoa_s[i] är mottagare i+1 minus mottagare 0). Positionen löses på jordytan med Gauss-Newton på geolocation::tdoa_predict, dess kovarians är geolocation::tdoa_crlb_on_sphere, och gaussfördelningen multipliceras in i posteriorn. Cramer-Rao-gränsen är en undre gräns för en modell, inte en uppmätt noggrannhet.
Utdata (emitter-<source>-<dataset>-<day>): .geojson (MultiPolygon-område per nivå och session, ellipspolygonen, tyngdpunktspunkten som bär sin ellips), -summary.json, -sessions.csv, -figure.svg. Var och en bäddar in datamängdens licens, licens-URL och tillskrivning, metod-id:t kshana-interference-map/emitter-region/v1, varje parameter, antagandena och begränsningarna, och bär sin evidensetikett (nivå MODELLED, registerradernas id; remsan under figuren, # evidence-rader i tabellen, en post evidence i JSON). Maskinfiler är på engelska oavsett språk; figurens text och raderna på kommandoraden lokaliseras. Ett syntetiskt exempel finns i examples/emitter-region/ (regenerate.sh).
Integritet och formulering. Inget id för flygplan eller fartyg förekommer i någon utdata; ingen rapportposition ritas; en session kräver minst 5 skilda flygplan eller fartyg; antal under 5 är null. Formuleringen är neutral: "uppskattat sändarområde", "område för störkälla". Ett område är ingens position, är inte ett fynd av orsaken och säger ingenting om vem eller vad som står bakom en källa; det utökade formuleringstestet kontrollerar utdata efter ord om aktörer, avsikt och konflikt.
Begränsningar. Trovärdigheten är villkorad av modellen. På syntetiska data (en generator som delar modellen, med räckviddskanter som är osäkra med 15 % per flygplan, bestående utrustningsfel, okänd effekt och okänd antennhöjd) höll 95 %-området den verkliga källan i 0,99 (flygplansgeometri) och 1,00 (fartygsgeometri) av sessionerna och 50 %-området i omkring 0,77: nivåerna är konservativa, genom likelihood-exponenten 0,3, och tyngdpunktsfelet för en session har en median på 23 km (flygplan) och 12 km (fartyg). Kalibreringen kontrolleras bara på syntetiska data; Jammertest-jämförelsen förhandsregistrerades (emitter-region/PREREGISTRATION.md) och kördes en gång: NOT ASSESSABLE för båda källorna (emitter-region/RESULTS.md). En källa per session; flera närliggande källor ser ut som en. En regional orsak (ett konstellationsavbrott, rymdväder) ger ett område som inte är en källa. ADS-B ger få rapporter utanför tätt trafikerat luftrum, och bara ungefär en fjärdedel av spårpunkterna i readsb bär NIC och NACp, så glesa områden ger breda eller inga områden (31 % av sessionerna med fartygsgeometri var unconstrained).
ADS-B-metod (kshana-interference-map/adsb/v2)#
Varje ADS-B-rapport från luften bär två självbedömda fält för navigeringskvalitet: NIC (positionens inneslutningsradie) och NACp (noggrannhetsgränsen på 95%, EPU). När mottagaren ombord förlorar eller misstror sin satellitpositionsbestämning sjunker båda, och därför bär de en signatur av störning. De sjunker också av andra orsaker.
Förhandsregistrerade parametrar (konstanter i koden, skrivna i varje fil; en ändring innebär en ny metodversion):
| Parameter | Värde |
|---|---|
| Höjdgolv | barometrisk höjd på minst 5000 ft |
| Rapport med låg noggrannhet | NACp högst 6 (den rapporterade EPU-gränsen är 556 m, 0,3 NM, eller större, eller okänd) eller NIC högst 5 (den rapporterade inneslutningsradiegränsen är 1852 m, 1 NM, eller större, eller okänd) |
| God rapport | NACp minst 8 och NIC minst 7; bedöms på de fält som indata har (båda när båda finns, annars det som finns) |
| Utrustningsbaslinje | ett flygplan räknas i en cell bara med minst 5 goda rapporter utanför den cellen samma dag |
| Samplade flygplan i en cell | minst 3 rapporter i cellen |
| Påverkade flygplan i en cell | minst 50% av dess rapporter i cellen har låg noggrannhet |
| Minsta urval | minst 10 samplade flygplan |
| Försämrad | minst 5 påverkade flygplan, en påverkad andel av samplade flygplan på minst 0,30, och minst 0,15 över dagens mediancellandel |
| Förvirrad dag | mediancellandel (över minst 5 celler med fullt urval) minst 0,15: ingen cell förklaras försämrad |
| Ingen bakgrund | färre än 5 celler med fullt urval, så medianen kan inte uppskattas: en cell som uppfyller tröskelvärdena är withheld_no_background, inte försämrad |
| Publiceringsminimum | minst 5 distinkta flygplan observerade |
De här värdena sattes utifrån definitionerna av NIC- och NACp-koderna och utifrån integritetsregeln innan några data hade tittats på. De trimmades inte på verkliga data, och testerna använder bara syntetiska data. Cellstatus: degraded, not_degraded, insufficient_sample (publicerad men färre än 10 samplade flygplan), withheld_day_confounded och withheld_no_background.
Version 2. Version 1 förklarade en cell försämrad från så få som 3 påverkade flygplan, färre än publiceringsminimum på 5 flygplan, och hoppade över kontrollen av dagens bakgrund utan att säga det när färre än 5 celler var fullt samplade. Version 2 kräver minst 5 påverkade flygplan och undanhåller bedömningen (withheld_no_background) när bakgrunden inte kan uppskattas. Båda ändringarna skärper metoden (inget som inte var försämrat i version 1 är försämrat i version 2); skälet är att en publicerad bedömning aldrig får vila på färre flygplan än det antal under vilket antal undanhålls. Filer av version 1 släpptes inte.
Varför noggrannhetsfälten sjunker av andra orsaker än störning, och skyddet mot var och en:
| Orsak | Skydd |
|---|---|
| Äldre transpondrar som aldrig rapporterar NIC eller NACp, eller rapporterar dem med ett fast lågt värde | utrustningsbaslinjen: ett flygplan utan goda rapporter någon annanstans den dagen räknas inte |
| Låg höjd och verksamhet på marken (terrängskuggning, andra positionsformat) | höjdgolv; rader markerade ground utesluts |
| MLAT eller andra positioner som inte kommer från GNSS | filtret source_type när kolumnen finns |
| Ett flygplan som skickar många rapporter | distinkta flygplan räknas, inte rapporter |
| Ett avbrott i en konstellation eller förstärkning, eller en rymdväderhändelse, som sänker noggrannheten över ett stort område | cellen måste överstiga dagens mediancellandel med en marginal, och en dag vars median i sig är hög markeras som förvirrad och förklarar ingen cell |
| Ett fel i ett enskilt flygplans utrustning | kräver en andel av många distinkta flygplan, med ett minsta urval |
| Få flygplan i cellen | minsta urval; under 5 observerade publiceras inte cellen |
Vad som återstår: metoden kan inte skilja störning från en regional orsak som är lokal snarare än utbredd (en lokal satellitgeometrieffekt eller ett avbrott i markbaserad förstärkning skulle se likadant ut), och den är försiktig i en riktning: ett flygplan som flyger enbart inom ett påverkat område hela dagen har ingen baslinje och räknas inte, så ihållande stora områden underrapporteras.
AIS-metod (kshana-interference-map/ais/v2)#
Per fartyg och dag, fem detektorer. En detektor kvalificerar i en cell när den flaggar minst 5 distinkta fartyg som utgör minst 20% av de fartyg som observerats där; cellen är anomalous om någon detektor kvalificerar.
| Detektor | Regel (förhandsregistrerad) |
|---|---|
on_land |
minst 3 rapporter i cellen mer än 2000 m inåt land från den angivna kustlinjen |
circle |
ett fönster med 20 på varandra följande rapporter (stride 10, luckor på högst 30 min) vars medelradie från tyngdpunkten är 500 m till 20 km, variationskoefficient för radien på högst 0,15, en färdriktning med total vridning på minst 270 grader (steg på högst 90 grader, netto minst 80% av totalen) och medelfart på minst 2 kn |
implausible_jump |
minst 2 hopp som anländer i cellen: på varandra följande rapporter minst 1000 m från varandra, högst 1 h emellan, vilket innebär mer än 70 kn (den underförstådda farten använder minst 1 s mellan rapporterna, så två rapporter med samma tidsstämpel och positioner 1 km eller mer från varandra räknas som ett hopp) |
implausible_speed |
minst 3 rapporterade farter över 70 kn i cellen |
same_position |
minst 5 distinkta fartyg som rapporterar samma position (avrundad till 1e-4 grader, cirka 11 m) i samma 10-minutersfönster |
Celler med färre än 5 distinkta fartyg publiceras inte; varje flaggat antal under 5, noll inräknat, rapporteras som null.
Version 2. Version 1 kvalificerade en detektor från 3 flaggade fartyg och publicerade antal på 3 och 4. Version 2 höjer minimum för flaggade fartyg till 5, publiceringsminimum, så att en anomalous-bedömning aldrig vilar på färre fartyg än det antal under vilket antal undanhålls. Det skärper metoden och ingen fil av version 1 släpptes.
Kända orsaker till falska positiva, som andelsregeln och tröskelvärdena minskar men inte tar bort: fartyg i floder, kanaler och hamnar nära en grov kustlinje (bufferten på 2 km inåt land finns för detta); två fartyg som delar en identifierare, vilket ser ut som hopp; transpondrar med dålig positionsbestämning eller testutrustning; och drivande lodsbåtar och sökfartyg, som kan likna cirklar. En kustlinjefil i 1:10 miljoner är noggrann till cirka en kilometer.
Hopp- och fartdetektorerna jämför rapporter inom en indatafil; ett spår som delas över filer eller dagar sys inte ihop.
Minne. Indata läses rad för rad och hålls aldrig i sin helhet. ADS-B behåller bara räknare per flygplan och cell. AIS behåller varje godtagen rapport i en kompakt post (cirka 40 bytes) tills dess dag har utvärderats, så minnet växer med antalet AIS-rapporter i indata; dela upp en mycket stor AIS-indata per dag.
Ruttexponering#
kshana route-exposure --route route.geojson --map out/ [--map other/] \
[--from 2026-03-01] [--to 2026-03-07] [--out report.json] [--json]
--route är en GeoJSON LineString (ensam, i en Feature eller i en FeatureCollection) eller en CSV med lat,lon-rader. --map tar kartfiler eller kataloger med dem, och får upprepas. Vägpunkter förbinds med raka linjer i latitud och longitud, så förtäta långa sträckor; en sträcka tar den korta vägen runt i longitud, så en som korsar antimeridianen (179,5 E till 179,5 W) korsar den. Rutten delas upp i delar om cirka 250 m. Varje del mäts mellan sina egna två ändpunkter på en sfär med radien 6371,0088 km (samma väg som avgör vilken cell den ligger i) och tilldelas den cell som rymmer dess mittpunkt.
Per dag och källa anger rapporten ruttlängden och fyra andelar som summerar till 1: share_degraded, share_not_degraded, share_unassessed (cellen finns men saknar bedömning) och share_not_observed (cellen saknas på kartan). Läs de två sista tillsammans med den första: en rutt med låg försämrad andel och hög andel inte observerat har inte visats vara fri. ADS-B- och AIS-rader redovisas separat och kombineras aldrig. Varje rad bär kartans licens och källangivelse.
Biblioteksfunktioner#
För anropare som håller data i minnet (bindningar, MCP-servern, webbläsarbygget) exponerar modulen kshana::interference_map::api samma metoder med text eller bytes in och JSON ut, utan att röra någon fil eller något nätverk:
| Funktion | In | Ut |
|---|---|---|
adsb_maps_from_csv(csv, &DatasetSpec, cell_deg) |
ADS-B CSV-text | Vec<DayMap> |
adsb_maps_from_readsb_traces(&[&[u8]], &DatasetSpec, cell_deg) |
en byte-slice per readsb-spårfil (gzip eller vanlig) | Vec<DayMap> |
ais_maps_from_csv(csv, &DatasetSpec, cell_deg, Option<&str>) |
AIS CSV-text, valfri GeoJSON-text för land | Vec<DayMap> |
route_exposure(route_text, &[&str], from, to) |
ruttext, GeoJSON-texter för kartor, valfria YYYY-MM-DD-gränser |
kshana-route-exposure/v1 JSON |
En DayMap har file_name (<source>-<dataset>-<date>.geojson), date och geojson (v1-dokumentet). DatasetSpec är Preset("adsb-lol" | "noaa-marinecadastre" | "kystverket") eller Custom { licence, licence_url, attribution }; DEFAULT_CELL_DEG är 0,5. Fel är MapError. Reglerna för datamängder (godkända förinställningar, licenstext krävs, typen måste stämma) gäller exakt som på kommandoraden.
Extern validering#
tests/interference_map_reference.rs jämför Kshana med oberoende implementationer på syntetiska indata, med toleranser som förhandsregistrerats i tests/fixtures/interference_map_ref/PREREGISTRATION.md: betydelsen av NIC- och NACp-koder mot pyModeS-avkodning av syntetiska ADS-B-ramar, AIS-värden för ”inte tillgängligt” mot pyais-avkodning av syntetiska AIVDM-meningar, tilldelning av rutnätsceller mot shapely, ruttlängd per celltillstånd mot shapely och GeographicLib, och maskning av inlandet mot shapely och pyproj. Testdata görs av scripts/gen_interference_map_ref.py; CI behöver inget Python. Det här validerar hur koderna och fältvärdena läses och geometrin. Det validerar inte att en flaggad cell är störning.
Tester#
Alla tester använder syntetiskt genererade data och inget nätverk: enhetstester i src/interference_map/, och tests/interference_map_cli.rs för kommandona från början till slut, inklusive att ingen identifierare når en utdata och att vägranden inte lämnar några filer efter sig.