Kshana · क्षण · precyzyjna chwila
Otwartoźródłowy symulator odporności PNT (pozycjonowanie, nawigacja i czas).
Wydanie v0.40.0 176 z 401 możliwości sprawdzonych względem niezależnych zewnętrznych wyroczni Około 95% pokrycia linii, z progiem 85% w ciągłej integracji Licencja: AGPL-3.0-only lub licencja komercyjna DOI 10.5281/zenodo.20528627
Przećwicz minutę, w której GNSS gaśnie#
Kshana odtwarza zagłuszanie, spoofing i holdover zegara, gdy zawodzą sygnały GNSS (globalnego systemu nawigacji satelitarnej), i mówi, jak długo system utrzymuje czas i pozycję w granicach budżetu oraz który zegar lub czujnik daje największy zapas. To jest pakiet WebAssembly: cały silnik w JavaScript, w przeglądarce lub w Node.js. Każdy przebieg jest odtwarzalny co do bitu na podstawie scenariusza, ziarna (seed) i wersji silnika.
Wypróbuj go najpierw bez niczego do instalowania: Kshana Studio uruchamia cały silnik w przeglądarce, skompilowany do WebAssembly, i niczego nie wysyła.
Dowody#
176 z 401 możliwości sprawdzonych względem niezależnych zewnętrznych wyroczni; 221 uczciwie oznaczonych jako obliczone na podstawie modelu, 4 należące do partnera. Każda możliwość nosi jedną etykietę w sprawdzanym maszynowo rejestrze (ledger): VALIDATED (niezależna zewnętrzna wyrocznia się zgadza: prawdziwe dane, niezależna implementacja lub opublikowane wektory wzorcowe), MODELLED (wewnętrznie spójne i powiedziane wprost) lub PARTNER (odpowiada za to partner sprzętowy). Wśród kontroli: wszystkie 666 wektorów SGP4 (Simplified General Perturbations 4) z AIAA (American Institute of Aeronautics and Astronautics) 2006-6753 z dokładnością do 4,12 mm oraz model sił Cowella z dokładnością do 0,08 m względem Orekit 12,2.
Instalacja#
npm install kshana
Sposób użycia#
Pakiet jest modułem ES (ECMAScript, standardowy JavaScript) z ładunkiem WebAssembly, zbudowanym dla przeglądarki. Zainicjuj go raz, a potem wywołuj silnik synchronicznie. Jedyna różnica między przeglądarką a Node.js polega na sposobie wczytania binarnego pliku WebAssembly.
W przeglądarce (przez bundler lub stronę, która serwuje node_modules/kshana/) init() pobiera kshana_bg.wasm z miejsca obok modułu:
import init, { run, summary, chart_svg, version } from "kshana";
await init(); // fetch and compile the WebAssembly binary
W Node.js init() kończy się błędem TypeError: fetch failed (fetch w Node nie potrafi czytać pliku lokalnego), więc wczytaj plik binarny z dysku i przekaż go do initSync:
import { readFileSync } from "node:fs";
import { createRequire } from "node:module";
import { initSync, run, summary, chart_svg, version } from "kshana";
const wasmPath = createRequire(import.meta.url).resolve("kshana/kshana_bg.wasm");
initSync({ module: readFileSync(wasmPath) }); // compile the WebAssembly binary
Zapisz wersję dla Node.js jako plik .mjs (albo ustaw "type": "module" w package.json), aby import działało. Dalej oba warianty są takie same:
// A complete scenario, not a sketch: scenarios/clock-holdover.toml without its comment
// lines. It runs 2 h, 10 min of GNSS then about 1.8 h with GNSS denied, and asks how long
// a strontium optical clock and a chip-scale atomic clock (CSAC) each hold time to within
// 20 ns. sigma_y(1s) is a clock's Allan deviation at an averaging time of one second;
// q_wf, the white-frequency-noise intensity, is its square.
const toml = `
seed = 42
threshold_ns = 20.0
[time]
step_s = 10.0
duration_s = 7200.0
[gnss]
windows = [
{ t0 = 0.0, t1 = 600.0, state = "nominal" },
{ t0 = 600.0, t1 = 7200.0, state = "denied" },
]
[clock_quantum]
id = "optical-sr-lattice"
provenance = "Strontium optical lattice clock, space-oriented goal sigma_y(1s)=1e-15 (Origlia/Schiller/Bongs et al., arXiv:1503.08457); q_wf=sigma_y(1s)^2; ground-demonstrator maturity, not flown; flicker/aging not modeled"
y0 = 5.0e-17
q_wf = 1.0e-30
q_rw = 0.0
[clock_classical]
id = "csac-sa45s"
provenance = "Microchip SA65 / SA.45s CSAC datasheet sigma_y(1s)=3e-10; q_wf=sigma_y(1s)^2; flicker/aging not modeled"
y0 = 5.0e-10
q_wf = 9.0e-20
q_rw = 0.0
`;
const result = JSON.parse(run(toml)); // the full result document
// timing_p95_ns: the 95th-percentile timing error over the GNSS outage, in nanoseconds
console.log(version(), result.classical.fom.timing_p95_ns);
console.log(summary(toml)); // the one-line result string
const svg = chart_svg(toml); // the same chart the command-line interface (CLI) writes
TypeScript widzi typowane wyniki: run_typed(toml) zwraca RunOutput (json, svg, summary, csv: string | null, data: ResultDocument), scenario_kinds() zwraca KindMeta[], którego name jest unią ScenarioKind wszystkich rodzajów, a error_kind() zwraca ErrorKind (albo "" przy powodzeniu). Własne pola każdego dokumentu wyniku różnią się w zależności od rodzaju; ResultDocument typuje wspólną kopertę (schema_version, engine_version oraz blok units z elementami FieldUnit).
import { run_typed, scenario_kinds, type ScenarioKind } from "kshana";
const out = run_typed(toml);
const units = out.data.units; // Record<string, FieldUnit>
const kinds: ScenarioKind[] = scenario_kinds().map((k) => k.name);
Cztery kolejne funkcje opisują silnik dla interfejsu użytkownika. kind_modules() zwraca obiekt JSON od rodzaju do modułów wymienionych w jego wierszach macierzy weryfikacji, field_importance() zwraca obiekt od rodzaju do pól wyniku, które odpowiadają na jego pytanie (metadane do wyświetlania; silnik nigdy ich nie czyta), iq_signals() zwraca nazwy sygnałów, które przyjmuje iq_run_short, a iq_run_short(fs_hz, duration_s, signal, ids, dopplers_hz, cn0_dbhz, seed) zwraca krótką syntetyczną scenę IQ, pozyskaną i śledzoną w pamięci (najwyżej 0,25 s, 1 000 000 próbek i 8 satelitów), z taką samą odpowiedzią jak w wersji natywnej.
import { list_examples, get_example, export_scenario, animate_scenario } from "kshana";
const names = JSON.parse(list_examples("")).scenarios.map((s) => s.name); // the bundled scenarios
const toml = get_example("orbit-gnss-challenged"); // its TOML, byte for byte
const czml = JSON.parse(export_scenario(toml, "czml")).files[0].content; // a CZML file, in memory
const player = JSON.parse(animate_scenario(toml, "html", 0, NaN, 0)).files; // {name: html text}
W wersji WebAssembly każdy punkt wejścia to osobne wywołanie: run (dokument wyniku jako ciąg JSON), summary, chart_svg, table_csv (tabela CSV (wartości rozdzielone przecinkami) scenariusza jako ciąg albo undefined dla rodzajów, które nie publikują tabeli; przy nieprawidłowym scenariuszu zgłasza wyjątek), run_all (jeden przebieg silnika zwracający {json, svg, summary, csv} jako ciąg JSON — użyj go, gdy potrzebujesz więcej niż jednego wyniku, ponieważ każde inne wywołanie uruchamia scenariusz od nowa), run_typed (te same wyniki jako jeden typowany obiekt, z dokumentem już sparsowanym jako data), version, list_kinds / scenario_kinds / error_kind (introspekcja; scenario_kinds zwraca sparsowaną listę), encode_permalink / decode_permalink — kodek linku do udostępniania (URL, jednolity lokalizator zasobów), którego Kshana Studio używa do przekazywania całego scenariusza we fragmencie paska adresu — oraz export_sp3 / export_omm / export_oem, czyli artefakty efemeryd SP3-c (wersja c formatu Standard Product 3) i CCSDS (Consultative Committee for Space Data Systems) — OMM, Orbit Mean-elements Message, i OEM, Orbit Ephemeris Message — które zapisuje CLI — oraz receiver_trust, które ocenia prawdziwy dziennik odbiornika opisany scenariuszem receiver-trust i zwraca {json, csv, svg, summary} jako ciąg JSON (przeglądarka nie ma systemu plików, więc dziennik i ewentualny plik nawigacyjny muszą być w scenariuszu wbudowane jako text lub base64; tabela [platform] kind = "vessel" dodaje monitory morskie i wskaźnik zaufania 0-100, wyłącznie doradczo), export_formats / export_scenario (jakie formaty interoperacyjności obsługuje scenariusz, bez jego uruchamiania, oraz jeden eksport w pamięci: czml, kml, geojson, stk lub sigmf jako JSON {format, spec_url, files}, bajt w bajt identyczny dla tego samego scenariusza, nic nie jest wysyłane), import_route (trasa GeoJSON zapisana w scenariuszu toru po punktach trasy, odpowiednik --import-route w wierszu poleceń), animate_scenario (szereg czasowy przebiegu jako animowany SVG, pojedynczy odtwarzacz HTML lub klatki SVG), list_examples / get_example (dołączone scenariusze referencyjne i ich TOML), evidence_attach_timestamp (powiązanie tokenu RFC 3161 z pakietem dowodowym w pamięci; pakiet nadal musi przejść weryfikację, a podpis urzędu znakowania czasem nie jest sprawdzany), osnma_verify (które dane nawigacyjne Galileo satelitów uwierzytelnia plik stron I/NAV lub strumień UBX, z zaufanym korzeniem Merkle'a lub kluczami publicznymi i opcjonalnym niezależnym czasem odniesienia; uwierzytelnia dane i nie zawiera twierdzenia o skuteczności ochrony przed spoofingiem; nic nie jest wysyłane), receiver_trust_replay (ograniczony fragment NMEA oceniany tak, jak ocenia go tryb na żywo; bez bramki), assess_vessel_log (dziennik NMEA statku jako przebieg wsadowy), trust_telemetry (strumień lub wynik zaufania jako tekst Prometheus, wiersze syslog CEF lub LEEF albo ładunek OTLP; nic nie jest wysyłane), evidence_verify (sprawdzenie podpisanego pakietu dowodowego; nic nie jest wysyłane; pakiety tworzy się przez CLI, Python lub MCP), bench_export (ruch i zdarzenia scenariusza jako tekst dla laboratoryjnego symulatora; nie jest zapisywany żaden sygnał), compliance_report i compliance_mapping (które wiersze wymagań publicznych ram dokumenty wyników wspierają dowodami (supports evidence for), z luką dla każdego wiersza; nie jest to stwierdzenie, że ramy zostały spełnione), interference_map (tekst CSV ADS-B lub AIS na GeoJSON kshana-interference-map/v1 na dobę UTC; tylko dane zagregowane), route_exposure (udział trasy w komórkach tych map o pogorszonej jakości; nie jest to prognoza), nmea_training (syntetyczny NMEA mostka i dziennik instruktora do szkolenia załóg; wyłącznie tekst, nigdy do żywych systemów nawigacyjnych statku) oraz funkcje geometrii nieba sky_geometry, sky_monte_carlo, skyline_presets, skyline_profile i skyplot_svg (które satelity widzi stanowisko, gdy budynki, nabrzeża lub teren zasłaniają część nieba, z rozmyciem dokładności, poziomą elipsą błędu, chmurą Monte Carlo z ziarnem i skyplotem jako tekstem SVG; decyzja o widoczności i elipsa są sprawdzone względem niezależnych bibliotek, zestawy są geometriami reprezentatywnymi, a nie pomiarami terenowymi, a horyzont usuwa satelity w linii widzenia i nic więcej). Nie ma ich w wersji przeglądarkowej: receiver-trust live z bramką i nasłuchem TCP, strumieniowany szkoleniowy NMEA oraz eksportery telemetrii (Prometheus, OpenTelemetry, syslog) to długo działające procesy sieciowe i pozostają w narzędziu wiersza poleceń; utworzenie pakietu dowodowego wymaga klucza podpisu, który należy do CLI lub Pythona. Nie ma tu jednowywołaniowego run_full; to powiązanie istnieje tylko w pakiecie wheel dla Pythona.
Każda możliwość w macierzy weryfikacji jest oznaczona jako sprawdzona (względem niezależnej wyroczni zewnętrznej), obliczona na podstawie modelu lub należąca do partnera; wartości zegarów optycznych to cele kosmiczne na sprzęcie naziemnym (żaden optyczny zegar strontowy nie poleciał w kosmos). Dojrzałość nie jest jednolita w różnych dziedzinach — PNT dla Ziemi jest sprawdzone względem prawdziwych danych; nawigacja w przestrzeni kosmicznej i na Marsie jest obliczona na podstawie modelu, a względem zewnętrznych wyroczni sprawdzone są tylko jej elementy składowe (czas przelotu światła, położenia planet); OD (wyznaczanie orbity) dla prawdziwych misji w przestrzeni kosmicznej jest w planach.
Możliwości#
Silnik ma 92 rodzajów scenariuszy; kshana kinds wymienia je wraz z ich polami. Nowe w 0.38.0: gnss-ssv (sygnały GNSS dla statków kosmicznych powyżej orbit GNSS, wokół nich i poza nimi) oraz lunar-infrastructure (orbita i powierzchnia Księżyca jako infrastruktura nawigacyjna i geodezyjna), oba MODELLED, a także holdover-test (zapis błędu czasu względem masek ITU-T).
- Widmo: jak zagłuszacz zajmuje pasmo L GNSS, pasmo po paśmie.
- Zegary i synchronizacja czasu: holdover względem progu, transfer czasu oraz holdover telekomunikacyjny względem masek sektora normalizacji Międzynarodowego Związku Telekomunikacyjnego (ITU-T).
- Konstelacje wokół dowolnego ciała: pokrycie, rozmycie dokładności i dostępność wokół Ziemi, Księżyca lub Marsa oraz Układ Słoneczny w jednej epoce.
- Nawigacja z niskiej orbity okołoziemskiej: sygnał, przelot i łącze, komunikat nawigacyjny oraz fuzja pozycji, etap po etapie.
- Kampanie: połączona misja, przegląd parametru lub zespół Monte Carlo w jednym scenariuszu.
- Raporty, animacja i eksporty: każda wartość z jednostką i etykietą; animowany rysunek przebiegu; pliki SP3 (Standard Product 3), komunikaty orbitalne CCSDS (Consultative Committee for Space Data Systems), CZML (Cesium Language), KML (Keyhole Markup Language), GeoJSON, STK (Systems Tool Kit) i SigMF (Signal Metadata Format).
Architektura#
Ten sam plik scenariusza daje te same bajty na każdej powierzchni. MCP to Model Context Protocol: kshana-mcp pozwala asystentowi AI (sztucznej inteligencji) uruchamiać silnik.
Badania#
Sześć prac na arXiv opiera się na otwartym silniku, każda z poleceniem, które za nią stoi: arXiv:2606,22054 (luka optymizmu detektorów zakłóceń), arXiv:2606,24210 (warunkowy poziom ochrony czasu), arXiv:2607,05415 (jak stabilny jest wskaźnik odporności PNT), arXiv:2607,02566 (obserwowalność stanowisk na powierzchni Księżyca w interferometrii o bardzo długiej bazie), arXiv:2607,06212 (geometria okołobiegunowa południowego bieguna Księżyca i latarnie na powierzchni) oraz arXiv:2610,23871 (nawigacja cislunarna jako problem obserwowalności: długość łuku, uwarunkowanie gramianu i dźwignia Dopplera). Zob. Badania.
Wydania#
Cały silnik jest darmowy na licencji AGPL-3.0. Kshana Pro, zastrzeżona nakładka, która zależy od otwartego silnika i nigdy go nie rozwidla, oraz studia na zamówienie są dostępne na podstawie umowy od Ashforde® OÜ: contact@ashforde.org. Nie ma cen; zob. docs/PRO.md.
Dowiedz się więcej#
- Pełny README → https://github.com/AshfordeOU/kshana
- Kshana Studio (silnik w przeglądarce, jako WebAssembly) → https://kshana.dev
- Możliwości → docs/CAPABILITY.md
- Walidacja i pochodzenie → docs/VALIDATION.md · docs/PROVENANCE.md
- Macierz weryfikacji → docs/VERIFICATION-MATRIX.md
- Cytowanie → CITATION.cff · DOI 10.5281/zenodo.20528627
Licencja#
Wolne i otwarte oprogramowanie na licencji GNU AGPL-3.0-only (GNU Affero General Public License, wyłącznie wersja 3). Licencja komercyjna jest dostępna od Ashforde® OÜ (estońskiej spółki z ograniczoną odpowiedzialnością; OÜ = osaühing) dla zamkniętej integracji; zob. LICENSING.md. Profesjonalnie rozwijane i utrzymywane przez Ashforde® OÜ.