NMEA-trainingsstromen: kshana nmea-scenario
Maritieme academies en simulatiecentra kunnen door Kshana gegenereerde NMEA 0183 in een brugsimulator of een kaartplotter voeren om bemanningen te trainen GNSS-jamming en spoofing te herkennen.
Alleen voor training en test. De gegenereerde stromen zijn synthetisch. Ze mogen nooit in de live navigatiesystemen van een vaartuig worden gevoerd. Kshana is adviserend, geen typegoedgekeurde navigatieapparatuur. Elke stroom begint met, en herhaalt elke tien seconden, een eigen markeringszin,
$PKSHT,TRAINING,SYNTHETIC,NOT-FOR-NAVIGATION, die ontvangers negeren;--no-markerverwijdert die voor een simulator die onbekende zinnen weigert. Dit schrijft alleen NMEA-tekst: er is geen RF-, IQ- of golfvormuitvoer, en niets zendt uit behalve de tekst naar het adres dat u opgeeft.
De figuur is getekend uit het instructeurslogboek van scenarios/training/coastal-drag-off.toml.
Gebruik#
# 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
| Optie | Betekenis |
|---|---|
--out <file> |
schrijf de stroom naar een bestand; zonder netwerkuitvoer is de standaard <name>.nmea |
--instructor-log <prefix> |
schrijf <prefix>.instructor.json en <prefix>.instructor.txt (standaard: naast het bestand) |
--tcp <addr:port> of <port> |
TCP-server; de run begint wanneer een client is verbonden (--wait-clients <n>). Een kale poort luistert alleen op 127.0.0.1 |
--udp <addr:port> of <port> |
UDP, één zin per datagram; --broadcast staat een broadcastadres toe. Een kale poort verzendt naar 127.0.0.1 |
--realtime, --speed <x> |
bepaal het tempo van de stroom; --speed 0 is zo snel mogelijk. Netwerkuitvoer gebruikt standaard realtime, bestanden zo snel mogelijk |
--seed <n> |
vervang de seed van het scenario |
--no-marker |
laat de markeringszin weg |
Er is geen authenticatie. Een TCP-server met een niet-lokaal adres levert de stroom aan iedereen die hem kan bereiken, en UDP verzendt naar elk adres dat u opgeeft. Een TCP-client die zijn data niet binnen twee seconden afneemt, wordt losgekoppeld, zodat één vastgelopen afnemer de andere niet kan ophouden.
Dezelfde seed geeft op één platform dezelfde bytes, en tempo verandert de bytes nooit. Tussen platforms is de eigen rekenkunde van de generator bitgelijk (hij gebruikt de draagbare wiskundelaag), maar satellietposities en kijkhoeken komen van enginefuncties die de wiskundebibliotheek van de host aanroepen, dus in een zeldzaam grensgeval kan een afgeronde elevatie-, azimut- of C/N0-digit in GSV tussen platforms verschillen.
Wat er wordt geschreven#
Elke epoch (1, 2, 5 of 10 per seconde) bevat: RMC, GGA, GNS (positiebepaling, positie, tijd), GSA (gebruikte satellieten en DOP, één per constellatie), GSV (satellieten in zicht met elevatie, azimut en SNR in dB-Hz, één set per constellatie, NMEA 4,10-signaal-ID), VTG (koers en snelheid over de grond), ZDA (tijd en datum), HDT (gyrokoers) en VBW (snelheid door het water en over de grond van het log). De talker is GN bij meerdere constellaties, anders die van de constellatie zelf. Regels eindigen op CRLF en hebben een geldige checksum.
HDT en VBW vertegenwoordigen onafhankelijke sensoren (een gyrokompas en een Doppler-log). Geen enkele gebeurtenis raakt ze, wat opzettelijk is: het verschil tussen wat GNSS meldt en wat de gyro en het log zeggen is een aanwijzing voor de nabespreking.
Wanneer de positiebepaling verloren gaat, is de GGA-kwaliteit 0, is de RMC-status V, zijn de positievelden leeg en lopen de tijdvelden door (de klok van de ontvanger blijft lopen), zoals bij echte ontvangers.
Het vaartuig#
[vessel] en [[waypoint]] geven een startpositie, snelheid en de punten waar doorheen wordt gestuurd. Het vaartuig wordt gestuurd naar het volgende waypoint onder een limiet op de draaisnelheid (max_rot_deg_per_min, standaard 30), een limiet op hoe snel de draaisnelheid zich opbouwt (max_rot_accel_deg_per_s2) en een limiet op snelheidsverandering (max_accel_kn_per_min). De snelheid van een etappe is de speed_kn van het waypoint. [environment] voegt een stroming toe, zodat de snelheid over de grond verschilt van de snelheid door het water en de koers verschilt van de koers over de grond, en een magnetische variatie. stop_at_end brengt het vaartuig tot stilstand bij het laatste waypoint.
Satellietgeometrie#
Satellieten komen uit de eigen nominale constellaties van de engine (GPS-slottabel, Walker-patronen voor Galileo en BeiDou MEO, GLONASS ICD), gepropageerd door constellation::satellite_positions_fixed (tweelichamenprobleem plus seculiere J2, aardrotatie) en gezien vanaf het vaartuig met de WGS-84-kijkhoeken van de engine. Het zichtbare aantal, de elevaties en de azimuts in GSV zijn aannemelijk voor de plaats en het tijdstip van de dag. Dit is een nominale hemel, geen efemeride voor de datum van de stroom: PRN's worden in slotvolgorde toegewezen en elke constellatie behoudt haar gepubliceerde slotindeling, continu gepropageerd vanaf de epoch van de GPS-slottabel (2016-12-31) onder J2, dus de indeling is intact maar haar oriëntatie is niet die van de echte hemel op de datum van de stroom. C/N0 volgt de elevatie (een nominaal zenitniveau, ingesteld in [receiver]), met een vaste offset per satelliet, langzame fading en ruis. Een satelliet onder track_threshold_dbhz heeft een leeg SNR-veld; een satelliet onder use_threshold_dbhz wordt gevolgd maar niet gebruikt. Tot max_used (standaard 12, het NMEA GGA-maximum) bruikbare satellieten worden gebruikt, gekozen op geometrie (eerst de hoogste satelliet in elke azimutsector van 30 graden). Minder dan vier bruikbare satellieten verliest de positiebepaling, en die keert terug na reacquire_s bruikbaar signaal.
Gebeurtenissen#
Elke [[event]] heeft een kind, een aanvang start_s, een duration_s (aanvang tot het begin van het loslaten), een aanloophelling ramp_s en een loslaathelling recovery_s. De sterkte stijgt lineair over ramp_s, blijft constant en daalt dan over recovery_s; 0 is een stap. Alle effecten schalen met die sterkte. Parameters die niet bij de soort horen, worden geweigerd.
| soort | parameters | effect |
|---|---|---|
jamming |
cn0_drop_db, spread_db (standaard 6) |
de C/N0 van elke satelliet daalt met maximaal cn0_drop_db (spreiding per satelliet), satellieten vallen weg beginnend bij de laagste, de positiebepaling gaat verloren wanneer minder dan vier bruikbaar zijn, en herstelt na het loslaten en reacquire_s |
drag-off |
final_offset_m, één van bearing_deg (waar) of relative_bearing_deg (ten opzichte van de koers bij aanvang, daarna vastgehouden), optioneel max_accel_mps2, counterfeit_cn0_dbhz |
de ontvanger behoudt een geldige positiebepaling waarvan de positie van de werkelijkheid wegloopt; SOG en COG bevatten de drag. De drag volgt smoothstep op de hellingen, zodat het valse spoor zonder snelheidssprong begint en stopt; de pieken zijn 1.5 D/T m/s en 6 D/T^2 m/s kwadraat voor een helling van T s over D m (beide gelogd), en een scenario dat max_accel_mps2 zou overschrijden wordt geweigerd. Een stap (ramp_s = 0) verplaatst de positie zonder de snelheid aan te raken |
time-spoof |
offset_s, counterfeit_cn0_dbhz |
De tijd van RMC, GGA, GNS en ZDA wordt verschoven ten opzichte van de ware UTC; de positie blijft waar |
replay-delay |
delay_s, affect_time (standaard true), counterfeit_cn0_dbhz |
positie, snelheid (en tijd) zijn die van het vaartuig delay_s geleden, waarbij de vertraging smoothstep volgt op haar hellingen en de gemelde snelheid wordt geschaald met 1 - d(delay)/dt terwijl ze verandert: een vereenvoudigde abstractie in de stijl van meaconing, geen propagatiemodel |
counterfeit_cn0_dbhz: zolang een drag-off, tijdspoof of replay-vertraging actief is, toont elke gevolgde satelliet dat ene verhoogde niveau, een klassiek teken. Laat het weg voor een subtiele gebeurtenis waarin het echte C/N0-patroon behouden blijft. Zolang een namaakgebeurtenis actief is, volgt de ontvanger het namaaksignaal, zodat jamming hem niet laat wegvallen; een door eerdere jamming verloren positiebepaling keert na reacquire_s terug op het namaaksignaal (zie combined-event). Een tijdwijziging waardoor de gemelde tijd zou stilstaan of terugloopt (een snelheid van 1 s per seconde of meer) wordt geweigerd tenzij het een stap is (ramp_s = 0).
Gebeurtenissen kunnen overlappen; hun effecten tellen op (offsets, tijdwijzigingen, vertragingen) of nemen de sterkste (jamming). De onset van de tijdlijn is de eerste epoch waarop de gebeurtenis effect heeft, één epoch na de gescripte start_s wanneer de gebeurtenis geleidelijk aanloopt.
Het instructeurslogboek#
Naast de stroom geven <prefix>.instructor.json en <prefix>.instructor.txt:
- de gebeurtenissen zoals geïnjecteerd, in gewone taal met elke parameter, en hun UTC-aanvang;
- een tijdlijn: aanvang, volledig effect, begin van herstel, hersteld, en de eigen
fix-lostenfix-regainedvan de ontvanger; - het ware spoor tegenover het gemelde bij een interval van
log_interval_s: ware en gemelde positie, snelheid en koers, positiefout in meters, tijdoffset, gebruikte en gevolgde satellieten, gemiddelde C/N0, en welke gebeurtenissen actief waren; - de piekversnelling en piekssnelheid van het ware en van het gemelde spoor;
- de
trainer_notevan het scenario.
Toon het logboek pas bij de nabespreking.
JSON-velden (schema kshana-nmea-training/1)#
| veld | type, eenheid | betekenis |
|---|---|---|
schema |
tekenreeks | kshana-nmea-training/1 |
warning |
tekenreeks | de verklaring dat het alleen voor training is |
scenario, description, trainer_note |
tekenreeks | uit het scenario |
seed |
geheel getal | gebruikte seed |
start_utc |
ISO 8601 UTC | begin van de run |
duration_s |
s | duur van de run |
summary.true_peak_sog_kn, summary.reported_peak_sog_kn |
knopen | hoogste ware en gemelde snelheid over de grond |
summary.true_peak_accel_mps2, summary.reported_peak_accel_mps2 |
m/s kwadraat | grootste snelheidsverandering per seconde, waar en tussen opeenvolgende gemelde positiebepalingen |
events[] |
één per gescripte gebeurtenis | |
events[].id |
geheel getal | telt vanaf 1; gebruikt door timeline[].event en track[].active_events |
events[].description |
tekenreeks | beschrijving in gewone taal met de parameters |
events[].start_utc |
ISO 8601 UTC | gescripte aanvang |
events[].parameters |
object | de gebeurtenis precies zoals geschreven (kind, start_s, duration_s, ramp_s, recovery_s, en de eigen parameters van de soort; ontbrekende worden weggelaten) |
events[].resolved_bearing_deg |
graden waar of null | drag-off: de toegepaste richting (een relatieve peiling wordt bij aanvang omgezet) |
events[].peak_drag_speed_mps, events[].peak_drag_accel_mps2 |
m/s, m/s kwadraat of null | drag-off: de pieken die de drag aan het valse spoor toevoegt |
timeline[] |
momenten voor de nabespreking, in tijdsvolgorde | |
timeline[].t_s, .utc |
s sinds de start, ISO 8601 UTC | wanneer (ware tijd) |
timeline[].event |
geheel getal of null | het gebeurtenis-id; null bij wijzigingen van de ontvangertoestand |
timeline[].what |
tekenreeks | onset, full-effect, recovery-begins, recovered (gebeurtenissen); fix-lost, fix-regained (ontvanger) |
timeline[].text |
tekenreeks | uitleg |
track[] |
één rij per log_interval_s |
|
track[].t_s, .utc |
s, ISO 8601 UTC | wanneer (ware tijd) |
track[].true_lat_deg, .true_lon_deg |
graden | ware positie |
track[].true_sog_kn, .true_cog_deg, .true_heading_deg |
knopen, graden waar | ware snelheid en koers over de grond, en gyrokoers |
track[].fix_valid |
boolean | de ontvanger meldde een positiebepaling |
track[].reported_lat_deg, .reported_lon_deg, .reported_sog_kn, .reported_cog_deg |
graden, knopen, graden waar, of null | wat de ontvanger meldde; null zolang de positiebepaling verloren is |
track[].position_error_m |
m of null | horizontale afstand van ware tot gemelde positie |
track[].time_offset_s |
s | gemelde UTC min ware UTC |
track[].n_used, .n_tracked |
gehele getallen | in de positiebepaling gebruikte satellieten, en gevolgde |
track[].mean_cn0_dbhz |
dB-Hz of null | gemiddelde C/N0 van de gevolgde satellieten |
track[].active_events |
gehele getallen | id's van gebeurtenissen met een effect op dit moment |
Een veld toevoegen wijzigt de schematag niet. Een veld hernoemen of verwijderen, of de betekenis of eenheid van een veld wijzigen, verhoogt het nummer (/2).
De scenariobibliotheek#
scenarios/training/, elk enkele minuten van een vaart met een opmerking voor de trainer in zijn TOML:
| bestand | wat het toont |
|---|---|
open-sea-jamming.toml |
C/N0 daalt gelijktijdig, satellieten vallen weg, de positiebepaling gaat verloren en keert terug |
coastal-drag-off.toml |
een geldige, gezond ogende positiebepaling schuift 1,4 km in de richting van de kust; uniform verhoogde C/N0 |
port-approach-time-spoof.toml |
positie juist, UTC loopt 45 s voor tijdens een langzame havenaanloop |
combined-event.toml |
jamming, dan overname door namaak met drag-off en tijdoffset, dan een replay-vertraging |
fjord-natural-degradation.toml |
een geblokkeerde hemel, geen interferentie: de wanden van een fjord (de REPRESENTATIVE-skylinevoorinstelling fjord) verbergen de satellieten in het oosten en westen, waarna het kanaal weer opent (gebeurtenis natural-degradation, met een skyline-tabel) |
Posities, data en sporen zijn verzonnen; de bibliotheek bevat geen echt vaartuig, geen echte exploitant en geen echte opname. Ze doet geen uitspraak over hoe enige ontvanger of enig systeem zou presteren onder interferentie.
Modelleringskeuzes#
De generator is een trainingshulpmiddel zonder externe onafhankelijke referentie, en zijn getallen zijn modelleringskeuzes, geen metingen van enige ontvanger. Ze zijn gekozen om op een gewoon ontvangerlog te lijken: de C/N0-helling van 14 dB van zenit tot horizon onder het zenitniveau (standaard 47 dB-Hz) en de offset per satelliet van +/-1.5 dB, langzame fading van 0,8 dB over 97 s en 0,5 dB over 31 s, 0,3 dB jitter; de drempels voor volgen (20 dB-Hz) en gebruik (28 dB-Hz); de positieruis (1,5 m bij HDOP 1, gecorreleerd over 30 s, verticaal tweemaal zoveel); 0,05 graad gyroruis en 0,03 kn leeway-ruis; de stuurtijdconstante van 20 s en de aankomststralen van waypoints van het vaartuigmodel; en de satellietkeuze per azimutsector. De standaardwaarden staan in [receiver] en [vessel] en kunnen allemaal in het scenario worden gewijzigd.
Terugwaarts inlezen#
kshana receiver-trust kan deze bestanden inlezen (format = "nmea"). De tests controleren elke zin van elk bibliotheekscenario aan zijn eigen regels voor veldaantal en checksum, en laten de bestanden door die lezer lopen, die GGA, RMC en GSV interpreteert en de andere typen passeert zonder er een over te slaan. Tests leggen per scenario een gouden fragment vast (tests/fixtures/nmea_training/); regenereer met KSHANA_BLESS_GOLDEN=1 na een bedoelde wijziging.