Releases: ashfordeOU/kshana
v0.16.0
Added
- Reference-grade precise orbit determination, cross-validated against real
agency products. A new batch least-squares estimator (src/precise_od.rs)
with a variational state-transition matrix and outlier editing, driven by a
full force model (PreciseForceModel: EGM2008 geopotential, third bodies,
solid + ocean + atmospheric tides, and empirical CPR/2-per-rev accelerations),
fed by a real IERSfinals2000AEarth-orientation parser. Validated against
published reference orbits: Galileo MEO to 13 cm post-fit, ESA Swarm-A
LEO, and LRO lunar (selenocentric, GRAIL gravity, IAU-2015 body frame —
reduced-dynamic 6.6 m, honestly above the 5 m target on the open path; the
DE-grade ANISE/DE440 path that reaches it is a workspace-excluded crate). spoof-detectscenario — an integrated multi-layer spoofing detector
combining per-epoch RAIM parity, AGC and signal-quality (SQM) monitors and a
fused decision, validated against the published TEXBAT scenario parameters
(Humphreys et al., ION GNSS 2012), including the carrier-aligned hard case.ephemerisscenario — state, frames, ground track and Doppler. Propagate
one satellite (TLE→SGP4 or an analytic orbit) and emit, per step, the inertial
TEME and GCRS state (position and velocity), the Earth-fixed ITRF/ECEF
position, the WGS-84 sub-satellite ground track (latitude / longitude /
altitude), and the topocentric azimuth / elevation / range with range-rate and
Doppler from a ground station. Reachable from the CLI, Python, WASM and the
MCP server, and shipped as the "Ground track" preset in the web playground,
where the track is drawn over a real world map (Natural Earth 1:110m
coastlines, embedded — no network or external dependency).- CCSDS OEM export (
--export-oem/export_oem = true) — the
velocity-carrying Orbit Ephemeris Message consumed by GMAT / Orekit / STK, at
parity with the existing SP3 and OMM exporters. - Solid, ocean (FES2004) and atmospheric (Ray 2001 S2) Earth tides on the
geopotential (IERS Conventions Ch. 6), wired into the force model. - ARM64 wheels — the PyPI build now also produces Linux aarch64
(manylinux_2_28), macOS arm64 and Windows arm64 wheels. - Extended technical report (preprint) linked from the README, and the JOSS
paper made submittable (author ORCID, compiled to PDF in CI on every change).
Changed
- Frames validated to the millimetre against published Vallado vectors. The
TEME→PEF/ITRF reduction, the full CIO IAU 2006/2000A GCRS→ITRS chain and the
ECEF→geodetic WGS-84 conversion are now pinned to the worked example in Vallado
et al. (AIAA 2006-6753) with its IERS EOP, not just to internal self-consistency. - Independent time-scale cross-checks. ERA and the UTC/TAI/TT scales agree
withhifitimeto < 1 µs, and the DE440 planetary ephemeris agrees with JPL
Horizons (Moon/Sun geocentric positions), both as always-on CI gates. - The web playground hides the figures-of-merit tab when a result carries no
figure-of-merit rows, so chart-only packs (ephemeris, RAIM, spoof) open on
their chart — for ephemeris, the ground track — instead of an empty table. - The playground's guided sliders and parameter sweep now work for the
ephemeris / ground-track scenario: its knobs (station latitude / longitude,
time step, duration, UT1−UTC) are tunable, and a sweep can plot pass geometry
(max elevation, peak Doppler, altitude, speed) against any of them — e.g. max
elevation vs station latitude. The Sweep tab is now shown only when a scenario
is actually sweepable, so no pack offers a control that plots nothing. - Documented the SGP4
DUT1 ≈ 0approximation at the GMST call site (a ≤ ~13″
rotation error, well inside SGP4's own model error) and refreshedCAPABILITY.md.
Get this release
Download — attached below, prebuilt (no toolchain needed); each artifact carries
SLSA build-provenance (verify with gh attestation verify <file> --repo AshfordeOU/kshana):
kshana— the simulator CLI / engine (Linux x86-64)kshana-mcp— the Model Context Protocol server (Linux x86-64)kshana-sbom.cdx.json— CycloneDX SBOMkshana-validation-summary.html— the per-release validation summary
On macOS or Windows, install from a registry below — the PyPI wheels, the npm/WASM
package, and the Docker image are all cross-platform.
Install from a package registry:
| Channel | Get it |
|---|---|
| crates.io | cargo install kshana · cargo install kshana-mcp |
| PyPI | pip install kshana |
| npm | npm install kshana |
| ghcr.io | docker run -i ghcr.io/ashfordeou/kshana-mcp:0.16.0 |
| MCP registry | io.github.ashfordeOU/kshana-mcp (auto-discovered by MCP clients) |
| JetBrains Marketplace | search "Kshana" in your IDE → Plugins |
No install: run it in your browser at kshana.dev · Cite: DOI 10.5281/zenodo.20528627
Full changelog: CHANGELOG.md · Docs: README
v0.15.1
Added
- The Kshana — PNT simulator JetBrains plugin is now published and approved on the
JetBrains Marketplace.
README,kshana.dev, and the distribution docs link to it directly.
Fixed
- MCP registry publish now succeeds: the
server.jsondescriptionwas over the
registry's 100-character limit (HTTP 422). Shortened it, and aligned the server name
(and the image's ownership label) to the canonical namespace
io.github.ashfordeOU/kshana-mcp. - JetBrains Marketplace publish now succeeds: the CI re-uploaded the same plugin
version that was listed manually, which the Marketplace rejects. The plugin version is
bumped to0.1.1, and the idempotency guard now also treats an "already contains
version" response as a no-op success. kshana.devcache-busting: the version-stampedstyle.css/app.jsquery strings
track the release, so returning visitors always get the current build.
Get this release
Download — attached below, prebuilt (no toolchain needed); each artifact carries
SLSA build-provenance (verify with gh attestation verify <file> --repo AshfordeOU/kshana):
kshana— the simulator CLI / engine (Linux x86-64)kshana-mcp— the Model Context Protocol server (Linux x86-64)kshana-sbom.cdx.json— CycloneDX SBOMkshana-validation-summary.html— the per-release validation summary
On macOS or Windows, install from a registry below — the PyPI wheels, the npm/WASM
package, and the Docker image are all cross-platform.
Install from a package registry:
| Channel | Get it |
|---|---|
| crates.io | cargo install kshana · cargo install kshana-mcp |
| PyPI | pip install kshana |
| npm | npm install kshana |
| ghcr.io | docker run -i ghcr.io/ashfordeou/kshana-mcp:0.15.1 |
| MCP registry | io.github.ashfordeOU/kshana-mcp (auto-discovered by MCP clients) |
| JetBrains Marketplace | search "Kshana" in your IDE → Plugins |
No install: run it in your browser at kshana.dev · Cite: DOI 10.5281/zenodo.20528627
Full changelog: CHANGELOG.md · Docs: README
v0.15.0
Added
kshana-mcp— Kshana as a Model Context Protocol (MCP) server (mcp/kshana-mcp/).
A standalone, workspace-excluded crate (thermcpSDK is edition 2024) that exposes the
validated engine to AI agents and assistants — Cursor, JetBrains AI Assistant / Junie,
and any MCP client — over stdio. Tools:run_scenario,list_scenario_kinds,
validate_scenario,export_sp3,export_omm, each a thin wrapper overkshana::api.- JetBrains IDE plugin (
ide/jetbrains/). Right-click a scenario.toml→
Run Kshana Scenario; figures of merit and result JSON stream into a Kshana tool
window. Pure-platform Kotlin plugin, compatible with every JetBrains IDE 2024.3+. - Public distribution + per-release auto-publish for both:
kshana-mcpto crates.io (cargo install kshana-mcp) viapublish.yml.kshana-mcpas a multi-arch OCI image onghcr.io
(docker run ghcr.io/ashfordeou/kshana-mcp) via a newmcp-publish.yml.kshana-mcpto the official MCP registry via GitHub OIDC (zero secrets); the
registry entry (server.json) uses the OCI package type with a label-verified owner.- the IDE plugin to the JetBrains Marketplace via
publishPlugin(token-gated,
optional developer signing) on each release tag.
Get this release
Download — attached below, prebuilt (no toolchain needed); each artifact carries
SLSA build-provenance (verify with gh attestation verify <file> --repo AshfordeOU/kshana):
kshana— the simulator CLI / engine (Linux x86-64)kshana-mcp— the Model Context Protocol server (Linux x86-64)kshana-sbom.cdx.json— CycloneDX SBOMkshana-validation-summary.html— the per-release validation summary
On macOS or Windows, install from a registry below — the PyPI wheels, the npm/WASM
package, and the Docker image are all cross-platform.
Install from a package registry:
| Channel | Get it |
|---|---|
| crates.io | cargo install kshana · cargo install kshana-mcp |
| PyPI | pip install kshana |
| npm | npm install kshana |
| ghcr.io | docker run -i ghcr.io/ashfordeou/kshana-mcp:0.15.0 |
| MCP registry | io.github.ashfordeOU/kshana-mcp (auto-discovered by MCP clients) |
| JetBrains Marketplace | search "Kshana" in your IDE → Plugins |
No install: run it in your browser at kshana.dev · Cite: DOI 10.5281/zenodo.20528627
Full changelog: CHANGELOG.md · Docs: README
v0.14.1
Added
- Independent ANISE/SPICE reference-frame cross-validation (
xval/anise-frames/).
A standalone, workspace-excluded crate cross-checkskshana's IAU 2006/2000A CIO
reduction (kshana::cio::gcrs_to_itrs_matrix, GCRS→ITRS) against ANISE (the
pure-Rust NAIF/SPICE reimplementation) rotating GCRF→ITRF93 from JPL's
earth_latest_high_prec.bpc, with the same IERSfinals2000AEarth-orientation
parameters fed to both sides, over eight quarterly epochs 2020–2023. The two
independent frame realizations agree to a maximum relative rotation of 0.028″ —
≤ 0.86 m on the ground, ≤ 0.93 m at LEO, ≤ 3.6 m at GNSS orbit, meeting the
long-standing ROADMAP "< 10 m" frame cross-check with large margin (it complements,
and does not replace, the existing bit-for-bit SOFA/ERFA anchors). The crate is
isolated becauseanise+hifitimeare MPL-2.0 / edition-2024 and must never enter
the publishedkshanadependency graph, itsCargo.lock, thecargo denylicense
gate, or the MSRV build; ANISE is pinneddefault-features = false. Includes a
frame-xvalbinary (fetches the ~5 MB BPC, prints a table, writesreport.{json,md}),
a kernel/network-self-skipping test gate, and an optionalworkflow_dispatch-only CI
job (never blocksmain). Documented indocs/VALIDATION.md(CIO row) andROADMAP.md.
Fixed
- Mobile-friendly playground. Fixed horizontal overflow of the playground
.panel
on phones (a CSS-grid item defaulting tomin-width: autorendered ~100 px wider than
the viewport) viamin-width: 0and width-guarded controls; verified clean at 360 /
390 / 414 / 768 px. Aligned the "Pin to compare" / "Download report" action buttons
(equal margin boxes in the flex row). Enlarged run buttons, sliders, selects and nav
links to the ~44 px WCAG 2.5.5 / Apple-HIG touch-target minimum on phones and touch
devices, with desktop sizing unchanged.
Full changelog: CHANGELOG.md · Docs: README
v0.14.0
Fixed
- Robustness hardening from an adversarial battle-test pass. (1)
sbas_protection_levelnow
rejects non-finite elevation/azimuth/variance and negative or non-finite covariance diagonals
(a near-singular geometry scaled up by small σ could previously slip the absolute-pivot gate and
return a NaN VPL / absurd HPL as a validSome— a silent integrity failure). (2) The
numerical propagator (propagate/propagate_dopri) fails closed on a non-finite initial state
instead of spinning the adaptive controller forever. (3) The DEM cell helper no longer panics on
a single-sample (1×N) grid. (4)lunar_look_angleazimuth is held strictly in[0, 360).
(5)SphericalHarmonicField::from_gfcrejects non-physical (NaN / non-positive)GM/radius.
Added
validation_reportbinary + release artifact: a dependency-free generator that emits a
one-page, print-ready HTML validation summary indexing every CI-enforced validation (SGP4
666/666, EGM2008, bit-for-bit frames, NIST Allan, IMU datasheets, ARAIM/SBAS, 3-OS
reproducibility, coverage) to its test and external oracle. The release workflow generates
kshana-validation-summary.htmland attaches it (with SLSA provenance) to each tagged release.- numpy-interop pytest + wheel hardening:
tests/python/test_numpy_interop.py(run in CI)
plus a pinned manylinux container and anauditwheel showverification step in the wheel build. - Tutorials & education:
docs/tutorials/(three worked tutorials, per-domain annotated
scenarios, Tier-1/2/3 exercises) withtests/tutorials.rspinning every quoted number to live
engine output. - External submission artifacts (
paper/,notebooks/,submissions/): a JOSS paper
draft, a quantum-vs-classical notebook, and ready-to-file kits for awesome-gnss / ESA Navipedia
/ NASA ASCL / ESA ESSR / ION/IAC, plusFUNDING.yml— staging the external steps for submission. - Terrain-referenced & combined alt-PNT navigation (
altpntmodule): a TERCOM/SITAN
terrain-matching navigator over a DEM (.hgtloader + synthetic-fixture generator) and a
combined gravity + magnetic (IGRF) + terrain GPS-denied navigator, exposed asterrain-navand
combined-altpntscenario kinds. Validated by terrain-match convergence (a known injected
offset recovered) and a bounded combined-filter error over a GPS-denied window. - LunaNet LANS geometry (
lunar): named lunar surface sites (Apollo 11/15/16, Shackleton
rim) with authoritative selenographic coordinates, surface look angles (az/el/range),
visibility/coverage, and site DOP, validated against the Moon radius, the published site
coordinates, and the radial-overhead 90° elevation identity. - Guided browser playground: guided-mode sliders, a tabbed output panel, a first-run tour
overlay, parameter-sweep and multi-run-overlay modes, a dependency-free canvas/SVG 3D orbit
view (the orbit pack now emits an additiveeci_track), an embed/iframe mode, and
download-as-HTML-report — each with node unit tests in CI. - Datasheet-validated IMU error model (
tests/imu_allan_spec.rs): ADIS16465/16488/16460
ARW/VRW/bias-instability recovered from the synthesised Allan deviation and checked against the
manufacturer specs (NIST SP1065 / IEEE 952 identification). - NIST SP1065 Allan-estimator validation (
tests/allan_nist_sp1065_1000point.rs): the four
estimators reproduce the published 1000-point reference deviations and Table-32 confidence
bounds. - SBAS / DO-229E protection levels, L1/L5 ionosphere-free, and a DO-316 compliance map
(sbasmodule).sbas_protection_levelforms the weighted geometry matrix from each
satellite's elevation/azimuth and UDRE/GIVE/airborne/tropo error budget, inverts the normal
matrix (sharedorbit::invert4), and projects the variances into HPL/VPL via the DO-229E
K-factors (PA 6.0/5.33, NPA 6.18).iono_free_l1l5adds the GPS L1/L5 ionosphere-free
pseudorange (IS-GPS-705,γ₁₅ = 1.79327), validated to cancel the engine's independent
first-order ionospheric delay.do316_compliance_maptraces DO-316/DO-229E requirements to
the implementing functions. Validated against closed-form K-factor definitions, the numpy
inv(GᵀG)reference geometry, and the two-route covariance identity; the published-PL
RTKLIB/gLAB conformance cross-check is documented as founder-gated indocs/COMPLIANCE.md. - Full tesseral spherical-harmonic gravity — the EGM2008 field to degree/order 70.
A newgravity_sh::SphericalHarmonicFieldevaluates the geopotential and its acceleration
in the Earth-fixed frame from fully-normalizedC̄_nm, S̄_nmcoefficients, using the stable
Holmes–Featherstone normalized Legendre recurrence (de-normalizing would overflow at this
degree). The shipped coefficients are the NGA EGM2008 product (public domain, via ICGEM),
bundled inegm2008_data.rsand reproduced bit-for-bit bytools/gen_egm2008.pyfrom the
committedtools/egm2008_to70.gfc; any ICGEM.gfcmodel loads viafrom_gfc. Validated
against three independent oracles: point-mass collapse (C̄00-only =−μr/|r|³), a zonal-only
field reproducing the existingforces::zonal_accelto ~1e-9, and the analytic acceleration
matching the finite-difference gradient of the directly-summed potential to <1e-6. - General-relativistic Lense–Thirring (frame-dragging) acceleration
(forces::lense_thirring_accel, IERS 2010 Eq. 10.12), the gravitomagnetic term beyond the
existing Schwarzschild correction, wired into the numerical propagator via a new
ForceModel::lense_thirring()flag. Validated as linear in the Earth's angular momentum and
1–2 orders of magnitude below the Schwarzschild term, the regime of the LAGEOS / Gravity
Probe B measurements. - A
Propagatortrait unifying the analytic and numerical orbit propagators. The
numerical Cowell force-model propagator is now a first-class peer of SGP4: a new
NumericalPropagatortype (initial state +ForceModel+Tolerance+ choice of
step-doubling or Dormand–PrinceIntegrator) andSgp4both implement
propagator::Propagator, whosestate_at(t_seconds) -> StateVectorreturns the inertial
TEME state in SI units (m, m/s) so the two are interchangeable behind a
Box<dyn Propagator>. The SGP4 impl is the exact km/min→SI conversion of the inherent
method (verified by an equality test); the numerical impl clears the same sub-metre
exact-Kepler gate through the trait, the two adaptive drivers agree, and aPropagatorError
surfaces the underlying SGP4 code.
Full changelog: CHANGELOG.md · Docs: README
v0.13.0
This release closes the largest correctness gap in the engine: Earth-orientation
and reference-frame reduction are now done to reference-implementation grade
(validated bit-for-bit against ERFA/SOFA), the integrity stack gains
dual-constellation ARAIM on real GPS+Galileo TLEs, and the propagation,
quantum-sensor, lunar/cislunar, and geomagnetic layers all deepen — alongside a
typed Python API, a richer browser playground, and a three-OS reproducibility
matrix. Highlights:
- Reference frames, bit-for-bit. Full IAU 2000A and 2000B nutation, IAU 2006
precession, the CIO-based (X, Y, s) IAU 2006/2000A GCRS↔ITRS reduction, IERS
polar motion, and TEME→GCRS/ITRS output frames — each validated bit-for-bit
against ERFA/SOFA reference routines. - Dual-constellation ARAIM (GPS + Galileo) on real TLEs, with HPL/VPL,
Stanford-diagram output, and an opendocs/ARAIM_REFERENCE.md. - Cislunar PNT: an Earth–Moon CR3BP propagator, MCI↔MCMF frames, selenographic
coordinates, and a runnable LunaNet lunar-integrity scenario. - Quantum sensing: Coriolis and AC-Stark systematics for the cold-atom
interferometer, a drift sweep, and validation against the Freier (2016) budget. - IGRF-14 geomagnetic main-field model, self-contained and validated.
- Typed Python API (PyO3
RunOutput/ScenarioMeta,.data(),scenario_kinds,
validate_toml, type stubs) with a CI wheel build, plus first-class GCRS/ITRS
propagator output and CCSDS OMM export. - Credibility & reproducibility: a head-to-head SGP4 accuracy comparison against
the independentsgp4crate, a CI coverage gate (~97% line onsrc/), and a
three-OS (ubuntu/macos/windows) reproducibility matrix.
Changed
- Every playground chart now matches the site theme. All twelve SVG chart
generators — the result/holdover chart (src/report.rs+src/chart.rs), the
Allan-deviation chart (web/app.js), and every scenario chart (src/hybrid.rs,
jamming.rs,timetransfer.rs,spoof.rs,raim.rsStanford + availability,
lunar.rs,ensemble.rs,sweep.rs,gnss_sim.rs,fusion/pack.rs,
inertial/mod.rs) — used cool navy panels (#0e131b), cool-gray axes/text, and
a clashing red/blue/purple series palette. They now use the warm graphite palette
throughout:--bgpanels, warm--linegrid,--fglabels, with a consistent
series assignment — quantum = honey-gold (--accent-bright), classical = warm
amber (--partial), spec/limit =--crit. Safety-coded views keep their
meaning: the RAIM Stanford diagram stays green (available) / amber (misleading) /
red (hazardous) / muted steel (unavailable), and HPL/VPL read as gold/bronze. - Charts are now self-describing when saved/downloaded. Both charts bake their
title into the SVG (the Allan chart's title + "lower is better" subtitle were
previously only HTML around the image, so a saved image had no caption), and both
carry a provenance footer —Kshana v<version> · <scenario-hash> · kshana.dev—
so a downloaded chart stands on its own and stays reproducible. - Every chart now carries the provenance footer. The footer —
Kshana v<version> · scenario <hash> · kshana.dev— is stamped centrally for all
scenario kinds inapi::run_toml(it was previously only on the holdover and Allan
charts), so any saved or downloaded image — from the playground, the CLI's
.chart.svgexport, or the HTML scorecard — identifies its version, scenario
fingerprint, and source. The hash is labelledscenariofor clarity and comes from
the result'sscenario_hashwhere present, with a source-hash fallback for the
integrity/lunar reports. What the fingerprint is and why it's there is documented in
the README "Output" section anddocs/PROVENANCE.md.
Fixed
raim::chi2_quantileand the RAIM Stanford-noise sampler are now panic-free on
out-of-range / non-finite inputs (aread_dir-order-dependent fuzz finding from
the new ARAIM scenarios).chi2_quantilenow guardsp/klikenormal_quantile
(returning a boundary value instead ofassert!-panicking), and the availability
Stanford-noiseNormalclamps to a strictly-positive σ — so the integrity/ARAIM
stack never panics on mutated or mis-configured scenarios.
Added
- Cross-platform reproducibility CI matrix. A new
reproducibility-matrix
job runs the reproducibility tests on ubuntu-latest, macos-latest, and
windows-latest on every push. Because full result JSON is not byte-identical
across OSes (last-ULP libm divergence), it asserts the platform-invariant
projection exactly — the input fingerprint plus output shape, pinned per
scenario as SHA-256 goldens intests/golden/by the new
tests/cross_platform_golden.rs— alongside the numeric pins (golden.rs, to
1e-6), the SGP4 states (sgp4_verification.rs, to 2e-5 km), and same-process
determinism (determinism.rs). Together these prove cross-platform
reproducibility on three OSes without the brittleness of exact full-output byte
hashing.docs/REPRODUCIBILITY.mddocuments the split. - Code-coverage gate in CI. A new
coveragejob runscargo-tarpaulinwith
the LLVM source-based engine, publishes an lcov report as a build artifact, and
enforces a line-coverage floor onsrc/(generated data tables, the CLI
entrypoint, the tests, and web assets excluded). Measured line coverage is
~97% onsrc/(SGP4 and the clock modules ≥95%); the gate is set at 85% — above
the ≥80% target and clear of the measured value, so it catches regressions
without flaking. A coverage badge is published in the README. - SGP4/SDP4 head-to-head against the independent
sgp4crate. A new test
(tests/sgp4_crate_comparison.rs) cross-validates Kshana's propagator against
the most widely used Rust SGP4 library (neuromorphicsystems/sgp4, added as a
test-only dev-dependency) over the same 666 AIAA 2006-6753 vectors. With both
driven on the WGS72 gravity model the vectors use, the two independent
implementations agree to sub-micron on near-earth and resonant orbits and
4.12 mm worst-case across all regimes, both reproducing the reference
tcppver.outtable. The committed comparison table
(tests/fixtures/sgp4_comparison.md, regenerated viaKSHANA_REGEN_FIXTURES=1)
breaks the result out per regime (LEO/MEO, deep-space, ½-day and 1-day
resonance) and notes the four deliberately-pathological cases the crate rejects
at construction. The live assertions hold both within 2e-5 km of the reference
and agree to within 4e-5 km — a regression guard, not a one-off. This is
competitive pedigree: correctness against an independent codebase, not just a
static table. (The crate's defaultfrom_elementsuses WGS84 and so differs
from the WGS72 reference by ~km — surfaced honestly in the table prose.) - CCSDS OMM export is now reachable end-to-end. The OMM writer
(src/omm.rs) previously had no CLI/API path; anorbitscenario's mean
elements can now be published as a CCSDS 502.0-B-2 OMM catalogue — one OMM KVN
message per TLE-defined satellite — viakshana <orbit.toml> --export-omm out.omm, orexport_omm = truein the scenario auto-writes<scenario>.omm
(mirroring the existing--export-sp3). Each message carries the satellite's
real NORAD catalogue number, COSPAR international designator (YYYY-NNNP),
and epoch (CCSDS day-of-year form), parsed from the TLE line 1 by the new
tle::parse_tle_identity; the name line becomesOBJECT_NAME(elseOBJECT <id>).CREATION_DATEis the scenario epoch, not wall-clock, so the output is
reproducible. New API:api::export_omm/api::auto_export_omm,
OmmFile::from_tle_block,OrbitClockScenario::to_omm_string. A synthetic
Walker or RINEX scenario (no TLE mean elements) errors rather than emitting an
empty file. Validated against the bundled 30-satellitegps-opssnapshot
(tests/sp3_export_roundtrip.rs). - Interactive hover read-outs on the playground charts. Moving the cursor over
a chart snaps a crosshair to the nearest sample and shows a value tooltip
(web/hover.mjs, wired inweb/app.js). On the Allan chart it reads τ and each
clock's σ_y(τ); on the time-series scenario charts (clock holdover, dead-reckoning,
time-transfer, hybrid PNT, GNSS/INS) it reads the time and each suite's value in
the chart's own units (ns / m / ps / utilization), parsed from the result so the
read-out matches the curve. Specialised diagrams (RAIM, spoof, sweep) get no
overlay. The charts stay self-describing blob<img>s — the overlay is a
transparent crosshair + tooltip on top, so download/compare/export are untouched.
Coordinate math (nearest-sample, cursor→plot-fraction, polyline parsing) is
unit-tested (web/hover.test.mjs, run in CI). - A/B compare mode in the playground. Pin any run as a baseline A, run a
second scenario, and the two are shown side by side with a figure-of-merit
delta table (holdover, timing RMS/p95, availability) that colours the winner
per metric (web/compare.mjs, wired inweb/app.js; delta logic unit-tested
inweb/compare.test.mjs, run in CI). All values are inserted as text and all
charts via blob<img>, so nothing from a scenario string is ever injected as
markup. - Chart download buttons (SVG + PNG). Each playground chart now has a
theme-matched "Download SVG / PNG" toolbar (web/chartdl.mjs, wired in
web/app.js). SVG hands back the faithful, scalable original; PNG rasterises
that same self-describing image at 2x for slides and documents. Files are named
with their provenance —kshana-<chart>-v<version>-<scenario-hash>.<ext>— and
the filename/size logic is unit-tested (web/chartdl.test.mjs, run in CI). - IGRF-14 geomagnetic main-field model (
src/igrf.rs). The IAGA standard
spherical-harmonic field (degree/order 13, 2025.0 epoch + 2025–2030 ...
v0.12.0
This release lands Kshana's first non-analytic orbit propagator — a Cowell
integrator with a hierarchical six-perturbation force model (two-body + J2–J6 zonal +
epoch-driven Sun/Moon third body + solar-radiation pressure with a conical
umbra/penumbra shadow + atmospheric drag + the post-Newtonian Schwarzschild relativistic
correction) driven by a choice of two adaptive integrators (RK4 step-doubling and the
Dormand–Prince RK5(4) embedded pair) — alongside a maneuver / trajectory-design layer
(impulsive and finite burns, an Izzo Lambert solver, and a porkchop sweep), a
gravity-map-matching alt-PNT layer that recovers a 60-minute GPS-denied track to under
500 m, a batch + sequential orbit-determination pipeline, and a full 17-state
tightly-coupled GNSS/INS UKF with quantum-CAI dead-reckoning. Every numerical capability
is pinned against analytic truth or a hand-derived closed form; the off-by-default
perturbations leave the released goldens untouched.
Added
- Post-Newtonian (Schwarzschild) relativistic correction (
forces::relativistic_accel+
propagator::ForceModel::relativity). Adds the dominant general-relativistic perturbation on a
near-Earth orbit — the leading driver of the relativistic perigee advance — in the IERS /
Montenbruck–Gillβ = γ = 1forma = (μ/c²r³)·{[4μ/r − v²]·r + 4(r·v)·v}. Like atmospheric
drag it is velocity-dependent, so it rides the(r, v)integrator RHS via
[accel_rv], opt-in and off by default. Validated self-contained: on a circular orbit it
collapses to the closed form3μ²/(c²r³)·r̂(purely radial and outward, off-axis components
exactly zero); its ratio to two-body is the textbook≈1.9·10⁻⁹at LEO (theμ/(c²r)
signature); a radial-velocity case matches the hand-simplifiedμ(4μ + 3v²r)/(c²r³); and in the
propagator it perturbs the orbit without dissipating it — the semi-major axis is conserved to
well under a metre/day, the structural opposite of drag's monotonic decay. Because it is off by
default the two-body/J2/zonal goldens are untouched. PPN-parameter (β,γ) tuning and the
Lense–Thirring frame-dragging term remain follow-ons. - Conical umbra+penumbra shadow model (
forces::conical_shadow), now used by solar-radiation
pressure. Upgrades the binary umbral-cylinder eclipse to a smoothν ∈ [0,1]factor: the Sun
and Earth are modelled as disks of apparent angular radiia = asin(R☉/d☉),b = asin(Rₑ/|r|)
with apparent centre separationc, andνis one minus the fraction of the Sun's disk occulted
by the Earth's disk (the circle–circle lens-overlap area) — full sun forc ≥ a+b, total umbra
forc ≤ b−a, annular forc ≤ a−b, and a continuous penumbra in between.srp_accelnow uses
it, so the SRP force tapers smoothly through eclipse instead of switching on/off. Adds the IAU
nominalforces::SOLAR_RADIUS. Validated self-contained:ν = 1in full sun andν = 0deep in
the umbra (exact), a smooth monotonic penumbra (νrises 0 → ~½ atc = b→ 1 across the
[b−a, b+a]band), and the conical penumbra extends beyond the umbral cylinder (a point the
binary cylinder calls fully lit is0 < ν < 1for the cone). The simplercylindrical_shadow
remains available; solar limb darkening and the oblate-Earth shadow remain follow-ons. - Dormand–Prince RK5(4) embedded integrator (
integrator::dopri54_step/
integrator::integrate_dopri+propagator::propagate_dopri). Adds the standard
Dormand–Prince (1980) embedded Butcher-tableau pair alongside the existing RK4 step-doubling
driver: seven FSAL stages yield a 5th-order solution and a 4th-order error estimate from one set
of evaluations (7 vs 11 function calls per step), a cheaper local-error estimate. The adaptive
driver reuses the same RMS-error norm and0.9·(1/err)^(1/5)step controller, so it is a drop-in
alternative;propagator::propagate_dopriexposes it on the orbit force model. Validated
self-contained: the embedded error estimate is O(h⁵) (halving the step cuts it ~32×); DP5(4)
integratesy' = ytoeand the harmonic oscillator over 50 periods conserving energy to
<1e-6; it reaches the same endpoint at the same tolerance in fewer function evaluations than
step doubling (without sacrificing accuracy); andpropagate_dopriclears the same analytic-truth
gate as the RK4 path — sub-metre against the exact universal-variable Kepler solution over a
24 h LEO orbit — while the two drivers agree to <1 m on a J2..J6 orbit (no closed form). Higher
embedded pairs (RKF7(8) / DOP853) remain a follow-on. - Atmospheric drag wired into the propagator as its first velocity-dependent force
(forces::atmospheric_density+forces::drag_accel+propagator::ForceModel::drag). Adds
the Vallado Table 8-4 piecewise-exponential atmosphereρ = ρ0·exp(−(h−h0)/H)(28 bands from
sea level past 1000 km, clamped below the surface) and the quadratic drag
a = −½ · ρ(h) · (C_D·A/m) · |v_rel| · v_relagainst the co-rotating atmosphere
v_rel = v − ωₑ ẑ × r(forces::EARTH_ROTATION_RATE = 7.2921151467e-5). Because drag depends on
velocity,ForceModelgains a newaccel_rv(t, r, v)and the integrator RHS now passes velocity
(f(t,[r;v]) = [v; a(t,r,v)]); the position-onlyaccel_atis unchanged, so the conservative
terms and goldens are untouched. Validated self-contained: the density anchors at the
1.225 kg/m³ sea-level value, clamps below the surface, decreases monotonically through LEO,
sits in the solar-mean ~1e-12 kg/m³ band at 400 km, and its recovered local scale height
(≈ 58 km at 400 km) is physical; drag opposes the co-rotating relative velocity at the
~2e-6 m/s² LEO magnitude forC_D·A/m = 0.02 m²/kg; and — the key signature — drag is
dissipative: a 300 km orbit loses specific energy monotonically and its semi-major axis
decays a bounded ~km/day, where the vacuum baseline conserves energy to <1e-9. The
NRLMSISE-00 thermospheric density (the < 5 % drag-density clause) remains a follow-on. - Solar-radiation pressure wired epoch-driven into the propagator force model
(forces::srp_accel+propagator::ForceModel::solar_radiation). Adds the cannonball SRP
modela = ν · P☉ · cᵣ · (A/m) · (AU/d)² · d̂with a cylindrical-shadow eclipse factor
(forces::cylindrical_shadow, ν ∈ {0,1}): the radiation pressureP☉ = Φ☉/cfrom the modern
1361 W/m² total solar irradiance (≈ 4.5398·10⁻⁶ N/m²), the inverse-square(AU/d)²flux fall-off,
and the radial push away from the Sun. It rides the same epoch-driven RHS as the third
body, sampling theephemSun once at the advanced epochepoch_jd_tt + t/86400shared between
the Sun third body and SRP. Composable:
with_zonals_j2_j6().third_body(true, true, epoch).solar_radiation(1.5, 0.02). Validated
self-contained against hand-derived signatures: the 1-AU radiation pressure pins to its textbook
≈ 4.5398·10⁻⁶ N/m²; a fully-lit LEO sat's SRP is bit-identical to the cannonball formula,
points away from the Sun, and sits in the ~1.36·10⁻⁷ m/s² band for cᵣ = 1.5, A/m = 0.02
m²/kg; doubling the Sun distance quarters the magnitude (inverse-square); the cylindrical
shadow eclipses only the umbral cylinder (anti-sunward and within one Earth radius of the
Earth–Sun line) and yields exactly zero SRP in eclipse; and in the propagator SRP perturbs
a LEO orbit by a small bounded amount that scales ~linearly with A/m — while a model with no
perturbations stays bit-for-bit time-independent, leaving the two-body/J2/zonal goldens untouched.
The conical umbra/penumbra (smooth ν ∈ [0,1]), atmospheric drag, and external GMAT/Orekit
cross-validation remain follow-ons. - Epoch-driven Sun/Moon third body wired into the time-varying propagator RHS
(propagator::ForceModel::third_body/accel_at). The third-body perturbation is no longer a
standalone force term — it is now integrated by the Cowell propagator as a genuinely time-varying
force: each RHS evaluation samples theephemSun/Moon positions at the advanced epoch
epoch_jd_tt + t/86400(reusingprecession::julian_centuries_ttfor the day↔century
conversion), so the perturbers move along their orbits during the integration rather than being
frozen at the start. Composable with any gravity model
(ForceModel::with_zonals_j2_j6().third_body(true, true, epoch)). Validated self-contained:
the RHS Sun term is bit-identical tothird_body_accelevaluated at the ephemeris position for
that instant at botht = 0andt = 1 day(proving the 86400 s ↔ 1 day ↔ 1/36525 century
wiring exactly), the perturber advances ~2.6·10⁹ m/day between samples (not frozen), the
instantaneous LEO tidal magnitudes hit the textbook ~5·10⁻⁷ m/s² (Sun) and ~1.1·10⁻⁶ m/s²
(Moon, ≈ 2× the Sun) bands, each body measurably perturbs the day-long trajectory while staying
bounded, and the same initial state propagated at epochs a quarter-year apart yields a
different trajectory (the tidal axis rotates 90°) — while a model with neither body enabled is
bit-for-bit time-independent, leaving the two-body/J2/zonal goldens untouched. DE-grade ephemeris
accuracy and external GMAT/Orekit cross-validation remain follow-ons. - Low-precision Moon ephemeris (
ephem::moon_position), completing the Sun/Moon third-body pair.
Adds the Montenbruck & Gill low-precision lunar series (§3.3.2) alongside the Sun model, so the
body-agnosticforces::third_body_accelcan now be driven by either luminary with no external
DE/SPK kernel. Validated self-contained against hand-derived lunar signatures: the geocentric
distance stays inside the real perigee/apogee envelope (~356 500–406 700 km) over a month and its
monthly mean recovers the ~384 400 km semi-major axis; the **ecliptic latitude never exce...
v0.11.0
Changed
- Honest framing for the quantum positioning. The headline descriptor is now a
"PNT-resilience simulator with quantum-sensor performance models" consistently
across the README tagline, citation line,CITATION.cff(title + abstract), and
the banner artwork — replacing the looser "hybrid quantum/classical PNT simulator"
marketing phrasing. The README's What it is / is not section gains an explicit
"It is not (yet)" scope statement (not a first-principles atom-interferometry
physics engine, not a GNSS receiver/PVT solver, not a mission-design tool), and a
new top-levelROADMAP.mdmakes the Quantum physics layer a P2
item (Mach–Zehnder CAI phase, projection noise, vibration tensor) so readers know
the first-principles physics is scoped-and-coming, not abandoned. No behaviour or
API change.
Added
- Constellation-design trade study: Walker design sweep with a Pareto front, revisit-time
JSON, and a sub-kilometre Walker-formula validation.src/walker.rsgains
walker_design_sweep, which runs aplanes × sats_per_planegrid (e.g. a 3×3 trade) at a
fixed inclination and tabulates, per design, the coverage fraction, worst-case PDOP, and the
max/mean revisit gap;pareto_frontflags the non-dominated designs (fewer satellites, more
coverage, lower PDOP, shorter revisit), andWalkerDesignReport::to_jsonserialises the cells
and Pareto front — revisit-time fields included — as JSON. New validation pins the generator to
the Walkeri:T/P/Fformula: same-slot satellites in adjacent planes are shown to map onto one
another by an exactR_z(2π/P)rotation to under 1 km over a full 24 h of SGP4 propagation
(the J2 short-period breathing is common-mode and cancels), and the in-plane slots are confirmed
spaced2π/Sin the mean. Builds on the committed real Celestrakgps-ops2021-07-28 snapshot
(scenarios/orbit-sgp4-gps.toml, exercised by the scenario-coverage and SP3 round-trip tests). - Advanced time-and-frequency transfer: TWSTFT, GNSS common-view, PPP, optical, IEEE-1139
power-law fit, and a clock ensemble. Newsrc/timetransfer_adv.rsbuilds the operational
transfer methods on the shipped Sagnac/common-view closed forms and the Allan-stability tools.
twstft_sagnacgives the Two-Way Satellite Time and Frequency Transfer Sagnac correction as the
three-hop loop sum, equal to the BIPM closed formΔt = 2·A·ω_E/c²exactly (cross-checked by the
independenttwstft_sagnac_bipm);run_twstftemits a one-dayT_A − T_Bseries and its TDEV.
gnss_common_view_seriessingle-differences two synthetic ground stations so the satellite clock
cancels.iono_free_combination+ppp_receiver_clockare the PPP ionosphere-free combination and
receiver-clock solve against an SP3-grade (synthetic) truth, cancelling the first-order ionosphere
exactly.rytov_variance,fried_parameter, and the unit-meanlognormal_fadingmodel a free-space
optical link's turbulence-induced scintillation.fit_power_law_psdis a full IEEE-1139 five-coefficient
h_αleast-squares fit of the Allan-variance curve (all five canonical noise processes at once) with the
dominant process reported per τ-decade.ensemble_timescaleforms an inverse-variance-weighted paper
timescale whose Allan deviation falls strictly below the best contributing clock. 31 unit tests;
validation targets are closed forms and synthetic truth — a real BIPM Circular-T / IGS SP3 ingest remains. - IONEX ionosphere maps: file parser, time interpolation, and slant obliquity mapping.
src/ionex.rs
gainsparse_ionex, which reads the IONEX file format (header grid definition +START/END OF TEC MAP
blocks) into a sequence ofIonexMaps — normalising the file's north-to-south latitude ordering into a
positive-stepTecGridand scaling values by10^EXPONENT.interpolate_tec_in_timeblends two
successive maps to a query epoch, andobliquity_factor/slant_tecmap the vertical TEC onto a slant
ray via the single-layer thin-shell factorM(z) = 1/cos z′(sin z′ = (Rₑ/(Rₑ+H))·sin z). Together
with the shipped grid model these turn a measured IGS global ionosphere map into a usable slant delay. - Constellation design: streets-of-coverage sizing + multi-constellation comparison.
src/walker.rs
gainsmin_satellites_streets_of_coverage, an idealised streets-of-coverage minimum-satellite solver —
from the shipped coverage half-angleλand street half-widthcit sizes the near-polar constellation
for continuous single global coverage asp = ⌈π/(2c)⌉planes (e.g. a GPS-altitude 4-satellite plane
needs 2 planes, 8 satellites), and reportsNonewhen the satellites are too sparse to form a continuous
street.compare_constellationsis the multi-constellation comparison tool: it scores each named Walker
design on the same station/window viapdop_sweepand returns their coverage / PDOP / size side by side.
Honest scope: the seam-exact Rider correction at the counter-rotating plane boundary and a 3-D coverage
globe are follow-ons. - Multi-layer spoof detection: RAIM-consistency parity detector + layer fusion.
src/spoof_monitors.rs
gains the third and final detection layer and the fusion stage:parity_raim_testleast-squares-fits
the position/clock solution to a redundant pseudorange set and tests the leftover weighted residual
sum-of-squares against its χ²(m−4)threshold — flagging a biased subset of satellites while
correctly leaving a common-mode bias (absorbed by the receiver clock) RAIM-invisible, not papered
over.fuse_spoof_layerscombines the parity, AGC and SQM layers into one weighted decision that
records which layers fired. A Monte-Carlo characterises the detector: empirical P_fa ≈ 0.068
against a 0.05 design point, with missed-detection falling from 0.885 at a 2σ spoof bias to 0.16 at
8σ. Honest scope: cross-validation against specific published (Spirent / ION GNSS+) spoofing test
vectors needs those external datasets and remains a follow-on. - Coupled-vs-decoupled Kalman validation ensemble. A 100-trial Monte-Carlo in
src/fusion/coupled.rsquantifies the value of carrying the position↔clock cross-covariance: a
faithful inline decoupled baseline (validated bit-for-bit against the shippedCoupledPntFilter)
processes the same data with the cross blocks zeroed, and after near-degenerate pseudoranges plus a
clock-only fix the coupled filter recovers position to 2.97 m RMS versus the decoupled filter's
48.8 m, winning 97 of 100 trials — the clock fix sharpens position only through the correlation
the decoupled pack discards. This completes the Kalman-correctness validation suite (Joseph form,
PSD safety, NEES/NIS consistency, and now the coupled-filter ensemble). - Orbit determination pipeline (batch + sequential). A new
src/orbit_determination.rsrecovers
a satellite's orbital state[r, v]from ground-station range tracking, composing three shipped
pieces: the two-body + J2 force model (src/forces.rs) and RK4 integrator (src/integrator.rs)
propagate a candidate state across the arc, a range measurement model predicts each station range,
and the Gauss–Newton batch corrector (src/batch_ls.rs) drives the candidate onto the best-fit
state (determine_orbit_batch). The same dynamics and range model also drive a sequential
recursive determination on the shipped unscented filter (determine_orbit_sequential). Four tests
validate it: range prediction across the arc; batch recovery to sub-metre / mm·s⁻¹ from noiseless
ranges; batch recovery to ~2 m with a post-fit residual at the 5 m noise floor (the signature
of a consistent least-squares fit); and sequential recovery to within tens of metres. Honest scope:
range-rate/Doppler and angle measurements, an analytic J2 state-transition matrix, and station
visibility masking are follow-ons. - Tightly-coupled GNSS/INS UKF navigator. A new
src/fusion/tightly_coupled.rswires the
shipped unscented Kalman core (src/fusion/ukf.rs) into a working tightly-coupled navigator over
the eight-state[px,py,pz,vx,vy,vz,b,d](ECEF position/velocity plus receiver clock bias and
drift in range units). It ingests the raw satellite measurements —pseudorange
(ρ = |p − sᵢ| + b) andrange_rate/Doppler (ρ̇ = (p − sᵢ)·(v − ṡᵢ)/|p − sᵢ| + d) — rather
than a pre-formed position fix, soTightlyCoupled(withpropagate/propagate_orbital/
update_gnss) keeps correcting with fewer than four satellites and coasts through GNSS
outages on its propagated dynamics. Five tests validate it end-to-end, including the milestone
acceptance scenarios: the pseudorange/Doppler geometry against hand values; noiseless convergence
to sub-metre on five satellites; a three-satellite case converging from ~212 m to ~13 m
where a snapshot PVT cannot even be formed; a constant-velocity 120-second outage within 50 m;
and — the headline acceptance — a 30-minute curving LEO pass (real two-body + J2 orbit) with a
120-second GNSS outage, held to 0.77 m pass RMS and 2.9 m worst-case through the
outage. That orbital coast composes the shipped gravity force model (src/forces.rs) and RK4
integrator (src/integrator.rs) into the UKF process model (propagate_orbital), so the filter
follows the orbit's curvature — which a constant-velocity coast cannot (curvature alone is ~58 km
over 120 s at LEO). Honest scope: the orbital coast uses the two-body + J2 force model rather than
raw IMU specific-force (for an unpowered orbital platform these coincide); folding in a
strapdown-IMU error state and in-loop iono/tropo corrections remain follow-ons. - Map-matching measurement model (terrain-/gravity-referenced navigation). A new
src/mapmatch.rssupplies the measurement model that turns the shipped...
v0.10.0
Changed
- Real-data validation. The multi-GNSS RINEX navigation parser, the GLONASS
RK4 propagator, and the SP3 reader are now exercised against genuine IGS/DLR
files (a real RINEX 3 mixed broadcast nav file and an IGS SP3-c orbit product),
not only self-authored samples — asserting non-empty satellite sets and finite,
physically-sized ECEF positions. The fixtures are test-only (excluded from the
published crate); seetests/fixtures/igs/NOTICE. - RAIM on real reference-orbit geometry. The snapshot, solution-separation
(MHSS), and ARAIM protection-level cores are now validated against the real IGS
precise-orbit (SP3) geometry, not synthetic constellations alone: the line-of-sight
geometry is built from the first SP3 epoch at a real ground station, and the tests
assert metre-level, APV-I-available protection levels, that a 60 m pseudorange bias
trips the χ² monitor, that solution separation identifies the faulted satellite,
and that ARAIM's levels meet the allocatedP_HMI. Closes the
validated-on-synthetic-geometry-only gap (receiver-domain gLAB parity over a full
RINEX arc remains a roadmap item — it needs a pseudorange solution).
Added
- Per-node confidence intervals for the N-D parameter sweep (
sweep::nd_sweep_ensemble).
Each grid node of the N-dimensional Cartesian-product sweep can now be evaluated as a
Monte-Carlo ensemble of seeds, reporting the metric's mean, percentiles, and a
percentile-bootstrap 95% CI per node (for both clocks) — a statistically honest sweep
rather than one draw per node. Reuses the ensemble/bootstrap machinery (metric_stat);
deterministic;runs = 1reduces exactly to the single-seednd_sweep. (Generalising
the sweep across all packs, entangled with the typed-Scenario refactor, and parallel
execution remain.) - NaveGo cross-validation of the IMU-noise pipeline (
tests/navego_imu_crossval.rs).
An external cross-check against NaveGo (R. Gonzalez's open-source INS/GNSS toolbox):
reproduces the synthetic round-trip ofnavego_example_allan.mon its published
Microstrain 3DM-GX3-35 reference profile, confirming our overlapping-ADEV estimator
recovers NaveGo's velocity- and angle-random-walk coefficients (ADEV(1 s) = σ·√dt)
to under 5% with the expected −1/2 white-noise slope. (The 40 MB recorded STIM300
.matlog is not ingested — binary-format-gated.) - Tightly-coupled (pseudorange) GNSS/INS update.
GnssInsEkf::update_tightly_coupled
(and theClosedLoopInsGnss::fuse_tightly_coupledwrapper) implement the
previously-stubbed range-domain measurement: the innovation is the predicted
range from the INS position to each satellite versus the measured pseudorange,
with a line-of-sight Jacobian on the position error. Because each satellite is a
scalar measurement, the filter keeps correcting with fewer than four
satellites — where a loosely-coupled PVT fix does not exist. Five tests cover
four-satellite nulling, two-satellite correction (no PVT possible), single-
satellite along-line-of-sight observability, and input validation. Pseudorange-
only; carrier phase and an explicit receiver-clock state remain roadmap. The
unusedtight_couplingcargo feature (which gated the old error stub) is removed. - Loosely-coupled GNSS/INS scenario pack (
kind = "gnss-ins",src/fusion/pack.rs).
Wires the three-axis strapdown navigator and the 15-state error-state EKF
(closed_loop/gnss_ins_ekf) into a runnable scenario with a figure of merit —
the EKF disciplines the mechanization against noisy GNSS fixes while coverage is
up, then coasts through the outage, replacing the legacy 1-DOF scalar pack's
truth-snap reset with genuine fusion. The result reports the fused horizontal
error series, the scored position FoM (availability / outage RMS / holdover), and
the open-loop free-INS RMS for comparison; a quantum/classical IMU pair differs
only in true bias. Dispatched from the CLI/Python/wasm entry point with a
scenarios/gnss-ins.tomlexample. Honest framing: loosely-coupled only, one
deterministic trajectory, and the fused outage error is floor-limited by the
hand-over attitude error (so it is not claimed to scale with bias) — the robust
findings are that fusion beats unaided dead-reckoning for a biased sensor and that
a lower-bias sensor has the better unaided coast. - Constellation design on the validated SGP4 core (
src/walker.rs). A new
walkermodule emits a designed Walker-delta pattern (i: T/P/F) as SGP4
mean elements, so the synthetic constellation propagates through the same
SGP4 path validated to 4.12 mm against the AIAA 2006-6753 vectors — not the
analytic Keplerian generator. On top of it:pdop_sweeptabulates coverage and
median/worst PDOP over a{planes × sats × inclination}design grid, and
coverage_revisitreports the coverage fraction and revisit gaps (worst/mean)
at a ground point. Validated by the physical monotonicities a trade must obey
(more satellites ⇒ higher coverage, lower PDOP, shorter revisit). Separately, a
genuine Celestrakgps-opsTLE snapshot (2021-07-28, 30 operational GPS
satellites) is added as a test-only fixture and the real-TLE → SGP4 → ECEF
geometry path validated against it (full MEO shell within 1%, nine-satellite
all-in-view at PDOP 1.64), alongside the existing SP3 and RINEX real-data paths. - Noise-type-specific effective degrees of freedom for the Allan confidence
intervals.allan::edf_overlapping_adevimplements the NIST SP 1065 Table 5
closed forms (the Stable32 simple set) for all five canonical power-law noise
types — white/flicker PM, white/flicker FM, random-walk FM — replacing the
conservative non-overlapping count as the χ² degrees of freedom. A new
PowerLawNoiseenum andclassify_power_lawidentify the dominant type from
the record's modified Allan-deviation slope (MDEV separates white from
flicker PM where ADEV cannot), andoverlapping_adev_curvenow attaches the
identified noise type, its edf, and a 95% confidence band to every point of the
exported ADEV curve (AdevPointgainsnoise/edf/ci_lo/ci_hi, additive
with serde defaults). Validated two ways: the five formulas match hand-evaluated
values to 1e-12, and a 4 000-record Monte-Carlo white-FM ensemble confirms the
formula predicts the estimator's actual chi-squared edf within 20% (and that it
materially beats the conservative count). Eight new tests. - Two-way time-transfer stochastic model.
timetransfer::TwoWayLinkreplaces the
white-only sampler with a physically-grounded model: the reciprocal (common-mode) path
delay cancels in the(m_AB - m_BA)/2estimate (two_way_offset_estimate, so two
independent one-way measurements average to1/sqrt(2)), and the residual is the
non-reciprocal differential delay — modelled as a colored white-FM + random-walk-FM
process (the validatedClockModel), giving the synchronization-error series a realistic
Allan signature (sigma_y^2(tau) = q_rw*tau/3) instead of flat white noise.LinkCfg
gainsq_wf_s/q_rw_s(serde default 0 ⇒ the legacy white-only behaviour, bit-for-bit),
the link FoM reportsadev_tau0(the model's Allan deviation at the base step), and the
timetransferscenario/CLI surface it. Golden FoM re-pinned. Six hand-derived tests
(common-mode cancellation, the sqrt(2) two-way gain, the RWFMtau/3law via the link's
ownstep(), legacy-equivalence atq=0, determinism, and end-to-end FoM exposure). - Stable32 numeric parity for the Allan-family estimators (NBS14).
tests/allan_reference.rs
validates the overlapping ADEV, modified ADEV, time deviation, and overlapping Hadamard
estimators against the Stable32 reference deviations for the canonical NBS14 dataset
(W. J. Riley, Handbook of Frequency Stability Analysis, NIST SP 1065, ~p.107) at
tau = 1, 2 to a 1e-4 relative tolerance — actual agreement ~1e-6. This pins the
estimator mathematics against the de-facto reference implementation, not just against
the estimators' own analytic self-consistency. Only the public reference numbers are
used; no third-party code. - Vertical Stanford integrity diagram exported by the
integrityscenario. The
runnableintegrityscenario kind now exports a vertical Stanford(-ESA) diagram
alongside the HPL/VPL availability map: at each protected epoch a seeded, reproducible
no-fault range-error draw is mapped through the geometry to an actual vertical position
error and classified against the VPL and the vertical alert limit (Available /
System-Unavailable / Misleading / Hazardously-Misleading). The diagram (per-epoch
points + region counts) is carried in the result JSON and the integrity-event / HMI
counts in the CLI summary, so the Stanford classifier — previously library-only — is
reachable end-to-end.IntegrityScenariogains aseedfield (default 0) controlling
the error realization; the availability map itself remains geometry-only and seed
independent. - ARAIM integrity-risk (P_HMI) budget for the protection levels.
raim::araim_raim
derives the horizontal and vertical protection levels from an explicit integrity-risk
budget rather than a fixedK_mdmultiplier: for the all-in-view solution and every
single-satellite exclusion sub-solution it builds the per-mode(prior, detection threshold, σ)on each axis, thenaraim_protection_levelsolves the smallest PL whose
summed probability of hazardously-misleading information (araim_integrity_risk,
P_HMI = Σ_k p_fault,k · Q((PL − T_k)/σ_k), Blanch et al. Baseline ARAIM) meets the
allocatedP_HMI. The result reports the integrity risk the levels actually achieve, so
a user can trade integrity against the alert limit explicitly. Six hand-derived tests
(fault-free and thresholded single-mode closed forms, multi-mode summation/mono...
v0.9.2
Added
- Archival DOI. Releases are now deposited to Zenodo and assigned a citable DOI.
Full changelog: CHANGELOG.md · Docs: README