Tréninkové proudy NMEA: kshana nmea-scenario
Námořní akademie a simulační střediska mohou vkládat NMEA 0183 generovanou nástrojem Kshana do simulátoru můstku nebo mapového plotru, aby školila posádky v rozpoznávání rušení (jamming) a podvržení signálu (spoofing) GNSS.
Pouze pro trénink a testování. Generované proudy jsou syntetické. Nikdy se nesmějí vkládat do živých navigačních systémů plavidla. Kshana má pouze poradní charakter a není typově schváleným navigačním zařízením. Každý proud začíná proprietární značkovací větou
$PKSHT,TRAINING,SYNTHETIC,NOT-FOR-NAVIGATIONa opakuje ji každých deset sekund; přijímače ji ignorují a--no-markerji odstraní pro simulátor, který neznámé věty odmítá. Zapisuje se pouze text NMEA: neexistuje žádný výstup RF, IQ ani průběhu signálu a nic se nevysílá kromě textu na adresu, kterou uvedete.
Obrázek je vykreslen z instruktorského záznamu scenarios/training/coastal-drag-off.toml.
Použití#
# 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
| Volba | Význam |
|---|---|
--out <file> |
zapíše proud do souboru; bez síťového výstupu je výchozí <name>.nmea |
--instructor-log <prefix> |
zapíše <prefix>.instructor.json a <prefix>.instructor.txt (výchozí: vedle souboru) |
--tcp <addr:port> nebo <port> |
server TCP; běh začne, když se připojí klient (--wait-clients <n>). Samotný port naslouchá jen na 127.0.0.1 |
--udp <addr:port> nebo <port> |
UDP, jedna věta na datagram; --broadcast povolí adresu pro vysílání všem. Samotný port odesílá na 127.0.0.1 |
--realtime, --speed <x> |
řídí tempo proudu; --speed 0 znamená co nejrychleji. Síťový výstup má výchozí tempo v reálném čase, soubory co nejrychleji |
--seed <n> |
nahradí seed scénáře |
--no-marker |
vynechá značkovací větu |
Neexistuje žádné ověřování. Server TCP s nelokální adresou poskytuje proud každému, kdo se k němu dostane, a UDP odesílá na jakoukoli adresu, kterou uvedete. Klient TCP, který si data nevyzvedne do dvou sekund, je odpojen, takže jeden zaseknutý odběratel nemůže zdržet ostatní.
Stejný seed dává na jedné platformě stejné bajty a tempo bajty nikdy nemění. Napříč platformami je vlastní aritmetika generátoru bitově shodná (používá přenosnou matematickou vrstvu), ale polohy družic a elevační úhly pocházejí z funkcí enginu, které volají matematickou knihovnu hostitele, takže se ve vzácném hraničním případě může zaokrouhlená číslice elevace, azimutu nebo C/N0 ve větě GSV mezi platformami lišit.
Co se zapisuje#
Každá epocha (1, 2, 5 nebo 10 za sekundu) nese: RMC, GGA, GNS (zaměření, poloha, čas), GSA (použité družice a DOP, jedna na konstelaci), GSV (družice v dohledu s elevací, azimutem a SNR v dB-Hz, jedna sada na konstelaci, identifikátor signálu NMEA 4,10), VTG (kurz a rychlost nad zemí), ZDA (čas a datum), HDT (směr podle gyra) a VBW (rychlost vůči vodě a nad zemí z logu). Talker je GN u více konstelací, jinak vlastní talker dané konstelace. Řádky končí CRLF a mají platný kontrolní součet.
HDT a VBW zastupují nezávislé senzory (gyrokompas a dopplerovský log). Žádná událost se jich netýká, což je záměr: rozdíl mezi tím, co hlásí GNSS, a tím, co říkají gyro a log, je podnět pro rozbor.
Když se zaměření ztratí, kvalita GGA je 0, stav RMC je V, pole polohy jsou prázdná a časová pole pokračují (hodiny přijímače běží dál), jako u skutečných přijímačů.
Plavidlo#
[vessel] a [[waypoint]] udávají počáteční polohu, rychlost a body, kterými se má plout. Plavidlo je řízeno k dalšímu bodu trasy při omezení rychlosti otáčení (max_rot_deg_per_min, výchozí 30), omezení toho, jak rychle narůstá rychlost otáčení (max_rot_accel_deg_per_s2), a omezení změny rychlosti (max_accel_kn_per_min). Rychlost úseku je speed_kn daného bodu trasy. [environment] přidává proud, takže rychlost nad zemí se liší od rychlosti vůči vodě a směr přídě se liší od kurzu nad zemí, a magnetickou deklinaci. stop_at_end zastaví plavidlo v posledním bodu trasy.
Geometrie družic#
Družice pocházejí z vlastních nominálních konstelací enginu (tabulka slotů GPS, vzory Walker MEO pro Galileo a BeiDou, ICD GLONASS), šířených pomocí constellation::satellite_positions_fixed (dvě tělesa plus sekulární J2, rotace Země) a viděných z plavidla pomocí elevačních a azimutových úhlů enginu podle WGS-84. Viditelný počet, elevace a azimuty ve větě GSV jsou věrohodné pro dané místo a denní dobu. Jde o nominální oblohu, nikoli o efemeridy pro datum proudu: PRN se přidělují v pořadí slotů a každá konstelace zachovává svůj zveřejněný rozvrh slotů, spojitě šířený od epochy tabulky slotů GPS (2016-12-31) pod vlivem J2, takže rozvrh je neporušen, ale jeho orientace není orientací skutečné oblohy v den proudu. C/N0 sleduje elevaci (nominální úroveň v zenitu, nastavená v [receiver]), s pevným posunem pro každou družici, pomalým únikem a šumem. Družice pod track_threshold_dbhz má pole SNR prázdné; družice pod use_threshold_dbhz je sledována, ale nepoužita. Použije se až max_used (výchozí 12, strop NMEA GGA) použitelných družic, vybraných podle geometrie (nejprve nejvyšší družice v každém azimutovém sektoru po 30 stupních). Méně než čtyři použitelné družice znamenají ztrátu zaměření, které se vrátí po reacquire_s použitelného signálu.
Události#
Každá [[event]] má kind, nástup start_s, duration_s (od nástupu do začátku uvolnění), nástupní rampu ramp_s a uvolňovací rampu recovery_s. Síla lineárně stoupá po dobu ramp_s, drží se a poté klesá po dobu recovery_s; 0 je skok. Všechny účinky se škálují touto silou. Parametry, které k danému druhu nepatří, se odmítnou.
| druh | parametry | účinek |
|---|---|---|
jamming |
cn0_drop_db, spread_db (výchozí 6) |
C/N0 každé družice klesne až o cn0_drop_db (rozptyl mezi družicemi), družice vypadávají od nejslabší, zaměření se ztratí, když jsou použitelné méně než čtyři, a obnoví se po uvolnění a reacquire_s |
drag-off |
final_offset_m, jedno z bearing_deg (skutečný) nebo relative_bearing_deg (vůči kurzu v okamžiku nástupu, poté držený), volitelně max_accel_mps2, counterfeit_cn0_dbhz |
přijímač udržuje platné zaměření, jehož poloha se vzdaluje od skutečnosti; SOG a COG zahrnují odtažení. Odtažení sleduje průběh smoothstep na rampách, takže falešná trasa začíná a končí bez skoku rychlosti; její maxima jsou 1.5 D/T m/s a 6 D/T^2 m/s na druhou pro rampu T s přes D m (obojí zaznamenáno) a scénář, který by překročil max_accel_mps2, se odmítne. Skok (ramp_s = 0) posune polohu, aniž by se dotkl rychlosti |
time-spoof |
offset_s, counterfeit_cn0_dbhz |
čas v RMC, GGA, GNS a ZDA je posunut oproti skutečnému UTC; poloha zůstává skutečná |
replay-delay |
delay_s, affect_time (výchozí true), counterfeit_cn0_dbhz |
poloha, rychlost (a čas) jsou ty, které plavidlo mělo před delay_s, přičemž zpoždění sleduje průběh smoothstep na rampách a hlášená rychlost se během jeho změny násobí 1 - d(delay)/dt: zjednodušená abstrakce ve stylu meaconingu, nikoli model šíření |
counterfeit_cn0_dbhz: dokud je aktivní odtažení polohy, podvržení času nebo zpoždění přehrávání, každá sledovaná družice ukazuje tuto jedinou zvýšenou úroveň, což je klasický příznak. Vynechejte ji pro nenápadnou událost, při níž se zachová skutečný vzor C/N0. Dokud je aktivní jakákoli padělaná událost, přijímač sleduje padělaný signál, takže jej rušení neodpojí; zaměření ztracené dřívějším rušením se vrátí po reacquire_s na padělaném signálu (viz combined-event). Změna času, která by způsobila zastavení nebo zpětný chod hlášeného času (rychlost 1 s za sekundu nebo více), se odmítne, pokud nejde o skok (ramp_s = 0).
Události se mohou překrývat; jejich účinky se sčítají (posuny, změny času, zpoždění) nebo se bere nejsilnější (rušení). onset na časové ose je první epocha, v níž má událost účinek, tedy o jednu epochu po skriptovaném start_s, když událost nabíhá po rampě.
Instruktorský záznam#
Vedle proudu poskytují <prefix>.instructor.json a <prefix>.instructor.txt:
- události tak, jak byly vloženy, srozumitelným jazykem se všemi parametry, a jejich nástup v UTC;
- časovou osu: nástup, plný účinek, začátek zotavení, zotaveno a vlastní
fix-lostafix-regainedpřijímače; - skutečnou trasu proti hlášené v odstupu
log_interval_s: skutečná a hlášená poloha, rychlost a kurz, chyba polohy v metrech, časový posun, počet použitých a sledovaných družic, střední C/N0 a které události byly aktivní; - nejvyšší rychlost a zrychlení skutečné i hlášené trasy;
- poznámku školitele scénáře (
trainer_note).
Záznam ukažte až při rozboru.
Pole JSON (schéma kshana-nmea-training/1)#
| pole | typ, jednotka | význam |
|---|---|---|
schema |
řetězec | kshana-nmea-training/1 |
warning |
řetězec | prohlášení, že jde pouze o trénink |
scenario, description, trainer_note |
řetězec | ze scénáře |
seed |
celé číslo | použitý seed |
start_utc |
ISO 8601 UTC | začátek běhu |
duration_s |
s | délka běhu |
summary.true_peak_sog_kn, summary.reported_peak_sog_kn |
uzly | nejvyšší skutečná a hlášená rychlost nad zemí |
summary.true_peak_accel_mps2, summary.reported_peak_accel_mps2 |
m/s na druhou | největší změna rychlosti za sekundu, skutečná a mezi po sobě jdoucími hlášenými zaměřeními |
events[] |
jeden na každou skriptovanou událost | |
events[].id |
celé číslo | číslováno od 1; používá timeline[].event a track[].active_events |
events[].description |
řetězec | popis srozumitelným jazykem s parametry |
events[].start_utc |
ISO 8601 UTC | skriptovaný nástup |
events[].parameters |
objekt | událost přesně tak, jak je zapsána (kind, start_s, duration_s, ramp_s, recovery_s a vlastní parametry druhu; chybějící se vynechají) |
events[].resolved_bearing_deg |
stupně skutečné nebo null | odtažení polohy: použitý směr (relativní kurz se určí při nástupu) |
events[].peak_drag_speed_mps, events[].peak_drag_accel_mps2 |
m/s, m/s na druhou nebo null | odtažení polohy: maxima, která odtažení přidává k falešné trase |
timeline[] |
okamžiky pro rozbor, v časovém pořadí | |
timeline[].t_s, .utc |
s od začátku, ISO 8601 UTC | kdy (skutečný čas) |
timeline[].event |
celé číslo nebo null | identifikátor události; null u změn stavu přijímače |
timeline[].what |
řetězec | onset, full-effect, recovery-begins, recovered (události); fix-lost, fix-regained (přijímač) |
timeline[].text |
řetězec | vysvětlení |
track[] |
jeden řádek na log_interval_s |
|
track[].t_s, .utc |
s, ISO 8601 UTC | kdy (skutečný čas) |
track[].true_lat_deg, .true_lon_deg |
stupně | skutečná poloha |
track[].true_sog_kn, .true_cog_deg, .true_heading_deg |
uzly, stupně skutečné | skutečná rychlost a kurz nad zemí a směr podle gyra |
track[].fix_valid |
logická hodnota | přijímač hlásil zaměření |
track[].reported_lat_deg, .reported_lon_deg, .reported_sog_kn, .reported_cog_deg |
stupně, uzly, stupně skutečné, nebo null | co přijímač hlásil; null, dokud je zaměření ztraceno |
track[].position_error_m |
m nebo null | vodorovná vzdálenost mezi skutečnou a hlášenou polohou |
track[].time_offset_s |
s | hlášené UTC minus skutečné UTC |
track[].n_used, .n_tracked |
celá čísla | družice použité v zaměření a sledované |
track[].mean_cn0_dbhz |
dB-Hz nebo null | střední C/N0 sledovaných družic |
track[].active_events |
celá čísla | identifikátory událostí s účinkem v tomto okamžiku |
Přidání pole značku schématu nemění. Přejmenování nebo odebrání pole, případně změna významu nebo jednotky pole zvyšuje číslo (/2).
Knihovna scénářů#
scenarios/training/, každý je několik minut plavby s poznámkou školitele ve svém TOML:
| soubor | co ukazuje |
|---|---|
open-sea-jamming.toml |
C/N0 klesá společně, družice vypadávají, zaměření se ztratí a vrátí se |
coastal-drag-off.toml |
platné, zdravě vypadající zaměření se odtáhne o 1,4 km směrem k pobřeží; jednotně zvýšené C/N0 |
port-approach-time-spoof.toml |
poloha správná, UTC se při pomalém přiblížení k přístavu rozchází o 45 s dopředu |
combined-event.toml |
rušení, poté převzetí padělaným signálem s odtažením polohy a časovým posunem, poté zpoždění přehrávání |
fjord-natural-degradation.toml |
zablokovaná obloha, nikoli interference: stěny fjordu (REPRESENTATIVE přednastavení obzoru fjord) skrývají družice na východě a západě, poté se kanál znovu otevře (událost natural-degradation s tabulkou skyline) |
Polohy, data a trasy jsou smyšlené; knihovna neobsahuje žádné skutečné plavidlo, provozovatele ani záznam. Neříká nic o tom, jak by se jakýkoli přijímač nebo systém choval při interferenci.
Modelovací volby#
Generátor je tréninkový nástroj bez externího orákula a jeho čísla jsou modelovací volby, nikoli měření jakéhokoli přijímače. Jsou zvolena tak, aby vypadala jako běžný záznam přijímače: sklon C/N0 o 14 dB od zenitu k obzoru pod úrovní v zenitu (výchozí 47 dB-Hz) a posun jednotlivých družic o +/-1.5 dB, pomalý únik 0,8 dB po dobu 97 s a 0,5 dB po dobu 31 s, jitter 0,3 dB; prahy pro sledování (20 dB-Hz) a použití (28 dB-Hz); šum polohy (1,5 m při HDOP 1, korelovaný po dobu 30 s, svisle dvojnásobný); šum gyra 0,05 stupně a šum dříftu 0,03 kn; časová konstanta řízení 20 s a poloměry příjezdu k bodům trasy v modelu plavidla; a výběr družic podle azimutových sektorů. Výchozí hodnoty jsou v [receiver] a [vessel] a všechny lze ve scénáři změnit.
Zpětné načtení#
kshana receiver-trust umí tyto soubory načíst (format = "nmea"). Testy kontrolují každou větu každého scénáře knihovny podle jejích vlastních pravidel pro počet polí a kontrolní součet a vedou soubory přes tento čtecí modul, který interpretuje GGA, RMC a GSV a ostatní typy přeskočí, aniž by některý vynechal. Testy zafixují pro každý scénář zlatý výřez (tests/fixtures/nmea_training/); po zamýšlené změně jej vygenerujte znovu pomocí KSHANA_BLESS_GOLDEN=1.