kshana 0.12.0 → 0.13.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 CHANGED
@@ -12,6 +12,7 @@
12
12
  <p align="center">
13
13
  <a href="https://ashfordeou.github.io/kshana/"><img src="https://img.shields.io/badge/playground-try%20in%20browser-c79e63" alt="Live playground — run in your browser, no install"></a>
14
14
  <a href="tests/sgp4_verification.rs"><img src="https://img.shields.io/badge/SGP4-666%2F666%20AIAA%20vectors%20%C2%B7%204.12mm-3fb950" alt="SGP4 validated against all 666 AIAA 2006-6753 vectors, worst 4.12 mm"></a>
15
+ <a href="https://github.com/ashfordeOU/kshana/actions/workflows/ci.yml"><img src="https://img.shields.io/badge/coverage-~97%25%20line-3fb950" alt="~97% line coverage on src/ (cargo-tarpaulin LLVM engine), gated at 85% in CI"></a>
15
16
  <a href="https://github.com/ashfordeOU/kshana/actions/workflows/ci.yml"><img src="https://github.com/ashfordeOU/kshana/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
16
17
  <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
18
  <a href="LICENSE"><img src="https://img.shields.io/badge/License-Apache_2.0-blue.svg" alt="License: Apache-2.0"></a>
@@ -42,7 +43,7 @@ citable table in [`docs/PROVENANCE.md`](docs/PROVENANCE.md).
42
43
  *Free and open source under Apache-2.0, professionally developed and maintained by
43
44
  Ashforde OÜ — commercial support, integration, and proprietary extensions available.*
44
45
 
45
- > **Status: v0.12.0 · a simulation substrate, not yet a product.** A validated,
46
+ > **Status: v0.13.0 · a simulation substrate, not yet a product.** A validated,
46
47
  > fully reproducible engine spanning the PNT stack — orbit geometry and constellation
47
48
  > design, a numerical (Cowell) propagator with a six-perturbation force model, maneuver
48
49
  > and trajectory design, time systems, inertial navigation (incl. map-aided and
@@ -218,6 +219,10 @@ cargo run -- scenarios/integrity-raim.toml
218
219
 
219
220
  # Export a propagated constellation to an SP3-c precise-ephemeris file:
220
221
  cargo run -- scenarios/orbit-sgp4-gps.toml --export-sp3 gps.sp3
222
+
223
+ # Export the constellation's mean elements to a CCSDS OMM catalogue (one OMM
224
+ # message per TLE-defined satellite, with its real NORAD id / COSPAR designator):
225
+ cargo run -- scenarios/orbit-sgp4-gps.toml --export-omm gps.omm
221
226
  ```
222
227
 
223
228
  **Interoperability role.** Kshana is the *performance-simulation* layer that sits
@@ -226,7 +231,11 @@ output into RTKLIB or gLAB for a position solution, and use its **SP3** output a
226
231
  precise-orbit product for tools like Ginan — Kshana answers *what resilience a given
227
232
  PNT architecture buys* before you have real signals, in formats those tools already
228
233
  ingest (`--export-sp3`, or `export_sp3 = true` in an `orbit` scenario, writes
229
- `<scenario>.sp3`).
234
+ `<scenario>.sp3`). The same orbit can be published as standards-track **CCSDS OMM**
235
+ mean elements (`--export-omm`, or `export_omm = true`, writes `<scenario>.omm`) —
236
+ one OMM 502.0 KVN message per TLE-defined satellite, carrying each object's real
237
+ NORAD catalogue number, COSPAR international designator, and epoch, for any
238
+ OMM-aware consumer instead of a bespoke two-line element set.
230
239
 
231
240
  Example output (clock holdover — note the Integrity and Security figures of merit):
232
241
 
@@ -455,8 +464,19 @@ power-law type is identified from its modified-Allan slope, and the χ² interva
455
464
  matching NIST SP 1065 effective degrees of freedom). The browser playground renders it as a
456
465
  log-log "Clock stability (ADEV)" chart. (MDEV, TDEV, and HDEV are available as library
457
466
  estimators; the exported result curve is the overlapping ADEV.) Every field, with units and a
458
- source pointer, is documented in [`docs/SCHEMA.md`](docs/SCHEMA.md). The figures of
459
- merit follow the standard operational PNT figures of merit:
467
+ source pointer, is documented in [`docs/SCHEMA.md`](docs/SCHEMA.md).
468
+
469
+ **Every chart is self-describing.** The browser playground, the CLI's `*.chart.svg`
470
+ export, and the HTML scorecard all stamp each chart image with a footer reading
471
+ `Kshana v<version> · scenario <hash> · kshana.dev`. The `scenario <hash>` is the first
472
+ 12 hex characters of the run's **scenario hash** — a SHA-256 over the canonical scenario
473
+ definition (seed, thresholds, model parameters, GNSS windows, …); the integrity and lunar
474
+ reports, which carry no hash of their own, fall back to a SHA-256 of the scenario source.
475
+ It is the **same fingerprint** shown in the one-line summary and the result JSON, so a
476
+ saved or pasted chart always carries its version, the exact scenario that produced it (for
477
+ bit-for-bit reproduction), and the source — change any input and the hash changes.
478
+
479
+ The figures of merit follow the standard operational PNT figures of merit:
460
480
 
461
481
  | Figure of merit | How Kshana computes it |
462
482
  |-----------------|------------------------|
@@ -472,7 +492,10 @@ New to these terms? Each is defined in plain language in the [glossary](docs/GLO
472
492
 
473
493
  ## Architecture
474
494
 
475
- One engine; each sensor pack plugs in via a common error-model interface. See
495
+ One engine. The sensor packs plug in via a common error-model interface; alongside
496
+ them sit an astrodynamics/numerical layer (analytic SGP4/SDP4 **and** a numerical
497
+ Cowell propagator with its force model, maneuver design, and orbit determination) and a
498
+ fusion / alt-PNT layer (the GNSS/INS estimators and the gravity-map matcher). See
476
499
  [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) for the full set of diagrams.
477
500
 
478
501
  ```mermaid
@@ -488,30 +511,45 @@ flowchart LR
488
511
 
489
512
  ```mermaid
490
513
  flowchart TD
491
- cli["CLI · Python · WebAssembly"] --> api["api — run_toml: dispatch by kind"]
514
+ cli["CLI · Python · WebAssembly"] --> api["api — run_toml / run_scenario: typed dispatch by kind"]
492
515
  subgraph shared["Shared core"]
493
516
  types["types"]
494
517
  scenario["scenario · GNSS timeline"]
495
518
  allan["allan — Allan deviation"]
496
519
  end
497
- subgraph p1["Pack 1 · Clock"]
498
- models["modelsClockModel (+ flicker)"]
499
- estimator["estimatorholdover"]
500
- kalman["kalmanIntegrity bound"]
501
- security["securityanalytic spoof-detectability bound"]
502
- fom["fom · report · run"]
520
+ subgraph packs["Sensor packs"]
521
+ p1["Clockmodels · estimator · kalman · security · fom"]
522
+ p2["inertialstrapdown INS + quantum-CAI"]
523
+ p3["timetransfer (+ _adv) optical/RF link"]
524
+ p4["hybridfused PNT suite"]
525
+ end
526
+ subgraph astro["Astrodynamics & numerical"]
527
+ orbit["orbit — geometry → GNSS timeline + DOP"]
528
+ sgp4["sgp4 · tle — SGP4/SDP4"]
529
+ prop["propagator — Cowell"]
530
+ forces["forces — J2–J6 · 3rd-body · SRP · drag · relativity"]
531
+ integ["integrator — RK4 · DOPRI"]
532
+ ephem["ephem — Sun/Moon"]
533
+ man["maneuver — burns · Lambert · porkchop"]
534
+ od["orbit_determination — batch · sequential"]
535
+ end
536
+ subgraph fnav["Fusion & alt-PNT"]
537
+ fus["fusion — EKF · UKF · 17-state · coupled"]
538
+ grav["gravimeter · mapmatch · particle_filter"]
503
539
  end
504
- p2["Pack 2 · inertial — accel + gyro"]
505
- p3["Pack 3 · timetransfer — optical/RF link"]
506
- p4["Pack 4 · hybrid — fused PNT suite"]
507
- orbit["orbit geometry → GNSS timeline + DOP"]
508
- api --> p1
509
- api --> p2
510
- api --> p3
511
- api --> p4
512
- p1 --> shared
513
- p2 --> shared
514
- p3 --> shared
540
+ api --> packs
541
+ api --> astro
542
+ api --> fnav
543
+ packs --> shared
544
+ orbit --> sgp4
545
+ prop --> forces
546
+ prop --> integ
547
+ forces --> ephem
548
+ man --> integ
549
+ od --> forces
550
+ od --> integ
551
+ fus --> p2
552
+ grav --> p2
515
553
  orbit --> p1
516
554
  p4 -. composes .-> p1
517
555
  p4 -. composes .-> p2
@@ -523,27 +561,32 @@ flowchart TD
523
561
  ```
524
562
  kshana/
525
563
  ├── src/
526
- │ ├── types.rs # Seconds, TimeGrid, ModelSpec
527
- │ ├── scenario.rs # GNSS timeline, clock scenario config
528
- │ ├── models.rs # ErrorModel trait, ClockModel (white FM, RWFM, aging)
529
- ├── estimator.rs # HoldoverEstimator (quadratic offset+aging removal)
530
- │ ├── fom.rs # figure-of-merit scoring
531
- │ ├── allan.rs # overlapping Allan deviation
532
- │ ├── kalman.rs # two-state Kalman clock estimator + integrity bound
533
- │ ├── report.rs # result schema, scenario hash, SVG chart (clock)
534
- │ ├── run.rs # clock + orbit-clock run pipelines
535
- │ ├── inertial.rs # Pack 2: inertial dead-reckoning (accel + gyro) + FoMs
536
- ├── timetransfer.rs # Pack 3: optical/RF time-transfer link
537
- │ ├── hybrid.rs # Pack 4: combined PNT suite + ISL clock-aiding
538
- │ ├── orbit.rs # orbit propagation + GNSS line-of-sight visibility
539
- │ ├── api.rs # scenario dispatch shared by the CLI and bindings
540
- │ ├── python.rs # optional PyO3 extension (feature = "python")
541
- ├── wasm.rs # optional wasm-bindgen module (feature = "wasm")
542
- └── main.rs # CLI
543
- ├── scenarios/ # cited scenarios (one per pack + a geometry-driven one)
564
+ │ ├── types.rs · scenario.rs · allan.rs # shared core (time grid, GNSS timeline, Allan)
565
+ │ ├── api.rs · main.rs # typed dispatch + CLI
566
+ │ ├── python.rs · wasm.rs # optional PyO3 / wasm-bindgen bindings
567
+
568
+ │ ├── models.rs · estimator.rs · kalman.rs # Pack 1 — clock holdover + integrity
569
+ │ ├── security.rs · detection.rs · spoof.rs · spoof_monitors.rs # spoof detection
570
+ │ ├── filter_health.rs · fom.rs · report.rs · chart.rs · run.rs # health · scoring · output
571
+ │ ├── inertial/ # Pack 2 strapdown INS (attitude, mechanization, imu_errors, quantum_imu)
572
+ │ ├── timetransfer.rs · timetransfer_adv.rs · timegeo.rs # Pack 3 TWSTFT/CV/PPP/optical, Sagnac
573
+ │ ├── hybrid.rs · ensemble.rs · sweep.rs # Pack 4 fused PNT suite, Monte-Carlo, trade sweeps
574
+
575
+ │ ├── orbit.rs · sgp4.rs · tle.rs · walker.rs # geometry, SGP4/SDP4, TLE, Walker design
576
+ │ ├── propagator.rs · forces.rs · integrator.rs # numerical Cowell propagator + force model + RK4/DOPRI
577
+ │ ├── ephem.rs · precession.rs · frames.rs · timescales.rs · jd2.rs # ephemerides, IAU precession, time/frames
578
+ │ ├── maneuver.rs · batch_ls.rs · orbit_determination.rs # burns/Lambert/porkchop, Gauss-Newton, OD
579
+
580
+ ├── fusion/ # GNSS/INS — EKF, UKF, tightly_coupled, tightly_coupled17, coupled
581
+ ├── gravimeter.rs · mapmatch.rs · particle_filter.rs # gravity-map / alt-PNT navigation
582
+ │ ├── raim.rs · lunar.rs # ARAIM HPL/VPL, cislunar integrity
583
+ │ ├── gnss_sim.rs · ionex.rs · jamming.rs # measurement domain, ionosphere maps, jamming
584
+ │ └── rinex.rs · rinex_obs.rs · glonass.rs · sp3.rs · oem.rs · omm.rs · permalink.rs # interop formats
585
+ ├── scenarios/ # cited scenarios (one per kind + geometry-driven + GPS-denied)
544
586
  ├── scripts/ # reproducibility + repo-hygiene guards
545
- ├── docs/ # CONCEPTS, ARCHITECTURE, VALIDATION, GLOSSARY, assets/
546
- ├── .github/workflows/ # CI gate, release, and wheel-build pipelines
587
+ ├── docs/ # CONCEPTS, ARCHITECTURE, CAPABILITY, VALIDATION, PROVENANCE, GLOSSARY,
588
+ ├── web/ # the WebAssembly playground + kshana.dev site
589
+ ├── .github/workflows/ # CI gate, release, wheels, publish, and pages pipelines
547
590
  ├── pyproject.toml # Python packaging (maturin)
548
591
  ├── CHANGELOG.md # Keep a Changelog + SemVer
549
592
  └── CONTRIBUTING.md
@@ -561,7 +604,7 @@ kshana/
561
604
  | [Provenance](docs/PROVENANCE.md) | reviewers / citers | every sensor parameter, model, and dataset traced to its published source, in one citable table |
562
605
  | [Reproducibility &amp; provenance](docs/REPRODUCIBILITY.md) | reviewers / packagers | determinism guarantees, golden-pinning, SBOM, build provenance |
563
606
  | [Positioning](docs/POSITIONING.md) | evaluators | where Kshana sits vs RTKLIB/gLAB (complementary), and the zero-install browser tier |
564
- | [SGP4 validation](docs/SGP4-VALIDATION.md) | reviewers / citers | agreement with the AIAA 2006-6753 reference (666 states, ~4 mm) |
607
+ | [SGP4 validation](docs/SGP4-VALIDATION.md) | reviewers / citers | agreement with the AIAA 2006-6753 reference (666 states, ~4 mm) **and** a head-to-head against the independent `sgp4` crate (agree to sub-micron / 4.12 mm) |
565
608
  | [Changelog](CHANGELOG.md) | everyone | released history (Keep a Changelog + SemVer) |
566
609
  | [Contributing](CONTRIBUTING.md) | contributors | build, guards, test/citation discipline, DCO |
567
610
  | [Code of Conduct](CODE_OF_CONDUCT.md) | community | expected conduct (Contributor Covenant) |
@@ -670,7 +713,7 @@ entry for every user-visible change. Participation is governed by our
670
713
 
671
714
  If you use Kshana in academic or technical work, please cite it. Machine-readable
672
715
  metadata is in [`CITATION.cff`](CITATION.cff) (GitHub renders a "Cite this repository"
673
- button from it); cite the version you used (e.g. `v0.12.0`) together with the
716
+ button from it); cite the version you used (e.g. `v0.13.0`) together with the
674
717
  scenario and seed for full reproducibility. Every release is archived on Zenodo with
675
718
  a citable DOI — the concept DOI [10.5281/zenodo.20528627](https://doi.org/10.5281/zenodo.20528627)
676
719
  always resolves to the latest version.
package/kshana_bg.wasm CHANGED
Binary file
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "Chakshu Baweja <contact@ashforde.org>"
6
6
  ],
7
7
  "description": "Open, reproducible PNT-resilience simulator with quantum-sensor performance models",
8
- "version": "0.12.0",
8
+ "version": "0.13.0",
9
9
  "license": "Apache-2.0",
10
10
  "repository": {
11
11
  "type": "git",