Maskinöversättning, inte granskad av en modersmålstalare. Engelska är referensen.

Mottagarförtroende och sjöfartRedigera på GitHubKälla: docs/RECEIVER-TRUST.md

Mottagarförtroende: bedöma en verklig logg från en GNSS-mottagare

kshana receiver-trust läser en logg från en verklig mottagare för globala satellitnavigeringssystem (GNSS), kör förtroendeövervakare över den epok för epok och säger när och varför mottagarens positionsbestämning slutade vara tillförlitlig. Den kan också poängsätta loggen mot händelser och prediktioner som du anger före körningen: om varje händelse upptäcktes i tid och om ett modellerat fall i bärvåg-till-brusdensitet (C/N0) stämmer överens med det som mottagaren mätte.

Observationerna är mottagarens egna; övervakarna och deras trösklar är motorns och dina. Varje resultat bär den etiketten, loggens SHA-256 och varje tröskel som det kördes med, så en körning kan upprepas och granskas.

För ett fartyg under gång, med en levande poäng och en valfri grind framför ett sjökortssystem, se MARITIME-TRUST.md.

Mottagarens egen spoofingflagga mot Kshanas larm, från en verklig körning av motor v0.40.0 på en påhittad UBX-logg (200 epoker vid 1 Hz). C/N0 faller 20 dB vid 80 till 90 s och 120 till 130 s; mottagaren flaggar 120 till 130 s och 160 till 165 s. Av 140 epoker som jämfördes efter kalibrering flaggade båda i 11, bara mottagaren i 6, bara Kshana i 11 och ingen av dem i 112. Ingen av sidorna är referens och samstämmighet är inte validering. Rådgivande: analysutdata från ett forsknings- och teknikverktyg, inte typgodkänd navigationsutrustning och inte en safety-of-life-tjänst.Mottagarens egen spoofingflagga mot Kshanas larm, från en verklig körning av motor v0.40.0 på en påhittad UBX-logg (200 epoker vid 1 Hz). C/N0 faller 20 dB vid 80 till 90 s och 120 till 130 s; mottagaren flaggar 120 till 130 s och 160 till 165 s. Av 140 epoker som jämfördes efter kalibrering flaggade båda i 11, bara mottagaren i 6, bara Kshana i 11 och ingen av dem i 112. Ingen av sidorna är referens och samstämmighet är inte validering. Rådgivande: analysutdata från ett forsknings- och teknikverktyg, inte typgodkänd navigationsutrustning och inte en safety-of-life-tjänst.

Kör den#

kshana receiver-trust examples/receiver-trust/session.toml

Detta skriver session.result.json, session.trust.csv (en rad per epok) och session.trust.svg (medel-C/N0 över tid med förtroendetillståndet under) bredvid scenariot och skriver ut en utlåtanderad. Exempelloggen är syntetisk, gjord för att visa formatet; peka path på din egen mottagares logg.

Förtroendepoäng över en syntetisk överfart, från en verklig körning av motor v0.40.0 på examples/maritime-trust (en påhittad NMEA-logg för en färja på rutten Tallinn till Helsingfors, 3001 epoker vid 1 Hz). Tre fält delar en tidsaxel. Överst: avståndet mellan den position mottagaren rapporterar och fartygets verkliga position, som håller sig inom några meter till ungefär 1576 s, då loggens skriptade bortdragning av positionen drar den bort, medan mottagaren fortsätter att rapportera en giltig positionsbestämning. I mitten: förtroendepoängen från 0 till 100, inte beräknad under de första 300 s av kalibreringen, i det nominella bandet (minst 90) fram till bortdragningen, och sedan fallande genom det degraderade bandet (minst 55) ner i det opålitliga bandet. Längst ned: varje epoks band som ett färgat band med sitt namn. Poängen är rådgivande. Rådgivande programvara, inte typgodkänd navigationsutrustning (IEC 61108, IEC 61162): operatören är fortsatt ansvarig för fartygets navigering. Loggen är påhittad för att visa formatet och övervakarna; den är ingen mätning och säger ingenting om hur någon mottagare skulle prestera.Förtroendepoäng över en syntetisk överfart, från en verklig körning av motor v0.40.0 på examples/maritime-trust (en påhittad NMEA-logg för en färja på rutten Tallinn till Helsingfors, 3001 epoker vid 1 Hz). Tre fält delar en tidsaxel. Överst: avståndet mellan den position mottagaren rapporterar och fartygets verkliga position, som håller sig inom några meter till ungefär 1576 s, då loggens skriptade bortdragning av positionen drar den bort, medan mottagaren fortsätter att rapportera en giltig positionsbestämning. I mitten: förtroendepoängen från 0 till 100, inte beräknad under de första 300 s av kalibreringen, i det nominella bandet (minst 90) fram till bortdragningen, och sedan fallande genom det degraderade bandet (minst 55) ner i det opålitliga bandet. Längst ned: varje epoks band som ett färgat band med sitt namn. Poängen är rådgivande. Rådgivande programvara, inte typgodkänd navigationsutrustning (IEC 61108, IEC 61162): operatören är fortsatt ansvarig för fartygets navigering. Loggen är påhittad för att visa formatet och övervakarna; den är ingen mätning och säger ingenting om hur någon mottagare skulle prestera.

Figuren ovan är fartygsdemon i MARITIME-TRUST.md: en påhittad logg, en rådgivande poäng.

Samma scenario kan köras från Python (kshana.receiver_trust(toml)), från WebAssembly-paketet (receiver_trust(toml), med loggen inbäddad) och från verktyget assess_receiver_log i Model Context Protocol-servern (MCP).

Loggar den läser#

format Källa Vad som läses
ubx u-blox binär NAV-SAT C/N0, elevation och azimut per satellit, NAV-PVT position, MON-RF automatisk förstärkningsreglering (AGC) och jamming-indikatorn jamInd, NAV-TIMEGPS vecka samt mottagarens egna flaggor: NAV-STATUS spoofDetState och SEC-SIG (self_report, se RECEIVER-PROTOCOLS.md)
rinex RINEX 3-observationsfil S-koder (C/N0) per satellit och signal; med en sänd navigeringsfil (nav) pseudoavstånden för motorns egen positionsbestämning
android CSV från Android GnssLogger Raw-rader: C/N0 och AgcDb per satellit; Fix-rader: position
nmea NMEA 0183-text GSV signal-brusförhållande per satellit (dB-Hz, med eller utan signal-ID 4,10) och dess elevation och azimut, GSA geometrisk försämring av precisionen och använda satelliter, GGA och RMC tid och position
sbf Septentrio binär (0,38, endast läsning) PVTGeodetic position, MeasEpoch C/N0 per satellit och signal, RFStatus antal band; se RECEIVER-PROTOCOLS.md
rtklib-pos Lösningsfil från RTKLIB (.pos) tid, position (latitud/longitud eller ECEF, omräknad) och använda satelliter per epok; filer med grader-minuter-sekunder avvisas med ett meddelande
novatel NovAtel OEM7 ASCII- eller binärloggar BESTPOS position (bara beräknad lösning), RANGE C/No per satellit och signal; RXSTATUS-flaggor för jammer blir epokens self_report (jamming-tillstånd 2 när mottagaren flaggar en jammer, 1 när den inte gör det; det finns ingen flagga för spoofing i RXSTATUS), ställd mot Kshanas larm genom jämförelsen receiver-self-report
gnss-sdr Strömmarna GNSS-SDR Monitor och PVT-monitor som JSON-rader C/N0 per kanal, positionsbestämning, använda satelliter, HDOP, azimut och elevation; skapad av integrations/gnss-sdr/relay.py

Detaljer, källor och begränsningar för dessa tre: MACHINE-INPUTS.md.

Varje epok som läsarna producerar bär också source_span, [start, end) byteförskjutningar i indata: det minsta sammanhängande intervall som rymmer de poster som bidrog till den, så att exakt den råa delen kan hashas för ett händelsefönster. NMEA: varje rad som läses medan epoken är aktuell (en övermängd där en orelaterad rad ligger mellan dess meningar). UBX: epokens ramar. RINEX 3: epokposterna från varje >-rad till nästa. Android: epokens Raw-rader (en Fix-rad bara för en epok utan Raw-rader). Saknas för en levande ström och överallt där det inte är väldefinierat (RINEX 2).

Filen läggs in med path (löses mot scenariots egen mapp), eller inbäddad som text eller base64 (de enda valen i en webbläsare).

En IMU-logg som en andra sensor#

[log.imu] lägger till en tröghetslogg på samma klocka:

[log.imu]
format = "csv"          # or "euroc"
path = "imu.csv"        # or text / base64
heading0_deg = 90.0     # heading at the first IMU sample
yaw_axis_down = true    # body z down (NED/FRD); false for z up (ENU/FLU)
time_offset_s = 0.0     # added to the IMU clock to reach the log's t_s

Girhastigheten integreras från heading0_deg och fyller i kursen överallt där mottagarloggen saknar kurs, så övervakaren heading-course (som kräver heading_sensor = true på plattformen) jämför gyrokursen med kurs över grund. Ett gyro driver: kursen är bara så bra som integreringsfönstret och hdg_cog_tol_deg avgör vad som räknas som avvikelse. Layouten för csv beskrivs i MACHINE-INPUTS.md. IMU-bytes ingår i scenariots hash och i ett bevispakets scenariohash. Inbäddat (text/base64) fungerar på varje yta; en path avvisas där filer inte läses.

Plattform: stillastående eller fartyg#

Övervakarna ovan förutsätter en fast antenn. Ett scenario anger plattformen före körningen i en [platform]-tabell på högsta nivån; utan en är plattformen static och ingenting ändras.

[platform]
kind = "vessel"            # "static" (default) or "vessel"
max_speed_kn = 30.0        # default 30
max_accel_mps2 = 0.5       # default 0.5
max_turn_rate_dps = 6.0    # default 6
antenna_height_m = 18.0    # no default: without it the sea-level monitor does not run
heading_sensor = false     # true: the stream carries a gyro heading (HDT or THS)
Nyckel Standardvärde Varför det värdet
max_speed_kn 30 Över marschfarten för handelsfartyg och de flesta passagerarfartyg, så att ett verkligt fartyg aldrig når den; långt under den hastighet som en positionsavdragning innebär. Ett långsammare fartyg bör ange en lägre gräns: ju lägre gräns, desto tidigare fångas en avdragning.
max_accel_mps2 0.5 Ett stort fartyg ändrar hastighet med långt under 0,1 m/s²; ett litet snabbt fartyg når ett par tiondelar vid en kraftig gasändring.
max_turn_rate_dps 6 Ett stort fartyg svänger med långt under 1 deg/s och ett litet fartyg i en kraftig sväng med några.
antenna_height_m ingen En egenskap hos installationen; en gissning vore en dold tröskel.
heading_sensor false Anges true och saknas i loggen är det ett fel, så en saknad sensor kan inte passera som en ren kontroll.

Fartygsnycklarna avvisas under kind = "static". För ett fartyg körs inte övervakaren position-jump, eftersom den mäter avstånd från kalibreringsmedelvärdet, vilket blir fel på en antenn i rörelse; resultatets monitor_config registrerar plattformen och gränserna som användes.

De syntetiska NMEA-strömmarna från kshana nmea-scenario, gjorda för besättningsträning, accepteras av NMEA-läsaren och kan köras genom den här typen som vilken NMEA-logg som helst.

Övervakare#

Varje övervakare behöver sina data; en övervakare vars data inte finns i loggen körs inte och förtecknas inte i monitors_run. De första calibration_s sekunderna (standard 60) sätter baslinjen och larmar aldrig.

Monitor Larmar när Behöver
cn0-drop medel-C/N0 över satelliterna som är gemensamma med baslinjen sjunker med cn0_drop_db eller mer (standard 6 dB) C/N0
loss-of-lock följda satelliter ligger sats_lost eller fler under medianen för baslinjen (standard 4) C/N0
agc AGC-värdet avviker från sin baslinje med mer än agc_k_sigma standardavvikelser (standard 5) UBX MON-RF eller Android AgcDb
jam-ind u-blox jamInd överstiger jam_ind_threshold (standard 80 av 255) UBX MON-RF
position-jump mottagarens egen positionsbestämning ligger mer än position_jump_m från sitt kalibreringsmedelvärde (standard 50 m) en rapporterad position
raim paritets-RAIM (autonom integritetsövervakning i mottagaren) på motorns egen enpunktspositionsbestämning förkastar mätmängden RINEX-logg med nav
solve-failure motorns enpunktspositionsbestämning misslyckas med fem eller fler satelliter RINEX-logg med nav
clock mottagarens klocka avviker från sin predikterade linje med mer än den minsta detekterbara förskjutningen för dess kalibreringsbrus RINEX-logg med nav

Kalibrerad profil (måste väljas). [monitors] profile = "jammertest-2024-calibrated" ersätter de tre störningströsklarna med värden som kalibrerats på den offentliga datamängden JammerTest 2024 (en u-blox ZED-F9P per scenario; Zenodo 15911589): cn0_drop_db = 1.5, agc_k_sigma = 3.5, jam_ind_threshold = 29. Kalibreringen förhandsregistrerades (xval/jammertest-trust/PREREGISTRATION.md) och profilen är MODELLED, anpassad på en offentlig kampanj: dess tröskel cn0_drop_db missade den förhandsregistrerade tröskeln för falsklarm i den undanhållna datamängden (0,0231 mot 0,02); trösklarna för AGC och jamming-indikator samt unionströskeln (falsklarm 0,033, detektion 0,81) nåddes (xval/jammertest-trust/RESULTS.md). Den gäller för den mottagartypen vid den händelsen, mot schemalagda attacktidsluckor, och kalibrerades på datamängdens CSV-loggar (dess UBX-loggar ger fler falsklarm i två mappar). Ett resultat som körts med profilen upprepar trösklarna som tillämpades och bär en profile_note som säger allt detta. Utan profilen gäller standardvärdena ovan och alla utdata är oförändrade.

För en vessel-plattform körs även övervakarna för plattformar i rörelse (trösklar i en [maritime]-tabell på högsta nivån, varje standardvärde dokumenterat i src/receiver_trust/maritime.rs); var och en behöver sina data och förtecknas i monitors_run bara när den har fattat ett beslut:

Monitor Larmar när Behöver
kinematic positionsändringen stämmer inte med rapporterad fart och kurs, eller innebär en fart, acceleration eller svängtakt över fartygets gränser positionsbestämningar; fart och kurs (RMC eller VTG) för dödräkningsdelen
heading-course gyrokursen och kursen över grund skiljer sig med mer än hdg_cog_tol_deg (fart över min_speed_kn) HDT-, THS- eller VHW-kurs, heading_sensor = true
speed-log farten genom vattnet och farten över grund skiljer sig med mer än stw_sog_tol_kn VHW eller VBW, och fart över grund
sea-level GGA-höjden skiljer sig från antenna_height_m med mer än sea_level_tol_m GGA-höjd, antenna_height_m
cn0-spread spridningen av C/N0 över satelliterna sjunker till cn0_spread_frac av sin kalibreringsmedian GSV
cn0-rise C/N0 för de gemensamma satelliterna steg med cn0_rise_db i genomsnitt och cn0_rise_frac av dem steg GSV
time-consistency på varandra följande epoktider hoppar oregelbundet, går bakåt eller lämnar värdens klocka NMEA-tid; värdens klocka för den sista delen
osnma mottagaren rapporterar ett autentiseringsfel för OSNMA (en rapporterad status läses; ingenting verifieras; för att verifiera OSNMA ur själva I/NAV-sidorna se docs/OSNMA.md) $PKSOS-statusmening

En epok är ej betrodd när RAIM, klockövervakaren, ett lösningsfel eller ett positionshopp larmar, eller när fallet i C/N0 når två gånger sin tröskel; försämrad vid varje annat larm; och nominell i övrigt.

Motorvägen (raim, solve-failure, clock) är samma beräkning som spoofing-orakel för JammerTest 2024 i tests/jammertest_spoof_oracle_support: tests/receiver_trust_jammertest.rs kontrollerar att det första larmet, för alla åtta publicerade starter, infaller på samma epok och är av samma slag.

Förtroendepoäng (fartygsplattform)#

För ett fartyg får varje epok efter kalibreringen också en poäng från 0 till 100 och skälen till att den inte är 100. Avbildningen är deterministisk och fastställd innan någon logg poängsätts: ingen inlärning, ingenting anpassat till händelser. Varje övervakare reducerar sitt underlag till ett kvot statistic / threshold (ett larm vid 1 eller mer); en kvot kostar poängen

points = weight * clamp((ratio - onset_ratio) / (full_ratio - onset_ratio), 0, 1)
score  = round_to_0.1( clamp(100 - sum of points, 0, 100) )

så en övervakare kostar ingenting så länge den ligger under onset_ratio av sin tröskel (standard 0,5), hälften av sin vikt vid sin tröskel och hela vikten vid full_ratio gånger tröskeln (standard 1,5); poängen är icke-växande i varje statistik. En källa som inte rapporterar vid en epok behåller sin senaste statistik under evidence_hold_s (standard 10 s: två cykler av en C/N0-mening som skickas var 5:e s), både som larm och som avdrag.

Avrundningen är uppåt vid hälften (floor(x * 10 + 0.5) / 10), bandet är det för den avrundade poängen, och begränsningen kommer före avrundningen. Bara övervakare vars poäng ligger över noll förtecknas bland avdragen, med sin kvot och sina oavrundade poäng, störst poäng först; avdrag med lika poäng förtecknas i ordningen för övervakarnas namn cn0-drop, agc, jam-ind, loss-of-lock, position-jump, raim, clock, solve-failure, kinematic, heading-course, speed-log, sea-level, cn0-spread, cn0-rise, time-consistency, osnma, geometry. En övervakare vars test bara har utfallen lyckat eller misslyckat (en misslyckad lösning, ett misslyckat autentiseringsförsök) får kvoten 1,5, hela vikten. De förtecknade poängen är de före begränsningen vid 0.

[score]
nominal_min = 90.0         # score >= 90: nominal
degraded_min = 55.0        # 55 <= score < 90: degraded; below 55: untrusted
onset_ratio = 0.5
full_ratio = 1.5
evidence_hold_s = 10.0
[score.weights]            # overrides; a monitor not listed keeps its default
sea-level = 30.0
Vikt (poäng) Övervakare Varför
70 osnma ett autentiseringsfel är ett påstående, inte en statistik
60 kinematic, raim, clock, position-jump, time-consistency en förfalskad position måste motsäga fysiken eller mottagarens egna kontroller, och tiden kan inte gå bakåt; en överträdelse med full styrka (1,5 gånger sin tröskel: 60 poäng, poäng 40) är ej betrodd, och vid sin tröskel (30 poäng, poäng 70) försämrad
40 heading-course, speed-log, solve-failure en oberoende sensor som avviker är försämrad; två med full styrka är ej betrodda
30 sea-level, cn0-spread, cn0-rise, cn0-drop signalmiljön, eller en kontroll med svagt informationsvärde
25 loss-of-lock, agc, jam-ind miljön är fientlig; det ensamt visar inte att positionsbestämningen är fel
upp till 15, [geometry] geometry (0.36) ingen vikt på den här rampen: ingenting om inte himlen är dålig, därefter upp till cap_points (15); enbart geometri når försämrad, aldrig ej betrodd, och ger inget larm (se "Geometri" nedan)

Bandgränserna följer av vikterna: den lättaste övervakaren som larmar kostar 12,5 poäng vid sin tröskel, så varje larm lämnar det nominella bandet; ingen enskild övervakare under 60 poäng kan ensam nå bandet ej betrodd (flera tillsammans kan). Resultatet registrerar poängmodellen (score_model) och varje epok bär score.deductions: vilka övervakare som drog av, deras kvoter och deras poäng. För ett fartyg är epokens tillstånd bandet för dess poäng.

Geometri: naturlig försämring skild från motsägelser som liknar attacker#

En mottagare vid en kajkran, i en sluss eller under ett högt skrov förlorar satelliter och dess positionsbestämning blir sämre av en orsak som inte är en attack. Från 0,36, enligt designanteckningen om geometri (docs/design/2026-10-12-geometry-and-skyline-design.md, avsnitt 4), bär varje epok sin satellitgeometri, har ett fartygs poäng en geometriövervakare och bär varje avdrag en klass: geometry (himlen), environment (signalmiljön) eller inconsistency (underlag som liknar en attack).

Varifrån geometrin kommer. Elevationen och azimuten för varje följd satellit (NMEA GSV, UBX NAV-SAT), ur vilka den geometriska försämringen av precisionen (DOP) härleds med motorns enda DOP-kärna (orbit::dop, VALIDATED mot gnss_lib_py): source = derived. Om det inte går, DOP och använda satelliter som mottagaren anger (NMEA GSA): source = reported. Himmelspositioner och GSA räknas under poängens evidence_hold_s (standard 10 s), eftersom många bussar skickar GSV med några sekunders mellanrum; en GSV-mängd som är ofullständig i en epok (slutet av ett utdrag, en förlorad mening) används inte. En logg med ingetdera, till exempel NMEA med bara GGA och RMC, eller Android- och RINEX-loggar i dag, får statusen unknown med anteckningen "geometri okänd": motorn gissar inte en geometri som den inte har fått, och geometriövervakaren körs inte.

geometry.status Betydelse
good tillräckligt många satelliter och DOP inom trösklarna
degraded ett eller flera skäl: few-satellites, high-pdop, high-hdop, och (upplysande, inte i poängen) sky-blocked när varje följd satellit ligger i ena halvan av horisonten
unknown loggen ger ingen satellitgeometri för den här epoken

Statusen är beskrivande och etiketten (nedan) är det som räknas för poängen: degraded omfattar det upplysande fallet sky-blocked, som kan förekomma med bra eller hygglig DOP, och bara en etikett poor poängsätts.

Etiketten (alltid redovisad, aldrig poängsatt). Varje epoks geometry.label är good (HDOP högst hdop_good 2, PDOP högst pdop_good 3 och minst used_good 6 satelliter), poor (HDOP över hdop_max 4, PDOP över pdop_max 6 eller färre än min_used 5 satelliter), fair däremellan, eller unknown. Epokens anteckning inleds alltid med etiketten och talen, till exempel "geometri hygglig: HDOP 1,105, PDOP 1,831, VDOP 1,410, 8 satelliter; inte poängsatt (poängen drar bara av över HDOP 4, PDOP 6 eller under 5 satelliter)", och lägger till ", signalförlust" när det gäller.

Geometriövervakaren (fartygspoäng). Den drar av ingenting om inte geometrin är dålig: dess kvot är max(hdop / hdop_max, pdop / pdop_max, min_used / n_used), och så länge den är högst 1 (bra eller hygglig geometri, inklusive en öppen himmel med enbart GPS och 8 satelliter) kostar den ingenting, så en sådan logg får exakt samma poäng som i 0,35. Över 1 ökar avdraget linjärt till cap_points (15) vid full_ratio (1,5 gånger trösklarna: HDOP 6, PDOP 9, 3 satelliter): 7,5 poäng vid kvoten 1,25 (HDOP 5, eller 4 satelliter), 15 från 1,5 och uppåt (poäng 85, försämrad). Ensamt kan den aldrig ta poängen under floor (standard: poängens degraded_min, 55), så enbart geometri når bandet försämrad som mest och aldrig bandet ej betrodd: taket som gäller är min(cap_points, 100 - floor), så en [score]-tabell som höjer degraded_min (en 0,35-tabell med degraded_min 90, till exempel) sänker taket till 100 - degraded_min i stället för att avvisas, och en floor som sätts under degraded_min avvisas. Övervakaren ger inget larm; den förtecknas sist i monitors_run när den fattade ett beslut vid någon epok (ett fartyg vars logg ger geometrin), och räknas inte i identiteten med 0,35; den är inte en post i [score.weights] (att ange en avvisas), och taket och golvet som gäller registreras i geometry_model.cap_in_force och geometry_model.floor_in_force. En dålig epoks anteckning säger varför, till exempel "geometri dålig: HDOP 5,200, PDOP 7,900, VDOP 4,100, 7 satelliter; försämrad av geometri: HDOP 5,200 över 4 (härledd ur 7 loggade satelliter); inte en motsägelse".

Klasser. Varje avdrag (score.deductions[].class):

Klass Övervakare
geometry geometry (dålig geometri); loss-of-lock när varje satellit som förlorats mot kalibreringens baslinje låg under low_elev_deg vid sin senaste rapport
environment cn0-drop, cn0-spread, cn0-rise, agc, jam-ind, loss-of-lock i övrigt; geometry vid signalförlust (nedan)
inconsistency kinematic, heading-course, speed-log, sea-level, time-consistency, clock, raim, position-jump, osnma, solve-failure; och geometry när geometrin är dålig och den angivna HDOP inte stämmer med den angivna himlen (nedan)

Skyddet mot en förfalskad dålig himmel. En spoofer skulle kunna skicka en tunn GSV, eller rapportera en hög HDOP, för att köpa tolerans. Motorn märker och förlåter inte: ingen annan kontroll vidgas av en dålig geometri, och den HDOP som mottagaren anger (GSA inom hållningen, annars GGA) jämförs med den HDOP som härleds ur den himmel den anger. När de skiljer sig med mer än max(reported_vs_derived_tol, reported_vs_derived_rel × derived HDOP) (1,0, eller 25 % av den härledda HDOP, vilket som är störst) bär epoken reported_derived_mismatch: true och, när geometrin är dålig, klassas dess avdrag som inconsistency. Vid bra eller hygglig geometri redovisas avvikelsen men poängsätts inte: ingenting dras av om inte geometrin är dålig. Det är ett medvetet val (0,36): "noll om inte dålig" gäller för varje epok, så bra och hygglig geometri får exakt samma poäng som i 0,35, och en förfalskad HDOP är aldrig tyst. Flaggan (reported_derived_mismatch) finns på varje epok i resultatet och varje levande rad, anteckningen säger "…utöver toleransen: redovisad, inte poängsatt (geometrin är inte dålig)" eller "…: geometriavdraget klassas som en motsägelse", geometry_summary.hdop_mismatch räknar epokerna, och sammanfattningssidan för underlaget visar antalet, även noll. De 25 % är ett REPRESENTATIVE tekniskt val, inte ett uppmätt eller standardiserat värde: en mottagare som löser för en klocka per konstellation, eller med en delmängd av de satelliter den följer (en elevationsmask, ett C/N0-snitt, en RAIM-uteslutning), anger en HDOP som skiljer sig från enklocke-HDOP för varje följd satellit med ett belopp som växer med HDOP, så en fast tolerans ensam skulle läsa naturligt dålig geometri som en motsägelse. En större skillnad läses ändå som en. Ett avdrag klassat geometry är ett påstående om himlen, inte ett konstaterande att ingen attack förekom.

Signalförlust är inte himlen. När satelliter som mottagaren listar i sikte (över low_elev_deg) inte följs härleder motorn också DOP för varje satellit i sikte. Om den DOP:en i sikte ligger inom trösklarna och antingen ingenting följs eller de ofölja satelliterna är spridda runt horisonten (inte begränsade till ena halvan av den), fanns himlen där och signalen inte: epoken bär signal_loss: true, anteckningen "satelliter i sikte men inte följda: signalmiljö, inte geometri", och geometriavdraget klassas som environment. Ofölja satelliter som är begränsade till ena halvan av horisonten läses fortfarande som en blockerad himmel (en vägg, en klippa, en kaj). En tvåsidig skymning (en kanjon eller en smal fjord) läses som signalförlust tills en horisontlinje har konfigurerats. Mottagarens signalvärden för ingen positionsbestämning är inte DOP: en angiven HDOP eller PDOP på 99 eller mer, GGA-kvalitet 0 och GSA-läge 1 ger ingen angiven DOP.

Nyckel i [geometry] Standardvärde Ursprung
hdop_max 4 vald (designanteckning 4,2): vid sigma_uere_m 1,5 m är HDOP 4 en 2drms på 12 m, den kinematiska kontrollens kin_pos_tol_m. IEC 61108-1 anges ofta ange sina noggrannhetskrav för HDOP ≤ 4 (eller PDOP ≤ 6): återgivet ur sekundär litteratur om GNSS-mottagare, ingen specifik sekundär källa konsulterad och standarden inte läst; ska kontrolleras mot standardens text
pdop_max 6 tröskeln för tillgänglighet av PDOP i scenarios/polar-arctic-leo-coverage.toml; GPS SPS Performance Standard, 5:e utg. (2020), PDOP ≤ 6, så som den anges i tests/constellation_availability_published_spec_oracle.rs; ska kontrolleras mot standardens text
min_used 5 en mer än vad en positionsbestämning behöver, så att en enskild förlust inte avslutar positionsbestämningen; det minsta antalet med en redundant mätning för RAIM
sigma_uere_m 1.5 en angiven indata för 2drms-länken i hdop_max; ange mottagarens eget värde
reported_vs_derived_tol 1,0 HDOP vald (designanteckning 4,2): den absoluta delen av toleransen; en avvikelse utöver toleransen är inte geometri
reported_vs_derived_rel 0.25 REPRESENTATIVE tekniskt val: den relativa delen, för mottagare med klockor per konstellation eller delmängdslösningar
low_elev_deg 15 designanteckning 4,3: satelliter som förloras under den förloras till himlen; en horisontlinje (0,36 punkt 1) kommer att utvidga detta
azimuth_gap_deg 180 geometrisk, upplysande: varje satellit i ena halvan av horisonten
cap_points 15 designanteckning 4,2: enbart geometri flyttar poängen från nominell till försämrad och aldrig till ej betrodd; avdrag bara när geometrin är dålig (grundarens beslut B1, 0,36)
full_ratio 1.5 poängens eget full_ratio: rampen når cap_points vid 1,5 gånger trösklarna för dålig
floor poängens degraded_min (55) enbart geometri når aldrig bandet ej betrodd; taket som gäller är min(cap_points, 100 - floor); ett golv under degraded_min avvisas
hdop_good 2 REPRESENTATIVE, bara etiketten: hälften av hdop_max (startkvoten för poängen i 0,35)
pdop_good 3 REPRESENTATIVE, bara etiketten: hälften av pdop_max
used_good 6 REPRESENTATIVE, bara etiketten: en mer än min_used, så att en enskild förlust fortfarande lämnar en redundant mätning

Vad som ändrades i utdata, och vad som inte ändrades. Ingen poäng ändras om inte geometrin är dålig; etiketten redovisas alltid. Tillagda nycklar: epochs[].geometry (status, reasons, source, n_used, hdop, pdop, vdop avrundad till 0,001, open_fraction (null tills en horisontlinje har konfigurerats), max_azimuth_gap_deg, age_s, reported_hdop, reported_derived_mismatch, note, in_view (satelliter förtecknade över low_elev_deg), signal_loss, label), class på varje avdrag, och sist geometry_model (trösklar, hållning, taket och golvet som gäller, proveniens, klassregler) och geometry_summary (epoker per status, per etikett och per avdragsklass, samt epokerna med en avvikelse i angiven HDOP); score_model.weights är som i 0,35. Två tester håller detta till byte-nivå mot baslinjen "0,36 portabel" när de nycklarna har tagits bort (hasharna för 0.35.0, ombaserade när motorn gick över till portabel matematik och kvar i testerna som registret över vad 0.35.0 släppte: docs/revisions/STUDIO15-portable-math-rebaseline.md). tests/geometry_trust_no_change.rs håller varje utdata från båda exempelsessionerna (resultat-JSON, CSV, SVG, utlåtande, återspelade levande rader, $PKSHT, Prometheus, CEF, LEEF). tests/geometry_corpus_identity.rs håller batchresultatet, sammanfattningen, de levande raderna och $PKSHT för varje incheckad NMEA-korpus för fartyg (demon och de maritima referensdatan, var och en även som öppen himmel med enbart GPS och 8 satelliter, samt besättningsträningsscenarierna som genereras ur sina frön); i de två träningsscenarier där jamming gör geometrin dålig är varje epok som inte är dålig identisk och varje dålig skiljer sig enbart genom geometriavdraget. En logg vars geometri är dålig förlorar upp till 15 poäng som den inte förlorade i 0,35; det är den avsedda ändringen. I demon läses avdragningen som inconsistency; tests/geometry_trust.rs redigerar loggen för att maska den västra himlen (hygglig: märkt, inte poängsatt), för att maska den och två östliga satelliter (dålig: geometriavdrag, förlorad låsning environment eftersom höga satelliter också försvann), för att bara förlora satelliter under 15° (förlorad låsning geometry), och för att ange en HDOP som himlen inte förklarar (avdraget för dålig geometri blir inconsistency). Trösklarna är MODELLED: valda, inte anpassade till någon logg; ingenting här hävdar hur ofta naturlig försämring och attacker kan skiljas åt på verkliga data.

Att ange händelser och prediktioner#

[[events]]
label = "jammer on"
kind = "jamming"            # jamming, spoofing or other
onset_s = 120.0             # seconds since the first epoch of the log
end_s = 240.0               # optional; otherwise onset_s + compare.horizon_s
predicted_cn0_drop_db = 12.0  # optional, e.g. from a `jamming` scenario's link budget

[compare]
detect_tol_s = 10.0         # an alarm this soon after onset counts as a detection
cn0_tol_db = 3.0            # predicted and observed drops agree within this

För varje händelse anger resultatet falsklarmen mellan kalibrering och start, det första larmet och dess övervakare, fördröjningen, utfallet (detected, late, missed eller not-evaluable) och det observerade medianfallet i C/N0 mot prediktionen (agree, disagree, no-prediction eller not-evaluable). Avvikelser redovisas, trimmas aldrig bort: toleranserna finns i scenariot, och scenariot finns i resultatets hash.

Vad detta inte hävdar#

Förtroendeövervakarna är MODELLED: deras trösklar är indata, och deras detektionsprestanda mot verklig störning är det som händelsepoängsättningen mäter, inte något som den här typen hävdar. På spoofing-sessionerna i JammerTest 2024 fångar övervakarna i motorvägen vissa starter inom 10 s och är sena på andra; se raden "Clock-aided χ², RAIM, AGC, SQM fused per-epoch security FoM" i VERIFICATION-MATRIX.md för siffrorna. En prediktion som stämmer överens med en logg är en datapunkt, inte en validering.