kshana 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +145 -43
- package/kshana.d.ts +28 -0
- package/kshana.js +81 -0
- package/kshana_bg.wasm +0 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
8
|
<strong>क्षण</strong> — Sanskrit for <em>the precise instant</em>, the smallest measure of time.<br>
|
|
9
|
-
Open, reproducible
|
|
9
|
+
Open, reproducible PNT-resilience simulation with published quantum-sensor performance models.
|
|
10
10
|
</p>
|
|
11
11
|
|
|
12
12
|
<p align="center">
|
|
@@ -16,34 +16,47 @@
|
|
|
16
16
|
<a href="https://github.com/ashfordeOU/kshana/releases"><img src="https://img.shields.io/github/v/release/ashfordeOU/kshana?sort=semver" alt="Release"></a>
|
|
17
17
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-Apache_2.0-blue.svg" alt="License: Apache-2.0"></a>
|
|
18
18
|
<a href="Cargo.toml"><img src="https://img.shields.io/badge/rust-1.75%2B-orange.svg" alt="Rust 1.75+"></a>
|
|
19
|
-
<a href="https://doi.org/10.5281/zenodo.20528627"><img src="https://
|
|
19
|
+
<a href="https://doi.org/10.5281/zenodo.20528627"><img src="https://img.shields.io/badge/DOI-10.5281%2Fzenodo.20528627-blue.svg" alt="DOI 10.5281/zenodo.20528627"></a>
|
|
20
20
|
</p>
|
|
21
21
|
|
|
22
22
|
<p align="center">
|
|
23
23
|
<strong>Kshana</strong> (क्षण, Sanskrit: <em>"the precise instant"</em>) is an open, reproducible
|
|
24
24
|
<strong>PNT-resilience simulator with quantum-sensor performance models</strong> —
|
|
25
|
-
positioning, navigation, and timing. It compares quantum and classical sensors
|
|
26
|
-
published Allan/noise-budget coefficients
|
|
27
|
-
|
|
25
|
+
positioning, navigation, and timing. It compares quantum and classical sensors mostly
|
|
26
|
+
from published Allan/noise-budget coefficients, with a first-principles cold-atom-
|
|
27
|
+
interferometer accelerometer layer (Mach–Zehnder phase, quantum projection noise,
|
|
28
|
+
contrast decay, and vibration coupling) that <em>derives</em> the noise coefficient
|
|
29
|
+
rather than looking it up; it is not yet a full quantum-physics simulator (Coriolis and
|
|
30
|
+
light-shift systematics remain coefficient-level — see
|
|
31
|
+
<a href="docs/QUANTUM.md">docs/QUANTUM.md</a> and
|
|
32
|
+
<a href="docs/QUANTUM-MODELS.md">docs/QUANTUM-MODELS.md</a>).
|
|
28
33
|
</p>
|
|
29
34
|
|
|
30
35
|
It quantifies, in hard and reproducible numbers, what quantum clocks, quantum
|
|
31
36
|
inertial sensors, and optical time-transfer buy a navigation system over classical
|
|
32
37
|
PNT — scored against the operational figures of merit that matter for resilient
|
|
33
38
|
navigation. Every result is reproducible from `scenario + seed + engine version`,
|
|
34
|
-
and every sensor parameter is traceable to a published source
|
|
39
|
+
and every sensor parameter is traceable to a published source — consolidated in one
|
|
40
|
+
citable table in [`docs/PROVENANCE.md`](docs/PROVENANCE.md).
|
|
35
41
|
|
|
36
42
|
*Free and open source under Apache-2.0, professionally developed and maintained by
|
|
37
43
|
Ashforde OÜ — commercial support, integration, and proprietary extensions available.*
|
|
38
44
|
|
|
39
|
-
> **Status: v0.
|
|
40
|
-
> fully reproducible engine spanning the PNT stack — orbit geometry
|
|
41
|
-
>
|
|
42
|
-
>
|
|
43
|
-
>
|
|
45
|
+
> **Status: v0.12.0 · a simulation substrate, not yet a product.** A validated,
|
|
46
|
+
> fully reproducible engine spanning the PNT stack — orbit geometry and constellation
|
|
47
|
+
> design, a numerical (Cowell) propagator with a six-perturbation force model, maneuver
|
|
48
|
+
> and trajectory design, time systems, inertial navigation (incl. map-aided and
|
|
49
|
+
> gravity-map-matching alt-PNT), GNSS/INS fusion (loose, tight, UKF, coupled
|
|
50
|
+
> clock+position, 17-state), orbit determination, ARAIM integrity, clocks, advanced
|
|
51
|
+
> time-and-frequency transfer, the GNSS measurement domain, and resilience (jamming +
|
|
52
|
+
> multi-layer spoofing).
|
|
53
|
+
> Honest by design: every figure of merit is labelled *validated* or *not-modeled*, and
|
|
54
|
+
> optical-clock figures are space goals on ground hardware (no strontium optical clock has flown).
|
|
44
55
|
> See **[Capabilities](#capabilities)** for what it does, **[What it is / is not](#what-it-is--is-not)**
|
|
45
56
|
> for scope, and [`docs/CAPABILITY.md`](docs/CAPABILITY.md) / [`docs/VALIDATION.md`](docs/VALIDATION.md)
|
|
46
|
-
> for per-capability maturity
|
|
57
|
+
> for per-capability maturity. The overclaim closure ledger
|
|
58
|
+
> [`docs/CLAIMS-VS-REALITY.md`](docs/CLAIMS-VS-REALITY.md) tracks every historical overclaim,
|
|
59
|
+
> how it was resolved, and a CI guard (`tests/no_overclaims.rs`) that keeps it resolved.
|
|
47
60
|
|
|
48
61
|
> **Try it in your browser:** the [playground](web/) runs the engine client-side as
|
|
49
62
|
> WebAssembly — pick a scenario, edit the parameters, and see the result, with nothing
|
|
@@ -97,17 +110,34 @@ receiver, or a certified avionics product. Quantum-hardware fidelity comes from
|
|
|
97
110
|
published error models, not from this tool. The granular maturity of each
|
|
98
111
|
capability is documented in [`docs/CAPABILITY.md`](docs/CAPABILITY.md).
|
|
99
112
|
|
|
113
|
+
**It is not (yet):** a *full* atom-interferometry physics engine (most quantum sensors
|
|
114
|
+
consume published Allan/noise-budget coefficients; the CAI accelerometer has a
|
|
115
|
+
first-principles layer — Mach–Zehnder phase, projection noise, contrast decay, and
|
|
116
|
+
vibration coupling — but Coriolis and light-shift systematics remain a **P2** roadmap
|
|
117
|
+
layer, see [`ROADMAP.md`](ROADMAP.md) and [`docs/QUANTUM-MODELS.md`](docs/QUANTUM-MODELS.md));
|
|
118
|
+
a GNSS receiver or PVT solver (it models the measurement domain and resilience, not
|
|
119
|
+
signal acquisition or a least-squares fix); or a mission-design / orbit-determination
|
|
120
|
+
tool. Owning this scope is deliberate. If you need first-principles cold-atom
|
|
121
|
+
interferometer error budgets (e.g. CARIOQA-PMP-grade or X-37B-style validation), see
|
|
122
|
+
the P2 roadmap and [get in touch](#support--professional-services) to collaborate.
|
|
123
|
+
|
|
100
124
|
## Capabilities
|
|
101
125
|
|
|
102
126
|
| Domain | Capability |
|
|
103
127
|
|--------|------------|
|
|
104
|
-
| **Orbit & geometry** | SGP4/SDP4 propagation (validated to 4.12 mm against all 666 AIAA 2006-6753 vectors)
|
|
105
|
-
| **
|
|
106
|
-
| **
|
|
107
|
-
| **
|
|
108
|
-
| **
|
|
109
|
-
| **
|
|
110
|
-
| **
|
|
128
|
+
| **Orbit & geometry** | SGP4/SDP4 propagation (validated to 4.12 mm against all 666 AIAA 2006-6753 vectors); real two-line elements (a committed, date-stamped Celestrak `gps-ops` snapshot) or synthetic Walker-delta constellations whose mean elements realise the `i:T/P/F` formula to under 1 km over a 24 h propagation; multi-constellation visibility, dilution of precision, and GNSS availability; a gradient-free constellation-design optimiser, streets-of-coverage minimum-satellite sizing, a multi-constellation comparison tool, and a Walker **design sweep** that tabulates coverage / PDOP / revisit-time over a planes × satellites grid and reports the Pareto-optimal designs. |
|
|
129
|
+
| **Numerical propagator** | A **Cowell** numerical propagator (`src/propagator.rs`) complementing the analytic SGP4/SDP4 path, with a hierarchical **six-perturbation** force model (`src/forces.rs`): two-body + the full **J2–J6 zonal** field (the exact analytic gradient of its disturbing potential), **epoch-driven Sun and Moon third-body** gravity (a built-in low-precision ephemeris, no DE/SPK kernel), **solar-radiation pressure** (cannonball model with a conical umbra+penumbra shadow), **atmospheric drag** (Vallado piecewise-exponential density, co-rotating atmosphere), and the **post-Newtonian Schwarzschild relativistic correction** — driven by a choice of two adaptive integrators (RK4 step-doubling or the **Dormand–Prince RK5(4)** embedded pair). Validated against analytic truth stronger than a cross-tool would give: the unperturbed orbit matches the exact universal-variable Kepler solution to **sub-metre over 24 h**, energy/angular-momentum conserve to ~1e-9, and each perturbation matches a hand-derived closed-form signature. |
|
|
130
|
+
| **Maneuvers & trajectory design** | Impulsive ΔV nodes with 6×6 covariance propagation (ECI / LVLH execution-error frames), finite-burn integration checked against the closed-form **Tsiolkovsky** rocket equation to < 0.01 %, an **Izzo-2015** single-revolution **Lambert** solver, an exact universal-variable **Kepler** propagator, and a **porkchop** (launch × arrival) C3 / arrival-V∞ sweep emitted as a JSON contour grid — the performance-simulation layer above GMAT/Orekit, with every Lambert output round-tripped against two-body truth and the porkchop minimum checked against the analytic Hohmann floor. |
|
|
131
|
+
| **Time systems** | IERS leap-second **UTC / TAI / TT / UT1** scales, a Julian-date API, the IAU-2000 **Earth Rotation Angle**, and GMST-based **TEME ↔ ECEF** with WGS-84 geodetic frames — plus IAU 2006 precession (Fukushima–Williams) toward an ITRF-precise reduction. |
|
|
132
|
+
| **Inertial** | Three-axis strapdown INS — quaternion attitude, WGS-84 NED mechanization, coning/sculling compensation, and a deterministic IMU error model (scale-factor, misalignment, g-sensitivity, quantization, drift); a **first-principles cold-atom-interferometer accelerometer** (Mach–Zehnder phase, quantum projection noise, contrast decay, vibration coupling) that *derives* the velocity-random-walk coefficient; and a sequential-importance-resampling **particle filter** for map-aided (terrain-/gravity-referenced) GPS-denied navigation. |
|
|
133
|
+
| **Gravity-map / alt-PNT** | A cold-atom **gravimeter measurement model** whose white-noise floor (`σ = ASD/√τ`) is derived from the CAI accelerometer physics; a low-degree, fully-normalised **spherical-harmonic gravity-anomaly field** (validated against the closed-form Legendre functions and a hand-derived single-term anomaly) plus synthetic mascons; and a **gravity-map-matching particle filter** that recovers a GPS-denied track from the anomaly sequence it flies through. A **60-minute GPS-denied benchmark** (a ~700 km / one-hour outage where the inertial solution drifts to ~70 km) is recovered to **~145 m (< 500 m)** by a hierarchical coarse-to-fine matcher — the ESA NAVISP *Quantum Wayfarer* target. |
|
|
134
|
+
| **Fusion** | Loosely-coupled 15-state GNSS/INS error-state EKF with closed-loop feedback (the `gnss-ins` pack); a **tightly-coupled** pseudorange update that keeps correcting with fewer than four satellites; a coupled **clock + position** filter; a general **unscented (sigma-point) Kalman** estimator for strongly nonlinear measurements; a tightly-coupled GNSS/INS **UKF navigator** (pseudorange + Doppler) whose force-model orbital coast is validated to **0.77 m RMS** over a 30-minute curving LEO pass that includes a 120-second GNSS outage; and a full **17-state tightly-coupled GNSS/INS UKF** (position, velocity, attitude error, accelerometer and gyro biases, clock bias and drift) whose **quantum-CAI dead-reckoning** coasts a 120-second outage on the cold-atom accelerometer's derived velocity-random-walk. |
|
|
135
|
+
| **Orbit determination** | Recovery of an orbital state `[r, v]` from ground-station range tracking, composing the two-body + J2 force model and RK4 integrator with a **Gauss–Newton batch** corrector (`determine_orbit_batch`, sub-metre / mm·s⁻¹ from noiseless ranges, ~2 m at a 5 m noise floor) and a **sequential** unscented-filter variant (`determine_orbit_sequential`). |
|
|
136
|
+
| **Integrity** | Snapshot and solution-separation (ARAIM-style) RAIM with horizontal/vertical protection levels (HPL/VPL), fault detection & exclusion, and Stanford integrity diagrams; an explicit integrity-risk-budget (**MHSS**) protection level, including the **dual-/multi-constellation constellation-wide fault mode** (EU ARAIM / DO-316). |
|
|
137
|
+
| **Clock & timing** | Two-state Kalman holdover (Joseph-form covariance, NIS/NEES consistency health); Allan-family stability (ADEV / MDEV / TDEV / HDEV) with noise-type-specific confidence intervals and a full **IEEE-1139 five-coefficient power-law fit**; geometric corrections (Sagnac, GNSS common-view); and the operational transfer methods — **TWSTFT** with the BIPM Sagnac closed form, **GNSS common-view**, **PPP** ionosphere-free time transfer, a free-space **optical** link with turbulence scintillation, and an inverse-variance **clock-ensemble (paper) timescale** below the best contributing clock. |
|
|
138
|
+
| **GNSS measurement domain** | Forward pseudorange / Doppler synthesis with **Klobuchar** (broadcast) and **IONEX / TEC-grid** (measured) ionosphere — including an IONEX file parser, time interpolation between maps, and the thin-shell slant-obliquity mapping — **Saastamoinen + Niell** troposphere, and snapshot RAIM (HPL/VPL). |
|
|
139
|
+
| **Resilience** | Link-budget **jamming** (J/S → effective C/N₀ → loss of lock); a stochastic **time-spoof detector** (Neyman–Pearson / χ²₁ energy test with closed-form and Monte-Carlo P_fa/P_md and a Security FoM of 1 − P_md); and a **multi-layer spoof detector** fusing a RAIM-consistency parity test (with the common-mode blind spot modelled honestly), an RF AGC-power monitor, and a signal-quality (SQM early-minus-late) monitor. |
|
|
140
|
+
| **Interoperability** | **RINEX-3** multi-GNSS broadcast-ephemeris ingestion (GPS, Galileo, QZSS, BeiDou MEO/IGSO via IS-GPS-200; GLONASS via PZ-90 state-vector RK4) usable as a constellation source (RINEX in, PNT geometry out); a **RINEX-3/4** observation parser (pseudorange, carrier phase, Doppler, signal strength); an **SP3-c/d** precise-ephemeris reader/writer with 9th-order Lagrange interpolation; and **CCSDS OEM 2.0 + OMM** (mean-elements) export for flight-dynamics tools (GMAT, Orekit, STK). |
|
|
111
141
|
|
|
112
142
|
Each capability is reachable as a Rust API, a runnable scenario `kind`, or both.
|
|
113
143
|
Maturity per capability — *validated*, *runnable*, or *library* — is tracked in
|
|
@@ -148,7 +178,12 @@ The constellation can also be given as real two-line element sets. A *full* TLE
|
|
|
148
178
|
(line 1 + line 2) is propagated with the full **SGP4/SDP4** model — including
|
|
149
179
|
atmospheric drag and the deep-space lunar-solar and 12 h / 24 h resonance terms that
|
|
150
180
|
matter for ~12 h GNSS orbits — validated against the official AIAA 2006-6753 vectors
|
|
151
|
-
to a worst-case ≈ 4 mm
|
|
181
|
+
to a worst-case ≈ 4 mm. `scenarios/orbit-sgp4-gps.toml` ships a **real Celestrak
|
|
182
|
+
`gps-ops` snapshot** of the operational GPS constellation (2021-07-28, 30 satellites)
|
|
183
|
+
and requires valid TLE checksums — two-line element sets are open data from the US
|
|
184
|
+
Space Force / 18th Space Defense Squadron catalogue, redistributed by Celestrak
|
|
185
|
+
(Dr T. S. Kelso, [celestrak.org](https://celestrak.org)); refresh with
|
|
186
|
+
`scripts/fetch_tles.sh`. A line-2-only block keeps
|
|
152
187
|
the analytic two-body propagation (`scenarios/orbit-real-tle.toml`); the two forms can
|
|
153
188
|
be mixed in one constellation. A constellation can equally be built from a block of
|
|
154
189
|
**RINEX-3 GPS broadcast-ephemeris** records — the format a receiver decodes —
|
|
@@ -180,8 +215,19 @@ cargo run -- scenarios/orbit-gnss-challenged.toml
|
|
|
180
215
|
cargo run -- scenarios/orbit-sgp4-gps.toml
|
|
181
216
|
cargo run -- scenarios/orbit-rinex.toml
|
|
182
217
|
cargo run -- scenarios/integrity-raim.toml
|
|
218
|
+
|
|
219
|
+
# Export a propagated constellation to an SP3-c precise-ephemeris file:
|
|
220
|
+
cargo run -- scenarios/orbit-sgp4-gps.toml --export-sp3 gps.sp3
|
|
183
221
|
```
|
|
184
222
|
|
|
223
|
+
**Interoperability role.** Kshana is the *performance-simulation* layer that sits
|
|
224
|
+
alongside the post-processing toolchain, not a replacement for it: feed its **RINEX**
|
|
225
|
+
output into RTKLIB or gLAB for a position solution, and use its **SP3** output as a
|
|
226
|
+
precise-orbit product for tools like Ginan — Kshana answers *what resilience a given
|
|
227
|
+
PNT architecture buys* before you have real signals, in formats those tools already
|
|
228
|
+
ingest (`--export-sp3`, or `export_sp3 = true` in an `orbit` scenario, writes
|
|
229
|
+
`<scenario>.sp3`).
|
|
230
|
+
|
|
185
231
|
Example output (clock holdover — note the Integrity and Security figures of merit):
|
|
186
232
|
|
|
187
233
|
```
|
|
@@ -250,8 +296,9 @@ console.log(version(), result.classical.fom.timing_p95_ns);
|
|
|
250
296
|
|
|
251
297
|
## Scenario format
|
|
252
298
|
|
|
253
|
-
Scenarios are declarative TOML. A top-level `kind` selects the pack
|
|
254
|
-
|
|
299
|
+
Scenarios are declarative TOML. A top-level `kind` selects the pack (`clock` is
|
|
300
|
+
the default if omitted; `inertial`, `timetransfer`, `hybrid`, `fusion`,
|
|
301
|
+
`gnss-ins`, `orbit`, `gnss-sim`, `integrity`, `spoof`, `jamming`, `sweep`, `sweep-nd`).
|
|
255
302
|
Common fields: `seed`, a `[time]` grid, a `[gnss]` availability timeline (the outage
|
|
256
303
|
driver), and per-sensor blocks with `provenance` strings citing the source of every
|
|
257
304
|
figure. Example (clock):
|
|
@@ -294,9 +341,13 @@ quaternion attitude with coning/sculling compensation, a full NED mechanization
|
|
|
294
341
|
(Earth-rate and transport-rate terms, WGS-84 Somigliana gravity), and a
|
|
295
342
|
deterministic IMU error model in which **scale-factor, misalignment,
|
|
296
343
|
g-sensitivity, quantization, and rate-ramp are modelled** (IEEE Std 952-1997
|
|
297
|
-
§A.2; Groves 2013 §4.3). That 3-axis path is **
|
|
298
|
-
pack
|
|
299
|
-
the
|
|
344
|
+
§A.2; Groves 2013 §4.3). That 3-axis path is now **wired into a runnable
|
|
345
|
+
loosely-coupled GNSS/INS pack** (`kind = "gnss-ins"`): a 15-state error-state EKF
|
|
346
|
+
disciplines the strapdown solution against noisy fixes while GNSS is up, then
|
|
347
|
+
coasts through the outage, reporting the fused horizontal error against the
|
|
348
|
+
open-loop free-INS coast. A **tightly-coupled pseudorange** update is also
|
|
349
|
+
available (it forms the innovation in the range domain, so it keeps correcting
|
|
350
|
+
with fewer than four satellites). A
|
|
300
351
|
clock-holdover scenario may add `runs` (> 1) to run a **Monte Carlo ensemble** — each
|
|
301
352
|
figure of merit is then reported as a mean with a 5th–95th-percentile spread and the
|
|
302
353
|
chart shades the error confidence band (see `scenarios/clock-ensemble.toml`).
|
|
@@ -308,10 +359,39 @@ cross-covariance: this is a stacked pair of error budgets, **not** a true couple
|
|
|
308
359
|
clock+position joint filter (cross-block covariance is a roadmap item). See
|
|
309
360
|
`scenarios/fusion-pnt.toml`.
|
|
310
361
|
|
|
311
|
-
A `spoof` scenario injects a
|
|
312
|
-
`
|
|
313
|
-
|
|
314
|
-
|
|
362
|
+
A `spoof` scenario injects a time-spoof — one of four `[attack.shape]` kinds
|
|
363
|
+
(`linear_ramp`, `step_jump`, `meaconing`, `replay`; a bare `rate_ns_per_s` is still
|
|
364
|
+
accepted as a linear ramp) — and runs each clock's spoof detector. The detector is a
|
|
365
|
+
two-sided **χ²₁ energy / Neyman–Pearson test** on the clock-aided monitor statistic:
|
|
366
|
+
the threshold is set from a target false-alarm budget `target_pfa`, and the
|
|
367
|
+
**missed-detection probability `P_md`** is reported both closed-form and by
|
|
368
|
+
Monte-Carlo (`mc_runs` trials per hypothesis — the two agree to a few ×1/√N). The
|
|
369
|
+
**Security figure of merit is `1 − P_md`** at the operationally-harmful (spec)
|
|
370
|
+
magnitude, so a quiet clock that catches a spec-sized spoof scores ≈ 1 and a noisy
|
|
371
|
+
one that often misses it scores lower (see `scenarios/spoof-attack.toml`,
|
|
372
|
+
`scenarios/spoof-meaconing.toml`).
|
|
373
|
+
|
|
374
|
+
A `gnss-sim` scenario is a **measurement-domain** simulation: for each visible
|
|
375
|
+
satellite it synthesises the pseudorange `ρ = geometric range + c·δt_rx − c·δt_sv +
|
|
376
|
+
I + T + noise + multipath` and the L1 Doppler, with the **Klobuchar** single-frequency
|
|
377
|
+
ionosphere (`[iono]`, IS-GPS-200 §20.3.3.5.2.5) and the **Saastamoinen** zenith
|
|
378
|
+
troposphere projected by the **Niell (1996)** mapping function (`[tropo]`). The
|
|
379
|
+
residuals feed **snapshot RAIM** for per-epoch HPL/VPL, and every satellite's
|
|
380
|
+
pseudorange, Doppler, C/N₀, and iono/tropo corrections are emitted in the JSON
|
|
381
|
+
`gnss_measurements` array. It is a forward simulator (it generates measurements from
|
|
382
|
+
a known truth), not a receiver/solver — a zero-noise run reproduces geometry plus the
|
|
383
|
+
corrections to sub-millimetre (see `scenarios/gnss-sim-raim.toml`).
|
|
384
|
+
|
|
385
|
+
A `jamming` scenario models RF interference as a **link budget**: a `[jammer]`
|
|
386
|
+
(ECEF position, transmit `power_dbw`, type) raises the jammer-to-signal ratio at a
|
|
387
|
+
`[receiver]` watching a Walker `[constellation]`. From the geometry (free-space
|
|
388
|
+
path loss and the per-direction receive-antenna gain) it computes each satellite's
|
|
389
|
+
`J/S`, the **effective C/N₀** via the standard anti-jam equation (despreading
|
|
390
|
+
processing gain × the spectral-separation factor `Q`; Kaplan & Hegarty §9.4), and
|
|
391
|
+
flags loss of lock below a configurable tracking threshold — reporting an
|
|
392
|
+
`availability_under_jamming` figure of merit. A 10 W broadband jammer at 1 km
|
|
393
|
+
denies the receiver entirely (J/S ≈ 72 dB); the same jammer at 100 km only
|
|
394
|
+
degrades the links (see `scenarios/jamming-demo.toml`).
|
|
315
395
|
|
|
316
396
|
A `sweep` scenario runs a **trade study**: it varies one `parameter` (`threshold_ns`,
|
|
317
397
|
`duration_s`, `quantum_q_wf`, or `classical_q_wf`) from `start` to `stop` over `steps`
|
|
@@ -319,6 +399,14 @@ points on a `lin` or `log` `scale`, records a `metric` (e.g. `holdover_s`) for b
|
|
|
319
399
|
clocks, and charts the two curves. The base scenario goes under `[base]` (see
|
|
320
400
|
`scenarios/sweep-clock-stability.toml`).
|
|
321
401
|
|
|
402
|
+
A `sweep-nd` scenario generalises this to **any pack and any number of axes**: it
|
|
403
|
+
varies dotted TOML keys of a `[base]` scenario (of any `kind`) over the Cartesian
|
|
404
|
+
product of `[[axes]]`, re-runs each grid node, and records `metrics` given as
|
|
405
|
+
dotted JSON paths into the result (e.g. `classical.fom.holdover_s`). It works for
|
|
406
|
+
every pack because it operates at the TOML/result boundary; native runs evaluate
|
|
407
|
+
the grid in parallel (no extra dependency, wasm falls back to sequential) and the
|
|
408
|
+
output is deterministic and row-major (see `scenarios/sweep-nd-inertial.toml`).
|
|
409
|
+
|
|
322
410
|
An `orbit` scenario derives the `[gnss]` timeline from geometry instead of authoring
|
|
323
411
|
it — give a `[user]` orbit, a `[constellation]`, an elevation `mask_deg`, and the two
|
|
324
412
|
clock blocks. It also reports position accuracy from the satellite geometry; the
|
|
@@ -360,10 +448,13 @@ See `scenarios/` for one example of every kind.
|
|
|
360
448
|
The result artifact is versioned, self-describing JSON: per-step time series, the
|
|
361
449
|
scored figures of merit, the active model specs (with provenance), the seed, a
|
|
362
450
|
**scenario hash** — so any chart can be reproduced from the file — and, for each clock,
|
|
363
|
-
an `adev_curve` (`[{tau_s, adev, n_samples}]`): the overlapping
|
|
364
|
-
octave-spaced averaging times
|
|
365
|
-
|
|
366
|
-
|
|
451
|
+
an `adev_curve` (`[{tau_s, adev, n_samples, noise, edf, ci_lo, ci_hi}]`): the overlapping
|
|
452
|
+
Allan deviation across octave-spaced averaging times — the standard way to read a clock's
|
|
453
|
+
stability — now with a **noise-type-specific 95% confidence band** per point (the record's
|
|
454
|
+
power-law type is identified from its modified-Allan slope, and the χ² interval uses the
|
|
455
|
+
matching NIST SP 1065 effective degrees of freedom). The browser playground renders it as a
|
|
456
|
+
log-log "Clock stability (ADEV)" chart. (MDEV, TDEV, and HDEV are available as library
|
|
457
|
+
estimators; the exported result curve is the overlapping ADEV.) Every field, with units and a
|
|
367
458
|
source pointer, is documented in [`docs/SCHEMA.md`](docs/SCHEMA.md). The figures of
|
|
368
459
|
merit follow the standard operational PNT figures of merit:
|
|
369
460
|
|
|
@@ -467,6 +558,7 @@ kshana/
|
|
|
467
558
|
| [Glossary](docs/GLOSSARY.md) | everyone | plain-language definitions of every term |
|
|
468
559
|
| [Architecture](docs/ARCHITECTURE.md) | developers / reviewers | module map, engine pipeline, dispatch, and diagrams |
|
|
469
560
|
| [Validation status](docs/VALIDATION.md) | reviewers / citers | what is `validated` vs `not modeled`, with evidence |
|
|
561
|
+
| [Provenance](docs/PROVENANCE.md) | reviewers / citers | every sensor parameter, model, and dataset traced to its published source, in one citable table |
|
|
470
562
|
| [Reproducibility & provenance](docs/REPRODUCIBILITY.md) | reviewers / packagers | determinism guarantees, golden-pinning, SBOM, build provenance |
|
|
471
563
|
| [Positioning](docs/POSITIONING.md) | evaluators | where Kshana sits vs RTKLIB/gLAB (complementary), and the zero-install browser tier |
|
|
472
564
|
| [SGP4 validation](docs/SGP4-VALIDATION.md) | reviewers / citers | agreement with the AIAA 2006-6753 reference (666 states, ~4 mm) |
|
|
@@ -542,15 +634,25 @@ CPython versions).
|
|
|
542
634
|
|
|
543
635
|
## Roadmap
|
|
544
636
|
|
|
545
|
-
See [`
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
637
|
+
See [`ROADMAP.md`](ROADMAP.md) for the phased roadmap, [`CHANGELOG.md`](CHANGELOG.md)
|
|
638
|
+
for released history, and [`docs/CAPABILITY.md`](docs/CAPABILITY.md) for the
|
|
639
|
+
per-capability roadmap. Near-term items include **ITRF-precise frame reduction**
|
|
640
|
+
(polar motion and sub-arcsecond nutation on top of the shipped GMST-based
|
|
641
|
+
TEME↔ECEF), two-part Julian dates, tightly-coupled carrier-phase fusion, and
|
|
642
|
+
surfacing the loosely-/tightly-coupled GNSS/INS navigator across more packs. The
|
|
643
|
+
**quantum physics layer** is a **P2** item: the CAI accelerometer is now simulated from
|
|
644
|
+
first principles (Mach–Zehnder phase, projection noise, contrast decay, vibration
|
|
645
|
+
coupling), while the clock/time-transfer sensors are still driven by published
|
|
646
|
+
Allan/noise-budget coefficients. GMST-based TEME↔ECEF, the IERS
|
|
647
|
+
leap-second time systems (UTC/TAI/TT/UT1), SGP4/SDP4 orbit propagation (v0.7.0,
|
|
648
|
+
validated against the AIAA 2006-6753 vectors), and the runnable `gnss-ins` fusion
|
|
649
|
+
pack have all **shipped**, and the inertial velocity is exposed downstream. An active
|
|
650
|
+
stochastic time-spoof detector (Neyman–Pearson / χ²₁ energy test with Monte-Carlo
|
|
651
|
+
P_fa/P_md and a Security FoM of 1−P_md), a link-budget jamming model (J/S → effective
|
|
652
|
+
C/N₀ → loss of lock), multi-constellation availability, a single-axis (1-DOF)
|
|
551
653
|
IMU error budget, two independent (clock + position) Kalman estimators reported as a
|
|
552
|
-
combined FoM, real constellation geometry from TLEs, an HTML scorecard report,
|
|
553
|
-
|
|
654
|
+
combined FoM, real constellation geometry from TLEs, an HTML scorecard report,
|
|
655
|
+
geometry-derived GNSS availability
|
|
554
656
|
*and* dilution of precision from Keplerian orbits with eccentricity and J2 drift,
|
|
555
657
|
Monte Carlo confidence bands, trade-study parameter sweeps, an in-browser WebAssembly
|
|
556
658
|
playground, and optional Python (PyO3) and WebAssembly (wasm-bindgen) bindings have
|
|
@@ -568,12 +670,12 @@ entry for every user-visible change. Participation is governed by our
|
|
|
568
670
|
|
|
569
671
|
If you use Kshana in academic or technical work, please cite it. Machine-readable
|
|
570
672
|
metadata is in [`CITATION.cff`](CITATION.cff) (GitHub renders a "Cite this repository"
|
|
571
|
-
button from it); cite the version you used (e.g. `v0.
|
|
673
|
+
button from it); cite the version you used (e.g. `v0.12.0`) together with the
|
|
572
674
|
scenario and seed for full reproducibility. Every release is archived on Zenodo with
|
|
573
675
|
a citable DOI — the concept DOI [10.5281/zenodo.20528627](https://doi.org/10.5281/zenodo.20528627)
|
|
574
676
|
always resolves to the latest version.
|
|
575
677
|
|
|
576
|
-
> Baweja, C. (2026). *Kshana —
|
|
678
|
+
> Baweja, C. (2026). *Kshana — a PNT-resilience simulator with quantum-sensor performance models*. Ashforde OÜ. https://doi.org/10.5281/zenodo.20528627
|
|
577
679
|
|
|
578
680
|
## Versioning & releases
|
|
579
681
|
|
package/kshana.d.ts
CHANGED
|
@@ -6,6 +6,30 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export function chart_svg(toml: string): string;
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Decode a permalink token back into the scenario TOML; returns an empty string if the
|
|
11
|
+
* token is not valid Base64 or not valid UTF-8.
|
|
12
|
+
*/
|
|
13
|
+
export function decode_permalink(token: string): string;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Encode a scenario TOML into a URL-safe permalink token for a `?s=` query parameter.
|
|
17
|
+
*/
|
|
18
|
+
export function encode_permalink(toml: string): string;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Run a scenario; on failure return the structured error *kind* tag
|
|
22
|
+
* (`invalid_input`, `unsupported`, …) so the caller can branch on the failure
|
|
23
|
+
* category rather than parse the message. Returns an empty string on success.
|
|
24
|
+
*/
|
|
25
|
+
export function error_kind(toml: string): string;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* List the available scenario kinds and their metadata as a JSON array (name,
|
|
29
|
+
* description, required and optional fields), for programmatic introspection.
|
|
30
|
+
*/
|
|
31
|
+
export function list_kinds(): string;
|
|
32
|
+
|
|
9
33
|
/**
|
|
10
34
|
* Run a scenario given as a TOML string; returns the result document as a JSON
|
|
11
35
|
* string. Throws a JS error if the scenario is invalid.
|
|
@@ -27,6 +51,10 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl
|
|
|
27
51
|
export interface InitOutput {
|
|
28
52
|
readonly memory: WebAssembly.Memory;
|
|
29
53
|
readonly chart_svg: (a: number, b: number) => [number, number, number, number];
|
|
54
|
+
readonly decode_permalink: (a: number, b: number) => [number, number];
|
|
55
|
+
readonly encode_permalink: (a: number, b: number) => [number, number];
|
|
56
|
+
readonly error_kind: (a: number, b: number) => [number, number];
|
|
57
|
+
readonly list_kinds: () => [number, number];
|
|
30
58
|
readonly run: (a: number, b: number) => [number, number, number, number];
|
|
31
59
|
readonly summary: (a: number, b: number) => [number, number, number, number];
|
|
32
60
|
readonly version: () => [number, number];
|
package/kshana.js
CHANGED
|
@@ -26,6 +26,87 @@ export function chart_svg(toml) {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Decode a permalink token back into the scenario TOML; returns an empty string if the
|
|
31
|
+
* token is not valid Base64 or not valid UTF-8.
|
|
32
|
+
* @param {string} token
|
|
33
|
+
* @returns {string}
|
|
34
|
+
*/
|
|
35
|
+
export function decode_permalink(token) {
|
|
36
|
+
let deferred2_0;
|
|
37
|
+
let deferred2_1;
|
|
38
|
+
try {
|
|
39
|
+
const ptr0 = passStringToWasm0(token, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
40
|
+
const len0 = WASM_VECTOR_LEN;
|
|
41
|
+
const ret = wasm.decode_permalink(ptr0, len0);
|
|
42
|
+
deferred2_0 = ret[0];
|
|
43
|
+
deferred2_1 = ret[1];
|
|
44
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
45
|
+
} finally {
|
|
46
|
+
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Encode a scenario TOML into a URL-safe permalink token for a `?s=` query parameter.
|
|
52
|
+
* @param {string} toml
|
|
53
|
+
* @returns {string}
|
|
54
|
+
*/
|
|
55
|
+
export function encode_permalink(toml) {
|
|
56
|
+
let deferred2_0;
|
|
57
|
+
let deferred2_1;
|
|
58
|
+
try {
|
|
59
|
+
const ptr0 = passStringToWasm0(toml, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
60
|
+
const len0 = WASM_VECTOR_LEN;
|
|
61
|
+
const ret = wasm.encode_permalink(ptr0, len0);
|
|
62
|
+
deferred2_0 = ret[0];
|
|
63
|
+
deferred2_1 = ret[1];
|
|
64
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
65
|
+
} finally {
|
|
66
|
+
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Run a scenario; on failure return the structured error *kind* tag
|
|
72
|
+
* (`invalid_input`, `unsupported`, …) so the caller can branch on the failure
|
|
73
|
+
* category rather than parse the message. Returns an empty string on success.
|
|
74
|
+
* @param {string} toml
|
|
75
|
+
* @returns {string}
|
|
76
|
+
*/
|
|
77
|
+
export function error_kind(toml) {
|
|
78
|
+
let deferred2_0;
|
|
79
|
+
let deferred2_1;
|
|
80
|
+
try {
|
|
81
|
+
const ptr0 = passStringToWasm0(toml, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
82
|
+
const len0 = WASM_VECTOR_LEN;
|
|
83
|
+
const ret = wasm.error_kind(ptr0, len0);
|
|
84
|
+
deferred2_0 = ret[0];
|
|
85
|
+
deferred2_1 = ret[1];
|
|
86
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
87
|
+
} finally {
|
|
88
|
+
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* List the available scenario kinds and their metadata as a JSON array (name,
|
|
94
|
+
* description, required and optional fields), for programmatic introspection.
|
|
95
|
+
* @returns {string}
|
|
96
|
+
*/
|
|
97
|
+
export function list_kinds() {
|
|
98
|
+
let deferred1_0;
|
|
99
|
+
let deferred1_1;
|
|
100
|
+
try {
|
|
101
|
+
const ret = wasm.list_kinds();
|
|
102
|
+
deferred1_0 = ret[0];
|
|
103
|
+
deferred1_1 = ret[1];
|
|
104
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
105
|
+
} finally {
|
|
106
|
+
wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
29
110
|
/**
|
|
30
111
|
* Run a scenario given as a TOML string; returns the result document as a JSON
|
|
31
112
|
* string. Throws a JS error if the scenario is invalid.
|
package/kshana_bg.wasm
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
"collaborators": [
|
|
5
5
|
"Chakshu Baweja <contact@ashforde.org>"
|
|
6
6
|
],
|
|
7
|
-
"description": "Open
|
|
8
|
-
"version": "0.
|
|
7
|
+
"description": "Open, reproducible PNT-resilience simulator with quantum-sensor performance models",
|
|
8
|
+
"version": "0.12.0",
|
|
9
9
|
"license": "Apache-2.0",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|