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.
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.
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.