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
sequential-importance-resampling particle filter (src/particle_filter.rs) into a working
GPS-denied navigator:field_likelihood(a Gaussian field-match likelihood) and
map_match_likelihood, which samples any georeferenced reference field — terrain elevation
(TRN) or a gravity anomaly — at a particle's position and weights it by agreement with the
vehicle's measured value. The field is anyFn(lat, lon) -> valuesampler, so it composes
with the bilinear grid insrc/ionex.rsor a closure. Two tests anchor it — the likelihood
peaks (=1) at a perfect match and falls toe^(−½)at one sigma, and a particle filter over
a distinctive synthetic-terrain patch recovers the true position to within 0.1. Honest scope:
the real reference maps (SRTM elevation, EGM/EIGEN gravity anomaly) and their loaders are
follow-ons. - Cislunar PNT integrity (lunar ARAIM). A new
src/lunar.rsapplies the Earth-side
MHSS ARAIM engine to a LunaNet-style lunar navigation service with the lunar parameters
(σ_URE ≈ 30 mvs GPS 0.6 m,P_sat ≈ 1e-4): lunar constants, a selenocentric
East/North/Up basis and sky-geometry helper, andlunar_araim(HPL/VPL). Three tests
anchor it — the orthonormal selenocentric basis, the slant-range geometry, and the exact
linear protection-level scaling withσ_URE(lunar 30 m gives a 50× larger protection
level than the same geometry at the GPS 0.6 m — the quantitative reason lunar PNT
integrity is hard). Honest scope: the precise LANS NRHO ephemeris, the signal-in-space
error budget, and the MCI↔MCMF frame reduction are follow-ons. - Two-part (high-precision) Julian dates. A new
src/jd2.rsaddsJd2, a Julian date
split into an integerdayand a fractionalfracin[0,1)(the SOFA/hifitime
convention), withnew/from_parts/add_seconds/diff_seconds/total. Differences of
nearby epochs stay exact to thef64floor where a single-f64JD loses ~50 µs near
J2000. Four tests anchor it: the round-trip, fraction normalisation, exact microsecond
recovery (with the single-f64failure demonstrated alongside), and additive/reversible
second arithmetic. - CCSDS OMM (Orbit Mean-Elements Message) writer. A new
src/omm.rscomplements the
oemephemeris writer with the mean-elements message:OmmFile::from_tlemaps SGP4/TLE
mean elements into the OMM units (mean motion in rev/day, angles in degrees, plus
BSTAR), andto_omm_kvnserialises the standards-track CCSDS 502.0-B-2 KVN form — so a
Kshana orbit can be consumed by any OMM-aware tool instead of as a bespoke TLE. Two tests
anchor the TLE→OMM unit conversion (≈ 15.5 rev/day, 51.6° inclination, etc.) and the
presence of the required KVN keywords. Honest scope: the KVN form and TLE mapping ship
here; the XML (ndm/omm) rendering and a reference-parser round-trip are follow-ons. - Sequential-importance-resampling particle filter. A new
src/particle_filter.rs
adds the nonlinear, non-Gaussian estimator behind map-aided, GPS-denied navigation
(terrain-referenced or gravity-map matching):predict(propagate particles through the
dynamics + Gaussian process noise),update(reweight by a per-particle measurement
likelihood), systematicresample, theeffective_sample_sizedegeneracy monitor, and
the weighted-mean estimate. Six tests anchor the deterministic core exactly — ESS spanning
1…N, systematic resampling picking indices in proportion to weight, the weighted-mean
convex combination, a Gaussian likelihood pulling the estimate onto the measurement,
resample-to-uniform behaviour, and seeded predict determinism. Honest scope: the engine
ships here; the reference maps (SRTM elevation, EGM gravity anomaly) and the map
measurement model are follow-ons (theionexgrid+bilinear sampler would serve a
gravity/terrain map equally). - IONEX-style TEC ionosphere maps. A new
src/ionex.rsadds the measured-ionosphere
alternative to the broadcast Klobuchar model: aTecGrid(a regular lat/lon grid of
vertical TEC, an IGS global ionosphere map) with bilinear interpolation at a pierce point
(vtec_at, clamped outside the grid) and the first-order delayΔ = 40.3·TEC/f²
(vtec_to_delay_m,delay_at). Four tests anchor it:1 TECU ≈ 0.162 mat L1 with the
1/f²scaling, node-exact interpolation, bilinear midpoints averaging the corners, and
edge-clamped out-of-grid queries. Honest scope: the grid and interpolation ship here;
parsing the IONEX file format, time interpolation between maps, and the slant mapping
function are follow-ons. - Geometric time-transfer corrections (Sagnac + GNSS common-view). A new
src/timegeo.rsadds the two deterministic effects a real clock comparison must account
for, complementing the stochastic two-way model intimetransfer:sagnac_correction
(Δt = (ω_E/c²)·(x₁y₂ − x₂y₁), the rotating-Earth delay — tens of ns for continental
baselines) andcommon_view_offset, the GNSS common-view single difference that cancels
the satellite-clock error exactly and recovers the inter-station offset. Three tests
anchor them on exact references: the ≈ 33 ns Sagnac of an equatorial quarter-turn,
antisymmetry and the zero radial/polar cases, and the exact satellite-clock cancellation.
Honest scope: a full TWSTFT transponder/hardware-delay budget and a PPP ionosphere-free
time-transfer solution are follow-ons. - Orbital force model (two-body + J2). A new
src/forces.rsadds the acceleration
model a numerical propagator integrates:two_body_accel(−μ·r/|r|³), thej2_accel
oblateness perturbation (the ECI closed form), andgravity_accelsumming them — pair
it withsrc/integrator.rsasf(t,[r;v]) = [v; a(r)]. It also exposes the analytic J2
secular rates (j2_secular_rates): the nodal regressionΩ̇, apsidal rotationω̇,
and mean-anomaly driftṀ. Six tests anchor the physics on exact references:μ/r²for
the two-body term, the J2 closed form at the equator (~10⁻³ of the two-body magnitude),
the critical inclination (63.4349°) that freezes the perigee (ω̇ = 0), the ISS
nodal regression (Ω̇ ≈ −5°/day), and the eastward drift of a retrograde sun-synchronous
orbit. Honest scope: two-body + J2 only; J3–J6, drag, SRP, and third-body are follow-ons. - Shareable scenario permalinks. A new
src/permalink.rsadds a dependency-free
RFC 4648 Base64 codec (standard+/alphabet with padding, and a URL-safe-_
unpadded alphabet) andencode_scenario/decode_scenariowrappers, so a playground
TOML can be encoded into a?s=query parameter and shared as a URL. Exposed to the
browser asencode_permalink/decode_permalinkwasm bindings. Four tests anchor it
on the canonical RFC 4648 vectors ("foobar"→"Zm9vYmFy", etc.), a URL-safe scenario
round trip (no+///=to escape), invalid-symbol rejection, and an all-256-byte
round trip. Honest scope: the codec and bindings ship here; the playground Share-button
UI, the Plotly/D3 multi-series chart, and the A/B comparison mode are follow-ons. - Gauss–Newton batch least squares (the batch differential corrector). A new
src/batch_ls.rsadds the estimation core a batch orbit determination (or any
parameter fit) rests on:gauss_newtonlinearises a user-supplied modelh(x)with a
central finite-difference Jacobian, forms and solves the weighted normal equations
(HᵀWH)·Δx = HᵀW·(z − h(x))(reusing the tested matrix inverse), and iterates to
convergence with per-measurement weights. Four tests anchor it: a linear line fit reaching
the exact weighted-least-squares solution, a nonlineara·exp(b·t)fit recovering the true
parameters, a 3-D range-multilateration that recovers a known position from noise-free
ranges (the orbit-determination flavour), and rejection of under-determined/mismatched
inputs. Honest scope: this is the generic corrector engine; the orbit-specific
range/range-rate/azimuth-elevation measurement model, the analytic J2 state-transition
matrix, and the published-case validation are follow-ons. - RF-layer spoofing monitors (AGC power and SQM). A new
src/spoof_monitors.rsadds
two independent receiver-front-end spoof detectors that complement the clock-aided
time-spoof monitor inspoof: an AGC power monitor (combine_power_dbmincoherent
power sum +AgcMonitor) that flags the excess received power a spoof transmitter adds
beyond a configurable dB margin, and a signal-quality monitor (bpsk_autocorr
triangular code autocorrelation +SqmMonitor) that flags the Early-minus-Late
correlator imbalance multipath/meaconing/replay introduces. Four tests anchor the exact
closed forms (3.01 dB for a doubling of power, the10·log10(N)aggregate, the
triangularR(τ)=1−|τ|, and the 10 % Early/Late alert threshold). Honest scope: the
full RAIM-consistency parity spoof detector, the multi-layer fusion of the monitor
outputs, and validation against published Spirent/ION GNSS+ spoofing vectors are
follow-ons. - Adaptive numerical ODE integrator. A new
src/integrator.rsadds the first piece
of a numerical propagator (Kshana's orbit propagation is otherwise analytic SGP4/SDP4):
a generic fourth-order Runge–Kutta step (rk4_step) over any first-order system
y' = f(t, y), and an adaptive driver (integrate) that controls local error by
step doubling (Richardson extrapolation) with the standard0.9·(tol/err)^(1/5)
step controller and accept/reject logic. Six tests anchor it on exact solutions: the
y' = y → eexponential to< 1e-9, the ~16× error reduction per halved step that
proves fourth-order convergence, energy/return conservation of the harmonic oscillator
over a full period, and the adaptive driver meeting a tight tolerance with variable
steps. Honest scope: this is the integrator core and its error control; the
Dormand–Prince RK5(4)/RKF7(8) embedded tableaux and the hierarchical orbit force model
(two-body + J2–J6 + drag + SRP + third-body) that make it aNumericalPropagatorare
follow-ons. - Unscented (sigma-point) Kalman filter. A new
src/fusion/ukf.rsadds the
scaled unscented Kalman filter (Julier & Uhlmann; Wan & van der Merwe) as a general
n-state estimator over user-supplied process and measurement functions — the
sigma-point estimator a tightly-coupled GNSS/INS navigator uses when the
pseudorange/Doppler model is strongly nonlinear and an EKF's Jacobian degrades. It
includes the supporting dense linear algebra (Cholesky factor for the sigma-point
spread, Gauss–Jordan inverse for the innovation covariance) and a Joseph-free
P⁺ = P⁻ − K S Kᵀupdate. Six tests pin it down, the key ones exploiting the exact
property that for a linear model the unscented transform reproduces the Kalman
filter to numerical precision (predict, update, and a full predict+update cycle all
matched against a hand-run linear KF, plus a 1-D analytic Bayesian-posterior check
and the Cholesky/inverse identities). Honest scope: this is the estimator engine; the
17-state tightly-coupled GNSS/INS navigator, pseudorange/Doppler measurement model,
and outage-validation scenario remain follow-ons. - Dual-constellation ARAIM protection levels. A new
araim_dual_raimextends the
single-fault Advanced RAIM (araim_raim) with the constellation-wide fault mode of
EU ARAIM / DO-316: alongside the fault-free and per-satellite hypotheses, each
constellation (labelled per satellite) contributes one hypothesis that removes all of its
satellites at once, with priorP_const(a newDualFaultPriors { p_sat, p_const }). Every
hypothesis adds a term to the same MHSS integrity sum, so VPL/HPL are the smallest bounds
whose totalP_HMImeets the budget over fault-free + single-SV + per-constellation faults
(the Bonferroni false-alert split is over allN + Chypotheses). WithP_const = 0the
result is bit-for-bitaraim_raim; a single-constellation user returnsNoneagainst its
own constellation fault (it cannot be excluded) — which is exactly why dual-constellation
coverage matters. Four tests cover the equivalence, the protection-level widening, the
single-constellation unavailability, and input validation, reusing the existing
solution-separation sub-solution machinery. - IAU 2006 precession (Fukushima–Williams angles and bias-precession matrix). A new
src/precession.rsimplements the IAU 2006 (P03; Capitaine, Wallace & Chapront 2003)
precession: the four Fukushima–Williams angles(γ̄, φ̄, ψ̄, ε̄_A)as polynomials in TT
Julian centuries (fw_angles), and the GCRS→mean-of-date bias-precession rotation matrix
built from them via the SOFAiauFw2mconstruction (precession_matrix, with
gcrs_to_mod/mod_to_gcrshelpers). This is the first inertial-frame piece on top of
the existing GMST-basedframesreduction. Eight tests validate against closed-form
anchors — the J2000 mean obliquityε̄ = 84381.406″ = 23.4392794°, the published angle
constant terms, theψ̄ ≈ 5039.998″general-precession accumulation over a century,
matrix orthonormality anddet = +1, the near-identity (frame-bias-only) value at J2000,
and the≈ 1.40°/century net rotation angle. Honest scope (ROADMAP.md): precession
only — the IAU 2000A 678-term nutation, the full TEME→GCRS chain, and a SOFA/ANISE µas/<10 m
numerical cross-check are follow-ons. - First-principles cold-atom-interferometer (CAI) accelerometer physics.
src/inertial/quantum_imu.rsmodels a three-pulse Mach–Zehnder atom interferometer
from first principles instead of a datasheet: effective wavevectork_eff = 4π/λ,
interferometer phaseΦ = k_eff·a·T², quantum projection (shot) noiseσ_Φ = 1/(C·√N),
per-shot acceleration sensitivity, contrast decayC(t) = C₀·e^(−t/τ), and — the
point —CaiAccelerometer::q_va(), which derives the white-acceleration PSD the
classicalAccelModelalready consumes from the atom number, interrogation time, and
contrast. The model now also covers vibration coupling — the dominant real-device
term: the interferometer acceleration→phase transfer function|H(ω)| = (4/ω²)sin²(ωT/2)(accel_transfer_function), the white-PSD phase variance
σ_Φ² = k_eff²·S_a·T³/3(vibration_phase_variance_white, with a numeric band-integral
cross-checkvibration_phase_variance_band), the rank-1 along-beambeam_axis_projection,
andCaiAccelerometer::vibration_phase_noise/vibration_limited_accel(the latter
reducing to thek_eff-independent√(S_a/(3T))floor). Eleven tests hand-verify the
physics (Rb-87k_eff ≈ 1.61×10⁷,Φ(1 g) ≈ 1.58×10⁴ rad,σ_a ≈ 0.13 µg/shot shot-noise
floor vs ≈ 5.9 µg vibration floor, the1/T²,1/√N, andT³scaling laws). Honest
scope indocs/QUANTUM.md: this spans the projection-noise floor and the vibration-limited
regime above it; laser-phase noise, Coriolis and light-shift systematics, and the
PHARAO/CARIOQA validation scenarios remain follow-ons. - Quantum-CAI accelerometer wired into the inertial scenario. An accelerometer in an
inertial dead-reckoning scenario now resolves to a newImuKind—Classical(the
existing datasheet-coefficient sensor) orQuantumCaiwhen it carries an optional[cai]
block (CaiCfg: wavelength, pulse separation, atom number, contrast, cycle time, and an
optional platformvibration_psd). Aquantum_caisensor's velocity-random-walk PSD
q_vais derived from the interferometer physics — the shot-noise floor plus, when a
vibration PSD is given, the vibration-limited contribution in quadrature — instead of a
supplied coefficient, and the run's provenance records that the noise is physics-derived.
Thecaifield isskip_serializing_if = "Option::is_none", so existing scenarios omit it
and serialize byte-identically (the scenario hash is unchanged). Five tests cover the
derivation, the quadrature vibration sum, theClassical/QuantumCaiselection, hash-stable
serialization, and an end-to-end CAI-driven run. - Constellation-design optimiser and streets-of-coverage geometry.
src/walker.rs
gainsoptimize_walker_design, a gradient-free grid optimiser that searches the
{planes × sats × inclination}design space and returns the best Walker design under
a chosenDesignObjective—MinSatellitesForCoverage,MaxCoverage, or
MinWorstPdop— over the already-validated PDOP sweep (a test confirms it returns the
brute-force winner). Plus the analytical streets-of-coverage closed forms
coverage_half_angle_rad(λ = arccos(Re/r·cos ε) − ε) andstreet_half_width_rad
(cos c = cos λ / cos(π/s), Rider/Beste), hand-verified against textbook geometry and
detecting the under-population gap. The full Rider minimum-satellite global-coverage
solver, a 3-D playground globe, and an external-tool DOP cross-check remain follow-ons. - SP3 precise-ephemeris export from the CLI. A propagated orbit/constellation
scenario can now be written to an SP3-c file:kshana <orbit.toml> --export-sp3 out.sp3, orexport_sp3 = truein the scenario auto-writes<scenario>.sp3
(api::export_sp3/auto_export_sp3,OrbitClockScenario::to_sp3_string, optional
epoch). A round-trip test (tests/sp3_export_roundtrip.rs) propagates the real
Celestrakgps-opssnapshot, exports it, re-parses it, and confirms the recovered
ECEF positions match the SGP4 truth over 24 h to < 0.5 m (well inside the 10 m
TLE-grade tolerance). README documents the interoperability role (RINEX → RTKLIB/gLAB,
SP3 → Ginan/precise-orbit products). - Coupled clock+position Kalman filter (cross-block covariance).
src/fusion/coupled.rs
CoupledPntFilteris a single stacked[pos, vel, phase, freq]filter (Joseph-form
updates) whose pseudorange measurementρ = g·pos + c·phase + noisegenuinely
couples the position and clock blocks — unlike the legacy fusion pack's two
independent two-state filters, which keep the cross-block covariance exactly zero.
Validated: a shared pseudorange drivesP[pos,phase]non-zero; two distinct
geometries jointly resolve injected position+clock offsets a single range cannot
separate; a clock-only fix sharpens the position through the cross-covariance
(the payoff decoupled filters cannot provide); and the Monte-Carlo NEES is
χ²(4)-consistent. This is the 1-DOF realization (the fusion pack's
dimensionality); the 3-D 8-state extension and wiring into the runnable pack are
tracked as follow-ons. - Kalman filter-consistency health monitoring (NIS/NEES). The two-state clock
filter's covariance update is now in Joseph stabilised form `P⁺ = (I−KH)P(I−KH)ᵀ- KRKᵀ
, which stays positive-semidefinite under extreme Q/R ratios (Cholesky-checked in CI atR=1e-26 / Q≈1e-30). A newsrc/filter_health.rsruns a Monte-Carlo consistency assessment (Bar-Shalom §5.4): pooled **NIS** (normalised innovation², target 1) and **NEES** (normalised estimation error², target 2) against 95% χ² bands, surfaced as afilter_health { nis_mean, nis_chi2_lower_95, nis_chi2_upper_95,
nees_mean, nees_chi2_lower_95, nees_chi2_upper_95, consistent }block in the clock result JSON and as a green/amber card in the playground. A Q/R-mismatch sweep test proves the monitor flips to inconsistent when the process noise is mistuned by ×0.1–×10. Adds a general χ² quantile (detection::chi2_inv_cdf`, Wilson–Hilferty,
table-checked).
- KRKᵀ
docs/PROVENANCE.md— one citable provenance table. Consolidates every sensor
parameter (clocks, inertial, time-transfer), physical/algorithmic model (orbit, time
systems, frames, iono/tropo, integrity, detection, jamming, Allan), and validation
dataset (AIAA 2006-6753, Celestrakgps-ops) with its published source — datasheet,
paper, ICD, or standard — and an honest maturity label (flight-qualified /
ground-lab / space-goal-on-ground-hardware). Linked from the README intro and
Documentation table; complements the per-runprovenancestrings that already travel
in the result JSON.- Typed scenario API. Dispatch is now on a typed
ScenarioKindenum instead
of a rawkindstring match (ScenarioKind::classify+ exhaustive dispatch), so
adding a pack is compile-checked. New typed surfaces alongside the unchanged
string-returningrun_toml:run_scenario(src) -> Result<RunOutput, KshanaError>
with a structured error taxonomy (InvalidInput/NonConvergence/
Unsupported/IoError, each with a stablekind_tag()); aScenariotrait
andExternalPackextension point (thejammingpack is wired through it as the
worked example); andlist_scenario_kinds()introspection (name, description,
required/optional fields per kind). The Python and WebAssembly bindings gain
list_kinds()anderror_kind(). Documented indocs/ARCHITECTURE.md. - Real GPS constellation + operating-envelope coverage.
scenarios/orbit-sgp4-gps.tomlnow ships a real Celestrakgps-opssnapshot
(2021-07-28, 30 satellites) instead of synthetic Walker TLEs, with
strict_checksum = trueso it only loads when every TLE checksum is valid;
scripts/fetch_tles.shdocuments reproducible refresh and the README credits
the open-data source. Newtests/scenario_coverage.rsexercises each pack across
≥5 envelope variants asserting finite/bounded output, confirms the flicker-FM
floor measurably degrades a clock's coast when enabled (now set in three shipped
scenarios), and confirms the fusion filter converges with a realistic non-zero
accelerometer bias (within 3× the zeroed-bias case), closing the "fusion only
works with zeroed biases" realism gap.docs/VALIDATION.mdgains an Operating
Envelope table. - Measurement-domain GNSS simulation (
gnss-simkind). A pseudorange-level
forward model: per visible satellite it synthesisesρ = geometric range + c·δt_rx − c·δt_sv + I + T + noise + multipathand the L1 Doppler, with the
Klobuchar single-frequency ionosphere (IS-GPS-200 §20.3.3.5.2.5) and the
Saastamoinen zenith troposphere projected by the Niell (1996) mapping
function — exposed as[iono]and[tropo]TOML blocks. The residuals feed
snapshot RAIM for per-epoch HPL/VPL, and agnss_measurements[]JSON array
carries each SV's pseudorange, Doppler, C/N₀, and iono/tropo corrections. A
zero-noise run reproduces geometry + corrections to sub-millimetre (CI test).
Newsrc/gnss_sim.rsandscenarios/gnss-sim-raim.toml. - Stochastic time-spoof detector (
spoofkind). The spoof pack now runs a real
detector instead of a deterministic ramp-vs-bound comparison: four injection
shapes (linear_ramp,step_jump,meaconing,replay), a two-sided χ²₁
energy / Neyman–Pearson test on the clock-aided monitor statistic with the
threshold set from a target false-alarm budgettarget_pfa, and the
missed-detection probabilityP_mdreported both closed-form and by Monte-Carlo
(mc_runstrials per hypothesis — the two agree to a few ×1/√N). The Security
figure of merit is now1 − P_mdat the operationally-harmful (spec) magnitude.
Newsrc/detection.rs(Gaussian tail functions, NP/energy test, Monte-Carlo
P_fa/P_md) andscenarios/spoof-meaconing.toml. Backward compatible: a bare
[attack] rate_ns_per_sis still accepted as a linear ramp.
Changed
- Security FoM definition (
spoofkind): from the analytic detectability
bound1 − min_detectable/thresholdto the stochastic detector's1 − P_md.
The clock pack'ssecurityfield remains the faster analytic proxy.
Added (continued)
- RF jamming model (
jammingkind). A link-budget interference model that
turns a jammer's power and geometry into per-satellite loss of lock: the
jammer-to-signal ratio from free-space path loss and the per-direction
receive-antenna gain, the effective C/N₀ via the standard anti-jam equation
(despreading processing gain × the spectral-separation factorQ; Kaplan &
Hegarty §9.4), and a configurable tracking threshold, scored over a Walker
constellation as anavailability_under_jammingfigure of merit. New
src/jamming.rsandscenarios/jamming-demo.toml. Honest scope (no multipath,
terrain shadowing, AGC, or adaptive nulling) is documented in
docs/CAPABILITY.md/docs/VALIDATION.md. - Generic N-D parameter sweep over any scenario kind (
sweep-nd). The
previous N-D sweep was clock-pack only.sweep-ndvaries dotted TOML keys of a
[base]scenario over the Cartesian product of its axes, re-dispatches each
grid node through the normal run path, and reads one or more metrics out of the
result by dotted JSON path — so it works for every pack (inertial, gnss-ins,
integrity, spoof, …) without coupling to each pack's Rust type. Grid nodes are
evaluated in parallel across OS threads on native targets (no added
dependency); wasm falls back to sequential. Deterministic and row-major
regardless of thread count. Newscenarios/sweep-nd-inertial.tomlexample. - TOML-configurable deterministic IMU error model in the
gnss-inspack. The
three-axis strapdown error chain (scale-factor, misalignment, g-sensitivity,
quantization, rate-ramp; IEEE Std 952-1997 §A.2, Groves 2013 §4.3) is now
reachable per sensor from a scenario file via an optional[imu_*.error_model]
block, layered on top of the constant turn-on biases. Omitting the block leaves
each sensor a pure constant-bias source, so existinggnss-insruns are
unchanged. This wires the previously library-only error model into a runnable
pack and figure of merit.
Full changelog: CHANGELOG.md · Docs: README