Tłumaczenie maszynowe, niezweryfikowane przez osobę, dla której polski jest językiem ojczystym. Wzorcem jest wersja angielska.

Zaufanie do odbiornika i żegluga morskaEdytuj na GitHubieŹródło: docs/MARITIME-TRUST.md

Zaufanie morskie: czy mostek może zaufać tej pozycji?

kshana receiver-trust może dla poruszającego się statku obliczać bieżący wskaźnik zaufania 0-100 dla każdej pozycji, na podstawie tego, co każdy odbiornik już umieszcza na magistrali (najpierw NMEA 0183), i wskazywać, które kontrole go obniżyły. Jest to warstwa programowa działająca obok odbiornika. Nie jest odbiornikiem, nie zastępuje żadnego i nie czyni pozycji dokładniejszą.

Oprogramowanie wyłącznie doradcze. Kshana nie jest sprzętem nawigacyjnym z zatwierdzeniem typu (IEC 61108, IEC 61162) i nie została oceniona względem żadnej normy działania. Jej wskaźnik i bramka są pomocą dla osądu nawigatora. Za bezpieczną nawigację statku oraz za każdą decyzję o poleganiu na pozycji lub o zaprzestaniu polegania na niej odpowiada nadal operator.

Ta strona mówi, na co patrzą kontrole, co każda z nich może, a czego nie może wychwycić, jak uruchomić ją na żywo i co robi bramka. Mapowanie wskaźnika i każda wartość domyślna znajdują się w RECEIVER-TRUST.md.

Co odczytuje#

Statek jest deklarowany w pliku sesji, z limitami podanymi przed przebiegiem:

[platform]
kind = "vessel"
max_speed_kn = 20.0        # includes any current you want to allow for: it limits speed over ground
max_accel_mps2 = 0.2
max_turn_rate_dps = 2.0
antenna_height_m = 18.0    # antenna above the waterline
heading_sensor = true      # the stream carries a gyro or compass heading
Zdanie Odczytywane
GGA położenie, jakość pozycji (0 = brak pozycji), wysokość nad średnim poziomem morza, separacja geoidy, HDOP
RMC status (A ważna, V nie), prędkość i kurs nad dnem, data, tryb
VTG prędkość i kurs nad dnem, gdy RMC ich nie ma
HDT, THS kurs (THS tylko gdy jego tryb nie jest V)
VHW, VBW prędkość względem wody (VBW tylko gdy jej status to A)
ZDA czas
GSV moc sygnału każdego satelity (dB-Hz), elewacja i azymut (dla geometrii)
GSA współczynnik DOP i użyte satelity (dla geometrii, gdy GSV nie daje nieba; oraz podany HDOP, z którym porównuje strażnik)
$PKSOS,<A/F/N> status OSNMA zgłoszony przez odbiornik, przetłumaczony na to zdanie przez adapter czytający odbiornik: A uwierzytelniony, F niepowodzenie, N brak wyniku

Epoki, o których sam odbiornik mówi, że nie są pozycją satelitarną (jakość GGA 0 lub od 6 do 8: estymowana, ręczna, symulator; status RMC V albo tryb E, M, S, N), nie są używane do kontroli położenia i nie niosą żadnego dowodu w żadną stronę: odbiornik już to powiedział.

Pierwsze calibration_s sekund tworzy punkt odniesienia i nigdy nie jest oceniane. Każdy monitor patrzy tylko na bieżącą i wcześniejsze epoki, więc decyzja w danej epoce nie zmienia się po nadejściu późniejszych danych, a strumień na żywo daje ten sam wskaźnik co ten sam tekst odczytany jako plik.

Co każda kontrola wychwytuje, a czego nie może#

Kierunki między pozycjami (azymut toru używany przez kontrolę prędkości zwrotu, kurs wynikający z dwóch położeń) są kierunkiem cięciwy między nimi, czyli średnim azymutem geodezyjnej między pozycjami, a nie azymutem wprzód w pierwszej pozycji; oba różnią się o około połowę zbieżności południków między pozycjami (0,001 stopnia dla bazy 260 m na szerokości 59,5 stopnia).

Sfałszowane położenie musi zgadzać się z fizyką statku i z jego innymi czujnikami. Każda kontrola porównuje pozycję z jednym z nich. Kontrola jest tak niezależna, jak jej drugie źródło: kurs z kompasu GNSS albo „prędkość względem wody” wyprowadzona z GNSS nie jest niezależna od badanego odbiornika i nic nie wnosi.

Sprawdzenie Wychwytuje Nie potrafi
kinematic skok pozycji; trasę, której ruchu nie wyjaśniają zgłoszona prędkość i kurs; wynikającą z przebiegu prędkość, przyspieszenie lub prędkość zwrotu przekraczające podane granice dla statku zwodzenie (drag), którego zgłoszona prędkość i kurs podążają za sfałszowaną trasą i mieszczą się w granicach (odbiornik wyprowadza je z własnego rozwiązania, więc są ze sobą zgodne); zbyt wysoko podaną granicę prędkości
heading-course trasę odbiegającą od kierunku, w którym wskazuje statek, o więcej niż podany kąt znoszenia zwodzenie wzdłuż kursu (kurs się nie zmienia); kierunek z tego samego odbiornika lub z kompasu GNSS; znos poprzeczny powyżej tolerancji (fałszywy alarm); prędkości poniżej min_speed_kn
speed-log zwodzenie, które zmienia prędkość nad dnem względem prędkości względem wody log pochodzący z GNSS; prąd powyżej dopuszczalnej wartości (fałszywy alarm); zwodzenie wolniejsze niż dopuszczalna wartość
sea-level wysokość, która nie jest tam, gdzie umieszczają ją powierzchnia morza i podana wysokość anteny spoofer, który utrzymuje wiarygodną wysokość; tolerancja jest szeroka, ponieważ samodzielny błąd pionowy jest duży; separacja geoidy jest rejestrowana, ale nie sprawdzana, bo silnik nie ma modelu geoidy
cn0-spread, cn0-rise sygnaturę jednego nadajnika: C/N0 wszystkich satelitów spadające razem lub rosnące razem względem bazowego poziomu kalibracji spoofera, który kształtuje moc osobno dla każdego satelity; cokolwiek, gdy sam poziom bazowy jest objęty spoofingiem; zbyt wolną kadencję GSV, by dało się za nią nadążyć
time-consistency nieregularne skakanie czasu odbiornika lub jego bieg wstecz; względem zegara tego komputera, rozchodzenie się czasu odbiornika z nim (tylko strumienie w czasie rzeczywistym) sfałszowany czas, który jest spójny i stały; zegar, który jest błędny od samego początku
osnma zgłoszoną porażkę uwierzytelnienia OSNMA status jest odczytywany, a nie weryfikowany; spoofer, który tłumi zgłoszenie, nie jest widoczny
cn0-drop, loss-of-lock, agc, jam-ind odmowę mocy i utratę satelitów, jak w przypadku statycznym mówią, że środowisko jest wrogie, a nie że rozwiązanie pozycji jest błędne

Czego monitory oparte wyłącznie na NMEA nie potrafią. Spoofer, który odtwarza całą konstelację ze spójną wewnętrznie pozycją, prędkością, kursem zgodnym z kierunkiem, wiarygodną mocą poszczególnych satelitów i zgodnym zegarem, jest niewidoczny dla każdego z powyższych sprawdzeń: nic w zdaniach nie odróżnia jego rozwiązania od prawdziwego. Tak samo jest z odtworzeniem zarejestrowanych prawdziwych sygnałów. Lukę tę zamykają uwierzytelnianie (OSNMA albo odbiornik z własną ochroną przed spoofingiem) i niezależne czujniki nawigacyjne; ta warstwa może jedynie wykorzystać ich zgłaszany status. Strumień, który jest już poddawany spoofingowi w czasie tworzenia poziomu bazowego, nie ma czystego poziomu bazowego. Brak alarmu nie jest dowodem dobrego rozwiązania pozycji.

Wskaźnik zaufania#

Każda epoka po kalibracji otrzymuje ocenę od 0 do 100 wraz z przyczynami, dla których nie wynosi ona 100: które sprawdzenia odjęły punkty, ich statystyka względem progu i ich punkty. Przedziały (granice podane w sesji): nominal przy 90 lub więcej, degraded przy 55 lub więcej, untrusted poniżej. Odwzorowanie, każda waga i jej uzasadnienie znajdują się w RECEIVER-TRUST.md; jest deterministyczne i ustalone przed oceną dziennika, bez uczenia i bez niczego dopasowywanego do zdarzeń.

Każde wyjście dla statku zawiera oświadczenie doradcze: klucz advisory w JSON wyniku i w każdej linii na żywo, pierwszy wiersz komentarza # w CSV (czytniki pomijają go opcją komentarza), <desc> oraz stopkę SVG. Wyjścia przebiegu wsadowego: session.result.json (z modelem oceny i odjęciami każdej epoki), session.trust.csv (z kolumnami score i score_reasons) oraz session.trust.svg, który dla statku jest trasą zgłoszoną przez odbiornik, pokolorowaną według przedziału zaufania, nad wykresem oceny w czasie.

Demonstracja syntetyczna#

examples/maritime-trust/ zawiera zmyślony dziennik NMEA promu na trasie Tallinn–Helsinki (50-minutowy fragment, około 17 kn, 1 Hz: GGA, RMC, VTG, kierunek z żyroskopu, log prędkości, GSV z wiarygodnym niebem), w którym od 1500 s odciągnięcie pozycji (drag-off) odsuwa zgłaszaną pozycję od rzeczywistej pozycji statku. Odbiornik przez cały czas zgłasza ważne rozwiązanie pozycji; spada wskaźnik zaufania, przechodząc przez przedział obniżony do przedziału braku zaufania. session.toml podaje przed przebiegiem każdy próg, granice statku i każdą wagę oceny.

kshana receiver-trust examples/maritime-trust/session.toml
kshana receiver-trust live examples/maritime-trust/session.toml \
  --file examples/maritime-trust/tallinn-helsinki.nmea --gate --json trust.jsonl > gated.nmea

Dziennik to tekst zapisany do pliku przez cargo run --example gen_maritime_trust_demo: nie modeluje żadnego sygnału radiowego i niczego nie nadaje. Nie jest pomiarem, a trasa jest ilustracyjna, nie jest mapą nawigacyjną. tests/receiver_trust_maritime_demo.rs utrwala dziennik i oczekiwane wyniki jako zabezpieczenia regresji na danych syntetycznych; nie mówią nic o tym, jak jakikolwiek monitor radzi sobie przy rzeczywistych zakłóceniach.

Wskaźnik zaufania podczas jednego syntetycznego rejsu, z rzeczywistego przebiegu silnika v0.40.0 na examples/maritime-trust (zmyślony dziennik NMEA promu na trasie Tallinn–Helsinki, 3001 epok przy 1 Hz). Trzy pasy dzielą jedną oś czasu. Góra: odległość między pozycją zgłaszaną przez odbiornik a rzeczywistą pozycją statku, która pozostaje w granicach kilku metrów do około 1576 s, gdy zaplanowane w dzienniku odciągnięcie pozycji ją odsuwa, podczas gdy odbiornik nadal zgłasza ważne rozwiązanie pozycji. Środek: wskaźnik zaufania od 0 do 100, nieobliczany w pierwszych 300 s kalibracji, w przedziale nominalnym (co najmniej 90) do odciągnięcia pozycji, a potem spadający przez przedział obniżony (co najmniej 55) do przedziału braku zaufania. Dół: przedział każdej epoki jako kolorowa wstęga z jego nazwą. Wynik ma charakter doradczy. Oprogramowanie wyłącznie doradcze, nie jest to sprzęt nawigacyjny z zatwierdzeniem typu (IEC 61108, IEC 61162): za nawigację statku odpowiada nadal operator. Dziennik jest zmyślony, aby pokazać format i monitory; nie jest pomiarem i nic nie mówi o tym, jak poradziłby sobie jakikolwiek odbiornik.Wskaźnik zaufania podczas jednego syntetycznego rejsu, z rzeczywistego przebiegu silnika v0.40.0 na examples/maritime-trust (zmyślony dziennik NMEA promu na trasie Tallinn–Helsinki, 3001 epok przy 1 Hz). Trzy pasy dzielą jedną oś czasu. Góra: odległość między pozycją zgłaszaną przez odbiornik a rzeczywistą pozycją statku, która pozostaje w granicach kilku metrów do około 1576 s, gdy zaplanowane w dzienniku odciągnięcie pozycji ją odsuwa, podczas gdy odbiornik nadal zgłasza ważne rozwiązanie pozycji. Środek: wskaźnik zaufania od 0 do 100, nieobliczany w pierwszych 300 s kalibracji, w przedziale nominalnym (co najmniej 90) do odciągnięcia pozycji, a potem spadający przez przedział obniżony (co najmniej 55) do przedziału braku zaufania. Dół: przedział każdej epoki jako kolorowa wstęga z jego nazwą. Wynik ma charakter doradczy. Oprogramowanie wyłącznie doradcze, nie jest to sprzęt nawigacyjny z zatwierdzeniem typu (IEC 61108, IEC 61162): za nawigację statku odpowiada nadal operator. Dziennik jest zmyślony, aby pokazać format i monitory; nie jest pomiarem i nic nie mówi o tym, jak poradziłby sobie jakikolwiek odbiornik.

Rysunek jest tworzony przez tools/gen_readme_assets.py z rzeczywistego przebiegu tej demonstracji (kshana receiver-trust examples/maritime-trust/session.toml); wynik ma charakter doradczy, a dziennik jest zmyślony.

Specyfikacja widoku Studio#

Dla tego, kto buduje widok Studio dla przebiegu statku. Nic w tej sekcji nie jest jeszcze zaimplementowane w Studio; strona silnika (dane poniżej) jest.

Dane wejściowe. Jedno z:

  • JSON wyniku przebiegu wsadowego (kshana receiver-trust <session.toml> albo to samo przez receiver_trust(toml) w pakiecie WebAssembly z dziennikiem w treści): score_model (granice przedziałów, narastanie, utrzymanie dowodu, każda waga), monitors_run, states i epochs[], każdy z t_s, state, alarms, score.{score,band,deductions[]}, marine.{position:[lat,lon], stats, ratios} oraz od 0,36 geometry i class każdego odjęcia, z geometry_model i geometry_summary na najwyższym poziomie; albo
  • linie JSON na żywo (schemat powyżej), po jednym obiekcie na epokę, dopisywane w miarę trwania strumienia. Każda linia zawiera zgłoszone przez odbiornik position (schemat 1,1).

Zestaw demonstracyjny to examples/maritime-trust/: session.toml, tallinn-helsinki.nmea (dziennik) i tallinn-helsinki.truth.csv (t_s,true_lat_deg,true_lon_deg: gdzie statek naprawdę był, czego nie ma żaden prawdziwy dziennik). Widok powinien uruchomić sesję i równolegle czytać plik prawdy.

Co narysować.

  1. Trasa, północ u góry, jedna skala na obu osiach: zgłaszane przez odbiornik pozycje jako linia pokolorowana według przedziału epoki (szary kalibracja, zielony nominalny, bursztynowy obniżony, czerwony brak zaufania), z oznaczonym początkiem i końcem oraz podziałką. Dla demonstracji prawdziwa trasa jako cienka neutralna linia pod spodem, aby odciągnięcie pozycji było widać jako rozchodzenie się obu; przełącznik prawdziwej trasy i odczyt odsunięcia w metrach w chwili wskazanej kursorem.
  2. Oś czasu oceny: ocena od 0 do 100 w funkcji czasu, granice przedziałów (nominal_min, degraded_min z score_model) jako linie przerywane, przedział jako pasek poniżej oraz początek każdego podanego zdarzenia jako znacznik. Oś czasu jest wspólna z trasą.
  3. Przyczyny: dla epoki pod kursorem odjęcia (monitor, stosunek do progu, punkty) jako poziome słupki, od największego, z wagą każdego monitora z score_model.weights; monitory, które działały i nic nie kosztowały, pokazane blado, monitory, które nie działały (brak w monitors_run), wypisane jako „not run”, nigdy jako zaliczone. Monitor geometry nie ma wpisu score_model.weights: jego limit to geometry_model.cap_in_force.
  4. Paski monitorów: jeden cienki pasek na każdy monitor w monitors_run, pokazujący jego stosunek w czasie (alarm przy 1), aby czytelnik widział, które sprawdzenie poruszyło się pierwsze.
  5. Stan bramki: w widoku na żywo gate każdej epoki (off, passed, withheld) jako pasek pod paskiem przedziału oraz najnowszy $PKSHT. W widoku wsadowym epoki, które bramka by wstrzymała, to te, których przedział jest bez zaufania, z zastosowanym wstrzymaniem zwolnienia.
  6. Pas geometrii (0,36): pasek pod paskiem przedziału pokolorowany według geometry.status (zielony dobry, bursztynowy obniżony, szary kreskowany nieznany), w innej rodzinie kolorów niż pasy niespójności i środowiska, z legendą „geometry: the sky, not the signal”. Odjęcia pokolorowane według class (geometria, środowisko, niespójność) w panelu przyczyn i na paskach monitorów oraz liczby epok w poszczególnych klasach z geometry_summary obok liczb epok w przedziałach. Dla epoki pod kursorem: geometry.note, n_used, HDOP, PDOP, VDOP, source, age_s oraz flaga, gdy ustawiono reported_derived_mismatch (odjęcie za geometrię jest wtedy niespójnością). unknown jest pokazywane jako „geometry unknown: no GSV or GSA in the log”, nigdy jako dobre. Progi [geometry] i ich pochodzenie z geometry_model znajdują się obok ustawień oceny. Uwaga doradcza pozostaje.
  7. Rozwiązanie pozycji zgłoszone przez odbiornik: odbiornik demonstracji przez cały czas zgłasza ważne rozwiązanie (jakość GGA 1, status RMC A); powiedz to w legendzie, ponieważ na tym polega sens widoku.

Interakcje. Jeden kursor czasu wspólny dla wszystkich paneli (przeciąganie, klawisze strzałek i przycisk odtwarzania, który odtwarza od 1x do 60x); najechanie na trasę lub dowolny pasek go przesuwa. Kliknięcie odjęcia podświetla epoki, w których dany monitor przekroczył swój próg wejścia. Filtr przedziału (pokaż tylko epoki obniżone i bez zaufania) oraz skok do pierwszego odjęcia i do pierwszej epoki bez zaufania. Podpowiedź przy każdej nazwie monitora z jednowierszowym opisem z tej strony. Progi i wagi sesji są pokazane tylko do odczytu obok wykresu, aby na ekranie było widać, czego użyto do oceny.

Brzmienie do zachowania. Strona musi mówić, że jest to oprogramowanie doradcze, a nie sprzęt nawigacyjny z zatwierdzeniem typu, że demonstracja jest syntetycznym tekstem ze zmyślonym odciągnięciem pozycji oraz że rozwiązanie pozycji bez alarmu nie jest przez to dobre (zob. ograniczenia powyżej). Żadna liczba na stronie nie powinna być odczytywana jako miara tego, jak sprawdzenia radzą sobie przy rzeczywistych zakłóceniach.

Z kodu#

Dla wywołujących, którzy mają sesję i bajty w pamięci (bez plików, zegara i gniazd; bezpieczne dla WebAssembly), kshana::receiver_trust::assess udostępnia:

  • assess_vessel_log(session_toml, log_bytes) -> Result<ReceiverTrustResult, String>: cały dziennik, oceniony jak przebieg wsadowy; ten sam wynik co kshana receiver-trust <session.toml>, serializowany do JSON wyniku (score_model, monitors_run, epochs[] z ocenami i odjęciami).
  • assess_stream_excerpt(session_toml, excerpt_bytes) -> Result<ExcerptAssessment, String>: ograniczony fragment strumienia (najwyżej 2 MiB i 20 000 epok, a zarazem dość długi, by obejmować okno kalibracji), oceniony tak, jak ocenia tryb na żywo, i zwrócony w schemacie linii JSON na żywo (epochs[], ostatnie $PKSHT, podsumowanie liczb epok w przedziałach, najniższa i końcowa ocena, czas pierwszej epoki bez zaufania). Czas odbiornika nie jest porównywany z zegarem hosta. Długotrwały tryb na żywo (gniazda, dopisywany plik, bramka) należy do pliku binarnego.

Oba wymagają sesji z [platform] kind = "vessel"; jej tabela [log] jest opcjonalna.

Uruchom na żywo#

# stdin: a serial port read by another tool, or a multiplexer's output
some-nmea-source | kshana receiver-trust live session.toml

# a log file that is being appended to (it starts at the beginning; --from-end skips what is there)
kshana receiver-trust live session.toml --file /var/log/nmea.log --follow

# a TCP server (a multiplexer or a terminal server) or UDP datagrams (a bridge network)
kshana receiver-trust live session.toml --tcp 192.0.2.10:10110
kshana receiver-trust live session.toml --udp 10110

Sesja to ten sam session.toml co w przebiegu wsadowym, z tabelą [platform], która deklaruje kind = "vessel"; jej tabela [log] nie jest potrzebna. Porty szeregowe nie są jeszcze otwierane bezpośrednio: odczytaj port narzędziem, którego już używasz (stty i cat, serwer terminali, multiplekser) i przekaż dane potokiem lub dalej. Bezpośrednie wejście szeregowe może pojawić się później.

Każda zakończona epoka zapisuje jedną linię JSON na stdout:

{"seq":941,"t_s":940.0,"time":"2025-06-14T08:15:40.000Z","state":"degraded","score":60.0,
 "deductions":[{"monitor":"heading-course","ratio":1.5,"points":40.0}],
 "alarms":["heading-course"],"gate":"off","note":null,
 "position":{"lat_deg":59.8123456,"lon_deg":24.9012345,"height_m":39.4}}

state to calibrating, nominal, degraded lub untrusted (przedział oceny, z granicami w tabeli [score] sesji); score jest nieobecne podczas kalibracji; deductions wymieniają, które sprawdzenia odjęły punkty i ile, od największych.

Schemat linii JSON (wersja 1,1)#

Jeden obiekt JSON na zakończoną epokę, klucze w tej kolejności:

Klucz Typ Znaczenie
seq liczba całkowita liczba zgłoszonych epok, od 1
t_s liczba sekundy od pierwszej epoki strumienia
time ciąg znaków lub null czas epoki podany przez strumień (ISO-8601 UTC z datą, gdy widziano RMC, w przeciwnym razie hh:mm:ss.mmm UTC (date not in log))
state ciąg znaków calibrating, nominal, degraded lub untrusted
score liczba lub null od 0 do 100, jedno miejsce po przecinku; null podczas kalibracji lub gdy note podaje, dlaczego nie można jej było wytworzyć
deductions tablica {"monitor": string, "ratio": number, "points": number, "class": string}, od największych punktów; ratio to statystyka podzielona przez próg (alarm przy 1 lub więcej); wymienione są tylko monitory, które kosztowały punkty; class (dodano w 1,3) to geometry, environment lub inconsistency
alarms tablica ciągów monitory na poziomie progu lub powyżej niego
gate ciąg znaków off, passed lub withheld
note ciąg znaków lub null dlaczego nie wytworzono oceny (na przykład zadeklarowany czujnik kierunku jest nieobecny)
position obiekt lub null (dodano w 1,1) pozycja zgłoszona przez odbiornik w tej epoce, {"lat_deg", "lon_deg", "height_m"} (wysokość elipsoidalna, gdy zdanie podaje separację geoidy, w przeciwnym razie nad średnim poziomem morza); null, gdy odbiornik żadnej nie podał, w tym w epokach kalibracji bez rozwiązania
advisory ciąg znaków (dodano w 1,2) czym to oprogramowanie jest, a czym nie jest: doradcze, nie jest to sprzęt nawigacyjny z zatwierdzeniem typu, operator nadal ponosi odpowiedzialność
geometry obiekt (dodano w 1,3) geometria satelitów: status (good, degraded, unknown, gdy strumień nie ma elewacji i azymutów GSV ani GSA), reasons (few-satellites, high-pdop, high-hdop, sky-blocked), source (derived, reported, none), n_used, hdop, pdop, vdop, open_fraction, max_azimuth_gap_deg, age_s, reported_hdop, reported_derived_mismatch, note, in_view, signal_loss (satelity widoczne, ale nieśledzone, gdy DOP widocznych jest dobry: odjęcie za geometrię jest wtedy environment), label (good, fair, poor, unknown: zawsze zgłaszane, nigdy nieoceniane; ocena odejmuje punkty tylko za poor) (zob. RECEIVER-TRUST.md)

Nazwy monitorów (kebab-case; 17): 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 oraz od 1,3 geometry. W późniejszych wersjach mogą zostać dodane nowe nazwy; konsumenci powinni traktować nieznaną nazwę monitora jako monitor. Układ $PKSHT poniżej niesie wersję formatu w pierwszym polu; ten schemat JSON ma wersję 1,3: 1,1 dodała position, 1,2 advisory, 1,3 geometry na końcu i class w każdym odjęciu, a zmienia się wyłącznie przez dodawanie kluczy na końcu.

Wejście uwierzytelniania#

Monitor osnma przyjmuje status uwierzytelnienia poszczególnych satelitów ze źródła uwierzytelniania przez MarineObs::sat_auth (lista (satellite, status), status Authenticated, Failed lub Unavailable), obok ogólnego MarineObs::osnma. Po stronie NMEA to samo przenosi $PKSOS,<A|F|N>[,<sat>:<A|F|N>...], na przykład $PKSOS,A,E11:A,E19:F. Każda porażka, ogólna lub dla jednego satelity, uruchamia alarm monitora i kosztuje całą jego wagę (otrzymuje stosunek 1,5); sukces nie jest dowodem. Kshana niczego tu nie weryfikuje: za zgłaszany status odpowiada źródło, które to robi.

Epoka jest zakończona, gdy nadejdzie następne zdanie z czasem; zdania wolniejszych lub niezsynchronizowanych przyrządów (żyroskop kilka dziesiątych sekundy za odbiornikiem), które nadejdą wcześniej, należą do niej. Jeśli strumień zatrzyma się na [live] idle_flush_s (domyślnie 1,5 s, ustaw wartość powyżej najdłuższej przerwy między zdaniami z czasem z twojego odbiornika), epoka jest kończona w takim stanie, w jakim jest. Pierwsze calibration_s sekund strumienia tworzy poziom bazowy i nigdy nie jest oceniane, więc strumień, który jest już poddawany spoofingowi w chwili pierwszego podłączenia, nie ma czystego poziomu bazowego: uruchom warstwę przed rejsem albo wtedy, gdy wiadomo, że rozwiązanie pozycji jest dobre. Okno kalibracji zamyka się raz, według kolejności nadejścia: epoka, której czas jest wcześniejszy niż czas już widziany (cofnięcie, odtworzenie początku strumienia), nigdy nie jest kalibracją, cokolwiek mówi jej czas; jest oceniana z pełnym odjęciem time-consistency, co oznacza brak zaufania. Silnik na żywo ocenia każdą epokę względem epok kalibracji i mniej więcej ostatniej minuty strumienia, więc jego koszt na epokę rośnie z calibration_s razy częstość epok; na szybkim odbiorniku utrzymuj krótkie okno. Jego bufory są ograniczone (zalew linii bez zdania z czasem jest kończony co 5 000 linii, kalibracja i historia są ograniczone do 20 000 epok).

Czas odbiornika jest też porównywany z monotonicznym zegarem tego komputera, co ma sens tylko dla strumienia nadchodzącego w czasie rzeczywistym. Zapisany dziennik podawany z pełną szybkością przez stdin, TCP lub UDP z konstrukcji uruchamia to sprawdzenie: przekaż --replay. (--file bez --follow już to implikuje.) --file ... --follow jest czytane jako odtwarzanie, dopóki nie zostanie przeczytane do końca, a zegar hosta jest włączany od tej chwili, więc zaległość nie wygląda na błąd zegara; sprawdzenie wymaga wtedy, aby okno kalibracji było jeszcze otwarte (w przeciwnym razie nie ma poziomu bazowego i się nie uruchamia).

Zakończenia strumieni i błędy: stdin i plik czytany do końca kończą się normalnie (wyjście 0). Połączenie TCP zamknięte przez drugą stronę nie jest normalnym końcem strumienia, który powinien trwać: warstwa kończy działanie z kodem niezerowym po ocenieniu i zapisaniu wszystkiego, co odebrała, i nie łączy się ponownie, więc uruchamiaj ją pod nadzorcą, który ją restartuje. Datagramy UDP dzielące zdanie są łączone; czytniki stdin, pliku i TCP są wspierane ograniczoną kolejką, która wywiera nacisk zwrotny na nadawcę (nic nie ginie), natomiast UDP, które nie może wywierać nacisku zwrotnego, odrzuca datagramy, których silnik nie może przyjąć, i informuje o tym na stderr. --udp <port> wiąże się z adresem pętli zwrotnej; podaj --udp <addr>:<port>, aby nasłuchiwać gdzie indziej (wypisywane jest ostrzeżenie).

$PKSHT: zdanie własnościowe#

Każda epoka tworzy też jedno zdanie NMEA 0183 z poprawną sumą kontrolną, które --pksht <path|-> zapisuje do pliku lub na stdout i które bramka wstawia do przekazywanego strumienia:

$PKSHT,1,080140.25,30.0,U,W,heading-course:40.0/cn0-spread:30.0*2F
Pole Znaczenie
1 1: wersja formatu
2 czas UTC epoki, hhmmss.ss; puste, jeśli strumień go nie podał
3 wskaźnik zaufania od 0 do 100, jedno miejsce po przecinku; puste podczas kalibracji lub gdy nie można go było wytworzyć
4 przedział: C kalibracja, N nominalny, D obniżony, U bez zaufania
5 bramka: - wyłączona, P przepuszczone, W wstrzymane (rozwiązanie pozycji oznaczono jako nieważne w przekazywanym cyklu)
6 do dwóch przyczyn, monitor:points połączonych znakiem /; puste, gdy nic nie odjęto

Adres to P + mnemonik producenta KSH + T. Urządzenia, które nie znają zdania własnościowego, ignorują je. Kshana ignoruje własne $PKSHT na wejściu.

Tryb bramki#

--gate umieszcza Kshana między odbiornikiem a urządzeniami, które korzystają z jego rozwiązania pozycji (system map, system sterowania torem). Strumień NMEA wchodzi, wychodzi na stdout i jest:

  • przepuszczany bez zmian, dopóki epoka nie jest bez zaufania (oraz podczas kalibracji), z $PKSHT po każdym cyklu zdań; oraz
  • oznaczany jako nieważny, gdy jest bez zaufania: jakość GGA 0; status RMC V (oraz jego wskaźnik trybu N i status nawigacyjny V, gdzie występują); tryb GNS N w każdej pozycji; status GLL V i tryb N; tryb VTG N, gdzie go ma. Pola pozycji pozostają bez zmian: chodzi o to, aby urządzenie widziało, że sam odbiornik deklaruje rozwiązanie jako nieważne, i podniosło własny alarm. W każdym przepisanym zdaniu suma kontrolna jest obliczana na nowo.

Po wstrzymaniu rozwiązanie jest zwalniane dopiero wtedy, gdy epoki przez [live] gate_release_s (domyślnie 30 s) pozostawały poza przedziałem bez zaufania, więc ocena na granicy przedziału nie może powodować migotania rozwiązania. Linie JSON trafiają tylko tam, gdzie wskazuje --json <path> (domyślnie nigdzie, bo strumień ma stdout).

receiver-nmea-source | kshana receiver-trust live session.toml --gate --json trust.jsonl | downstream-equipment

Aby umożliwić plotterowi map bezpośrednie połączenie, udostępnij strumień po bramce przez TCP zamiast na stdout:

receiver-nmea-source | kshana receiver-trust live session.toml --gate --listen tcp:10110

--listen tcp:<port> nasłuchuje na adresie pętli zwrotnej; tcp:<addr>:<port> nasłuchuje gdzie indziej (wypisywane jest ostrzeżenie, ponieważ każdy, kto dotrze do adresu, może czytać strumień). Może się połączyć dowolna liczba klientów; każdy dostaje ten sam strumień od chwili połączenia, a klienci tylko czytają. Każdy klient ma własną ograniczoną kolejkę i własny zapis, więc ten, który nie nadąża, jest odłączany (jego połączenie zamykane, linia na stderr) i nigdy nie opóźnia pozostałych ani wejścia. --listen wymaga --gate; stdout nie niesie wtedy nic ze strumienia, więc --json - jest wolne.

Czego bramka nie robi i co warto wiedzieć przed jej użyciem:

  • Jest dobrowolna. Nic nie oznacza rozwiązania jako nieważnego, jeśli nie podano --gate.
  • Dodaje opóźnienie: cykl jest wstrzymywany, dopóki jego epoka nie zostanie oceniona, czyli do następnego zdania z czasem (około jednego cyklu: sekundy dla odbiornika 1 Hz), albo idle_flush_s po ostatnim, gdy strumień utknie. Urządzenia, które potrzebują zdania w ciągu kilkudziesięciu milisekund od wyjścia odbiornika, nie mogą się za nią znajdować.
  • Jest pojedynczym punktem w łańcuchu: jeśli się zatrzyma, zatrzyma się strumień. Uruchamiaj ją pod nadzorem i z góry zdecyduj, co robi urządzenie dalej w łańcuchu bez strumienia.
  • W razie własnych usterek zawodzi w bezpiecznym kierunku: jeśli monitory nie mogą wytworzyć oceny po kalibracji (zadeklarowany czujnik kierunku nic nie wysyła, za mało epok kalibracji), epoka jest bez zaufania, niesie note i jest wstrzymywana; wstrzymanie zwolnienia jest mierzone zegarem tego komputera, a nie czasem odbiornika, który kontroluje spoofer (dla odtworzenia jest tylko czas odbiornika).
  • Może wstrzymać prawidłowe rozwiązanie pozycji (fałszywy alarm), a także przepuścić sfałszowane (niewykryte zdarzenie). Monitory sprawdzają rozwiązanie pozycji na tle fizyki statku i jego pozostałych czujników; podróbka spójna ze wszystkimi z nich nie zostanie zauważona (zob. ograniczenia poniżej).
  • Oczekuje czystego strumienia tekstowego NMEA 0183. Ramki binarne wmieszane w strumień są przekazywane bez zmian, ale $PKSHT może wtedy trafić między bajty ramki.
  • Nie jest to sprzęt z zatwierdzeniem typu, a nic w nim nie zostało ocenione względem IEC 61108 ani IEC 61162. Za nawigację statku odpowiada nadal operator.