NMEA-träningsströmmar: kshana nmea-scenario
Sjöfartsakademier och simulatorcenter kan mata NMEA 0183 som genererats av Kshana in i en bryggsimulator eller en sjökortsplotter för att träna besättningar att känna igen GNSS-jamming och spoofing.
Endast för träning och test. De genererade strömmarna är syntetiska. De får aldrig matas in i ett fartygs levande navigationssystem. Kshana är rådgivande, inte typgodkänd navigationsutrustning. Varje ström börjar med, och upprepar var tionde sekund, en proprietär markörmening,
$PKSHT,TRAINING,SYNTHETIC,NOT-FOR-NAVIGATION, som mottagare ignorerar;--no-markertar bort den för en simulator som avvisar okända meningar. Det här skriver endast NMEA-text: det finns ingen RF-, IQ- eller vågformsutdata, och ingenting sänder annat än texten till den adress du anger.
Figuren är ritad utifrån instruktörsloggen för scenarios/training/coastal-drag-off.toml.
Användning#
# write a file (default <name>.nmea) and the instructor log next to it
kshana nmea-scenario scenarios/training/coastal-drag-off.toml --out drag.nmea
# serve over TCP in real time on this machine only (waits for the simulator to connect)
kshana nmea-scenario scenarios/training/open-sea-jamming.toml --tcp 10110
# reachable from the bridge-simulator host: name the address in full
kshana nmea-scenario scenarios/training/open-sea-jamming.toml --tcp 192.168.1.20:10110
# UDP, one sentence per datagram, ten times faster than real time
kshana nmea-scenario scenarios/training/combined-event.toml --udp 192.168.1.50:10110 --speed 10
# UDP broadcast
kshana nmea-scenario scenarios/training/combined-event.toml --udp 192.168.1.255:10110 --broadcast
| Alternativ | Betydelse |
|---|---|
--out <file> |
skriv strömmen till en fil; utan nätverksutdata är standardvärdet <name>.nmea |
--instructor-log <prefix> |
skriv <prefix>.instructor.json och <prefix>.instructor.txt (standard: bredvid filen) |
--tcp <addr:port> eller <port> |
TCP-server; körningen startar när en klient har anslutit (--wait-clients <n>). En enbart portangivelse lyssnar endast på 127.0.0.1 |
--udp <addr:port> eller <port> |
UDP, en mening per datagram; --broadcast tillåter en broadcast-adress. En enbart portangivelse skickar till 127.0.0.1 |
--realtime, --speed <x> |
ta takten på strömmen; --speed 0 är så fort som möjligt. Nätverksutdata går som standard i realtid, filer så fort som möjligt |
--seed <n> |
ersätt scenariots frö |
--no-marker |
utelämna markörmeningen |
Det finns ingen autentisering. En TCP-server som får en icke-lokal adress serverar strömmen till vem som helst som kan nå den, och UDP skickar till vilken adress du än anger. En TCP-klient som inte tar emot sina data inom två sekunder kopplas bort, så en fastnad konsument kan inte hålla upp de andra.
Samma frö ger samma byte på en plattform, och takten ändrar aldrig byten. Mellan plattformar är generatorns egen aritmetik bitidentisk (den använder det portabla matematiklagret), men satellitpositioner och blickvinklar kommer från motorfunktioner som anropar värdens matematikbibliotek, så i ett sällsynt gränsfall kan en avrundad elevation, azimut eller C/N0-siffra i GSV skilja sig mellan plattformar.
Vad som skrivs#
Varje epok (1, 2, 5 eller 10 per sekund) innehåller: RMC, GGA, GNS (positionsbestämning, position, tid), GSA (använda satelliter och DOP, en per konstellation), GSV (satelliter i sikte med elevation, azimut och SNR i dB-Hz, en uppsättning per konstellation, NMEA 4,10-signal-ID), VTG (kurs och fart över grund), ZDA (tid och datum), HDT (gyrokurs) och VBW (fart genom vattnet och över grund från loggen). Talker är GN med flera konstellationer, annars konstellationens egen. Rader slutar med CRLF och har giltiga kontrollsummor.
HDT och VBW fungerar som oberoende sensorer (en gyrokompass och en Doppler-logg). Ingen händelse påverkar dem, vilket är avsiktligt: skillnaden mellan vad GNSS rapporterar och vad gyrot och loggen säger är en ledtråd för genomgången.
När positionsbestämningen går förlorad är GGA-kvaliteten 0, RMC-status V, positionsfälten är tomma och tidsfälten fortsätter (mottagarens klocka fortsätter gå), precis som verkliga mottagare gör.
Fartyget#
[vessel] och [[waypoint]] anger en startposition, en fart och de punkter som ska styras genom. Fartyget styrs mot nästa waypoint under en gräns för girhastighet (max_rot_deg_per_min, standard 30), en gräns för hur snabbt girhastigheten byggs upp (max_rot_accel_deg_per_s2) och en gräns för fartändring (max_accel_kn_per_min). Fartens värde för en sträcka är waypointens speed_kn. [environment] lägger till en ström, så att farten över grund skiljer sig från farten genom vattnet och att kursen skiljer sig från kursen över grund, samt en magnetisk missvisning. stop_at_end för fartyget till vila vid den sista waypointen.
Satellitgeometri#
Satelliterna kommer från motorns egna nominella konstellationer (GPS slottabell, Galileo och BeiDou MEO Walker-mönster, GLONASS ICD), propagerade av constellation::satellite_positions_fixed (tvåkroppsrörelse plus sekulär J2, jordrotation) och sedda från fartyget med motorns WGS-84-blickvinklar. Antalet synliga satelliter, elevationerna och azimuten i GSV är rimliga för platsen och tiden på dygnet. Detta är en nominell himmel, inte en efemerid för strömmens datum: PRN tilldelas i slottordning och varje konstellation behåller sin publicerade slottlayout, propagerad kontinuerligt från epoken för GPS slottabell (2016-12-31) under J2, så layouten är intakt men dess orientering är inte den verkliga himlens på strömmens datum. C/N0 följer elevationen (en nominell zenitnivå, satt i [receiver]), med en fast förskjutning per satellit, långsam fading och brus. En satellit under track_threshold_dbhz har ett tomt SNR-fält; en under use_threshold_dbhz spåras men används inte. Upp till max_used (standard 12, taket för NMEA GGA) användbara satelliter används, valda för geometri (den högsta satelliten i varje azimutsektor på 30 grader först). Färre än fyra användbara satelliter ger förlorad positionsbestämning, och den återkommer efter reacquire_s med användbar signal.
Händelser#
Varje [[event]] har en kind, en start start_s, en duration_s (från start till början av avklingningen), en rampning vid start ramp_s och en rampning vid avklingning recovery_s. Styrkan stiger linjärt över ramp_s, hålls och faller sedan över recovery_s; 0 är ett steg. Alla effekter skalar med den styrkan. Parametrar som inte hör till slaget avvisas.
| kind | parametrar | effekt |
|---|---|---|
jamming |
cn0_drop_db, spread_db (standard 6) |
varje satellits C/N0 faller med upp till cn0_drop_db (spridning per satellit), satelliter faller bort med den lägsta först, positionsbestämningen går förlorad när färre än fyra är användbara, och återhämtar sig efter avklingningen och reacquire_s |
drag-off |
final_offset_m, en av bearing_deg (sann) eller relative_bearing_deg (till kursen vid start, därefter hållen), valfritt max_accel_mps2, counterfeit_cn0_dbhz |
mottagaren behåller en giltig positionsbestämning vars position vandrar bort från referensen; SOG och COG inkluderar avdragningen. Avdragningen följer smoothstep på rampningarna, så det falska spåret startar och stannar utan hastighetssteg; dess toppar är 1.5 D/T m/s och 6 D/T^2 m/s i kvadrat för en rampning på T s över D m (båda loggade), och ett scenario som skulle överskrida max_accel_mps2 avvisas. Ett steg (ramp_s = 0) flyttar positionen utan att röra hastigheten |
time-spoof |
offset_s, counterfeit_cn0_dbhz |
Tiden i RMC, GGA, GNS och ZDA förskjuts från sann UTC; positionen förblir sann |
replay-delay |
delay_s, affect_time (standardvärde true), counterfeit_cn0_dbhz |
position, hastighet (och tid) är de som fartyget hade för delay_s sedan, där fördröjningen följer smoothstep på sina ramper och den rapporterade farten skalas med 1 - d(delay)/dt medan den ändras: en förenklad abstraktion i stil med meaconing, inte en utbredningsmodell |
counterfeit_cn0_dbhz: medan en drag-off, tidsspoofing eller replay-fördröjning är aktiv visar varje spårad satellit den enda förhöjda nivån, ett klassiskt tecken. Utelämna den för en subtil händelse där det genuina C/N0-mönstret behålls. Medan någon förfalskad händelse är aktiv följer mottagaren den förfalskade signalen, så jamming får den inte att tappa den; en positionsbestämning som förlorats på grund av tidigare jamming kommer tillbaka efter reacquire_s på den förfalskade signalen (se combined-event). En tidsändring som skulle få rapporterad tid att stanna eller gå baklänges (takt på 1 s per sekund eller mer) avvisas om den inte är ett steg (ramp_s = 0).
Händelser kan överlappa; deras effekter adderas (förskjutningar, tidsändringar, fördröjningar) eller så gäller den starkaste (jamming). Tidslinjens onset är den första epok då händelsen har effekt, en epok efter det skriptade start_s när händelsen trappas in.
Instruktörsloggen#
Vid sidan av strömmen ger <prefix>.instructor.json och <prefix>.instructor.txt:
- händelserna såsom de injicerats, i klartext med varje parameter, och deras UTC-start;
- en tidslinje: start, full effekt, återhämtning börjar, återhämtad, och mottagarens egna
fix-lostochfix-regained; - det sanna spåret mot det rapporterade med
log_interval_smellanrum: sann och rapporterad position, fart och kurs, positionsfel i meter, tidsavvikelse, använda och spårade satelliter, genomsnittligt C/N0 och vilka händelser som var aktiva; - högsta fart och acceleration för det sanna och det rapporterade spåret;
- scenariots
trainer_note.
Visa loggen först vid genomgången.
JSON-fält (schema kshana-nmea-training/1)#
| fält | typ, enhet | betydelse |
|---|---|---|
schema |
sträng | kshana-nmea-training/1 |
warning |
sträng | uttalandet som endast gäller utbildning |
scenario, description, trainer_note |
sträng | från scenariot |
seed |
heltal | använt frö |
start_utc |
ISO 8601 UTC | körningens start |
duration_s |
s | körningens längd |
summary.true_peak_sog_kn, summary.reported_peak_sog_kn |
knop | högsta sanna och rapporterade fart över grund |
summary.true_peak_accel_mps2, summary.reported_peak_accel_mps2 |
m/s i kvadrat | största hastighetsändring per sekund, sann och mellan på varandra följande rapporterade positionsbestämningar |
events[] |
en per skriptad händelse | |
events[].id |
heltal | 1-baserad; används av timeline[].event och track[].active_events |
events[].description |
sträng | beskrivning i klartext med parametrarna |
events[].start_utc |
ISO 8601 UTC | skriptad start |
events[].parameters |
objekt | händelsen exakt som den skrevs (kind, start_s, duration_s, ramp_s, recovery_s och typens egna parametrar; frånvarande utelämnas) |
events[].resolved_bearing_deg |
grader sann eller null | drag-off: den riktning som tillämpades (en relativ bäring löses vid starten) |
events[].peak_drag_speed_mps, events[].peak_drag_accel_mps2 |
m/s, m/s i kvadrat eller null | drag-off: de toppar som släpet tillför det falska spåret |
timeline[] |
ögonblick för genomgången, i tidsordning | |
timeline[].t_s, .utc |
s från start, ISO 8601 UTC | när (sann tid) |
timeline[].event |
heltal eller null | händelsens id; null för ändringar av mottagarens tillstånd |
timeline[].what |
sträng | onset, full-effect, recovery-begins, recovered (händelser); fix-lost, fix-regained (mottagare) |
timeline[].text |
sträng | förklaring |
track[] |
en rad per log_interval_s |
|
track[].t_s, .utc |
s, ISO 8601 UTC | när (sann tid) |
track[].true_lat_deg, .true_lon_deg |
grader | sann position |
track[].true_sog_kn, .true_cog_deg, .true_heading_deg |
knop, grader sann | sann fart och kurs över grund samt gyrokurs |
track[].fix_valid |
boolesk | mottagaren rapporterade en positionsbestämning |
track[].reported_lat_deg, .reported_lon_deg, .reported_sog_kn, .reported_cog_deg |
grader, knop, grader sann eller null | vad mottagaren rapporterade; null medan positionsbestämningen är förlorad |
track[].position_error_m |
m eller null | horisontellt avstånd från sann till rapporterad position |
track[].time_offset_s |
s | rapporterad UTC minus sann UTC |
track[].n_used, .n_tracked |
heltal | satelliter som använts i positionsbestämningen, och spårade |
track[].mean_cn0_dbhz |
dB-Hz eller null | genomsnittligt C/N0 för de spårade satelliterna |
track[].active_events |
heltal | id för händelser med effekt i detta ögonblick |
Att lägga till ett fält ändrar inte schemataggen. Att byta namn på eller ta bort ett fält, eller ändra ett fälts betydelse eller enhet, höjer numret (/2).
Scenariobiblioteket#
scenarios/training/, vart och ett några minuters överfart med en instruktörsanteckning i sin TOML:
| fil | vad det visar |
|---|---|
open-sea-jamming.toml |
C/N0 faller samtidigt, satelliter försvinner, positionsbestämningen förloras och kommer tillbaka |
coastal-drag-off.toml |
en giltig positionsbestämning som ser frisk ut dras 1,4 km mot land; enhetligt förhöjt C/N0 |
port-approach-time-spoof.toml |
positionen är korrekt, UTC driver 45 s före under en långsam hamninfart |
combined-event.toml |
jamming, sedan förfalskat övertagande med drag-off och tidsförskjutning, sedan en replay-fördröjning |
fjord-natural-degradation.toml |
en blockerad himmel, inte störning: väggarna i en fjord (den REPRESENTATIVE förinställningen fjord för horisontprofil) döljer satelliterna i öster och väster, sedan öppnas rännan igen (händelse natural-degradation, med en skyline-tabell) |
Positioner, datum och spår är påhittade; biblioteket innehåller inga verkliga fartyg, operatörer eller inspelningar. Det gör inget uttalande om hur någon mottagare eller något system skulle klara sig mot störning.
Modelleringsval#
Generatorn är ett utbildningsverktyg utan oberoende referens, och dess siffror är modelleringsval, inte mätningar av någon mottagare. De är valda för att likna en vanlig mottagarlogg: C/N0-lutningen på 14 dB från zenit till horisont under zenitnivån (standard 47 dB-Hz) och förskjutningen per satellit på +/-1.5 dB, långsam fädning på 0,8 dB över 97 s och 0,5 dB över 31 s, 0,3 dB jitter; trösklarna för spårning (20 dB-Hz) och användning (28 dB-Hz); positionsbruset (1,5 m vid HDOP 1, korrelerat över 30 s, vertikalt dubbelt så stort); 0,05 graders gyrobrus och 0,03 kn avdriftsbrus; styrtidskonstanten på 20 s och ankomstradierna för waypoints i fartygsmodellen; samt valet av satelliter efter azimutsektor. Standardvärdena finns i [receiver] och [vessel] och kan alla ändras i scenariot.
Att läsa in dem igen#
kshana receiver-trust kan läsa in de här filerna (format = "nmea"). Testerna kontrollerar varje mening i varje bibliotekscenario mot dess egna regler för fältantal och kontrollsumma, och kör filerna genom den läsaren, som tolkar GGA, RMC och GSV och låter de övriga typerna passera utan att hoppa över någon. Testerna fäster ett golden-utdrag per scenario (tests/fixtures/nmea_training/); generera om med KSHANA_BLESS_GOLDEN=1 efter en avsiktlig ändring.