Skip to content

Dynamics and pod#75

Open
VPRamon wants to merge 119 commits into
mainfrom
dynamics-and-pod
Open

Dynamics and pod#75
VPRamon wants to merge 119 commits into
mainfrom
dynamics-and-pod

Conversation

@VPRamon
Copy link
Copy Markdown
Member

@VPRamon VPRamon commented May 22, 2026

No description provided.

VPRamon added 30 commits May 10, 2026 13:55
…tate

Promote the spacecraft-state primitives that lived in siderust-pod-core
into siderust itself, where they are no longer POD-specific:

- New module siderust::astro::dynamics with submodule state.
- OrbitState, Position, Velocity, Acceleration aliases parameterised by
  frame and unit, defaulting to GCRS / km / km·s^-1 / km·s^-2.
- StateDerivative now carries typed Velocity and Acceleration vectors
  instead of raw [f64;3] arrays. rk4_combine, scaled, add are
  expressed via affn vector ops.
- A transitional StateDerivative::from_components([f64;3],[f64;3]) shim
  exists for callers (force models, integrators) that will be ported
  to typed acceleration in Phase 4.
- SpacecraftProperties / SpacecraftState moved alongside.

The motivating gap is documented in siderust's own README and
frames_and_centers.md; this commit closes the state-primitive part.
…frames

Promote the RTN, VNC, and LVLH local orbital frames into siderust as
state-tagged typed objects. Previously these lived in
siderust-pod-core::frames as ad-hoc ZSTs, which siderust's own
frames_and_centers.md flagged as a missing first-class concept.

The new API is orbit-relative rather than a set of global ZSTs:

- RTN, VNC, LVLH are zero-sized ReferenceFrame markers used purely as
  type tags on Displacement<M, U>.
- LocalOrbitalFrame<M> captures the GCRS->M rotation for one
  OrbitState. Build it once via LocalOrbitalFrame::<RTN>::from_state
  (or VNC / LVLH) and call to_local / to_inertial to rotate many
  vectors without rebuilding the basis.
- rotation() / rotation_inverse() expose the underlying Rotation3 for
  callers (covariance transport, STM) that operate on the matrix
  directly.
…teCovariance

Add a typed 6×6 Cartesian state covariance carrier and the standard
inertial<->local transport that siderust-pod-core::covariance previously
implemented as untyped Covariance6 free functions.

- StateCovariance<F> is a frame-parameterised wrapper around a 6×6
  matrix (block layout [Prr Prv; Pvr Pvv]), so an inertial covariance
  cannot be accidentally mixed with an RTN/VNC/LVLH one.
- transform_into::<M>(&LocalOrbitalFrame<M>) and
  transform_into_inertial(&LocalOrbitalFrame<M>) implement the
  block-diagonal similarity T = blockdiag(R, R), reusing the rotation
  captured by the typed local frame from Phase 2.
- block_diag, similarity, and the row-major Covariance6 alias are
  exposed for callers that operate on the raw matrix.

The Rdot rate term is intentionally omitted; the rate-aware variant
remains follow-up work, as documented.
Promote the textbook satellite-mechanics force models and propagators
from siderust-pod-dynamics into siderust:

- New `astro::dynamics::forces` exposes a typed `ForceModel` trait
  whose `acceleration` returns `Acceleration<GCRS, AccelerationUnit>`
  instead of a raw `[f64; 3]`.  Includes `CompositeForce`, `TwoBody`,
  and `J2`.
- New `astro::dynamics::integrators` exposes typed `rk4_step`,
  `rk4_propagate`, `rk4_propagate_series`, `dopri5_step`,
  `dopri5_propagate`, and the `Tolerance` config.  Both integrators
  consume the upstream typed `ForceModel` and operate on typed
  `OrbitState` / `StateDerivative` values directly.

Update README and `doc/frames_and_centers.md` to reflect that local
orbital frames and covariance transport are now first-class.
- Add siderust::astro::dynamics::atmosphere with DensityProvider
  trait, ExponentialAtmosphere, and ConstantDensity.
- Add siderust::astro::dynamics::gravity with GravityFieldProvider
  trait, GravityConstants, and TwoBodyEarth.
- Add lod field (Seconds) to EopValues; populate from tempoch's
  lod_milliseconds when reading bundled IERS data.
- Expose both new modules from astro::dynamics::mod.
Move DragForce<D: DensityProvider>, ExponentialDrag type alias, and the
Earth-body constants R_EARTH_KM / OMEGA_EARTH_RAD_S from siderust-pod-dynamics
into siderust::astro::dynamics::forces.

- Add pub const R_EARTH_KM and OMEGA_EARTH_RAD_S to forces.rs.
- Use R_EARTH_KM in J2::earth() instead of an inline literal.
- Add DragForce<D> struct and ForceModel impl (identical logic, no raw-value
  changes; [f64;3] intermediate arrays are acceptable for this hot path).
- Add ExponentialDrag type alias.
- Port two drag tests into the siderust forces test module.

siderust-pod drag.rs becomes a 6-line re-export shim.
All 681 siderust tests + all pod tests pass.
ThirdBodySunMoon and CannonballSrp are satellite perturbation models that
belong in siderust, not siderust-pod. Both depend only on DynEphemeris,
OrbitState, and ecliptic_of_date_to_mean_equatorial_matrix, which are
already canonical siderust types.

- Add MU_SUN_KM3_S2, MU_MOON_KM3_S2, AU_KM, P0_N_M2 as pub consts in
  siderust::astro::dynamics::forces
- Add ThirdBodySunMoon, CannonballSrp, norm3 helper in forces.rs
- Add 3 new tests: third_body_nonzero_acceleration,
  srp_order_of_magnitude_at_leo, srp_zero_when_area_is_zero
- forces tests: 7/7 pass
Move finite_diff_stm and finite_diff_stm_series from siderust-pod-dynamics
into siderust::astro::dynamics::stm. Both functions are generic propagation
tooling with no POD-specific dependencies.

- Add pub type Stm6 = [[f64; 6]; 6] as a named alias for the 6×6 Jacobian
- Add finite_diff_stm and finite_diff_stm_series using central differences
  with RK4 propagation; relative perturbation h = 1e-6 * max(|x₀ⱼ|, 1)
- Re-export Stm6, finite_diff_stm, finite_diff_stm_series from
  siderust::astro::dynamics
- Add 2 tests: identity at zero steps, series first element is identity
…ers and improve code clarity

- Introduced a new `units.rs` file to define typed unit aliases for gravitational parameters.
- Replaced `f64` representations of gravitational parameters with the new `GravitationalParameter` type.
- Updated constants for Earth, Sun, and Moon gravitational parameters to use the new type.
- Modified various structs and functions in the dynamics module to utilize the new typed units, enhancing type safety and readability.
- Adjusted the `advance` method in `OrbitState` to accept `Second` type for time steps.
- Updated integrators (RK4 and DOPRI5) to work with the new `Second` type for time steps.
- Refactored tests to align with the new unit types and ensure correctness.
- Replace from_stddevs([f64;3],[f64;3]) with typed diagonal_from_sigmas
  (Kilometers, Quantity<KmPerSecond>) on StateCovariance
- Add from_block_components/from_blocks constructors
- Add rotate_by(&Rotation3) for block-diagonal rotation (TODO: upgrade to
  BlockDiagRotation6 once affn git ref is updated past a3664ef)
- Add ProcessNoise<F> with zero(), diagonal_from_sigmas(), add_to()
- Add is_symmetric(RelativeTolerance), is_positive_semidefinite(RelativeTolerance),
  symmetrise_in_place() with manual Cholesky PSD check
- Re-export ProcessNoise from astro::dynamics mod
- 15 unit tests covering all new APIs (all pass)
- Add ForcePartials<F> with zero(), two_body(), add(), add_in_place()
  using manual FrameMatrix3 array arithmetic (no missing ops assumed)
- Add generic ForceModel<C, F> trait with where C: ReferenceCenter,
  F: ReferenceFrame bounds; acceleration returns Result<_, DynamicsError>;
  partials() has a default Err impl
- Update all force models: CompositeForce<C,F>, TwoBody, J2, DragForce,
  ThirdBodySunMoon (unit struct, ctx-sourced ephemeris), CannonballSrp
- Add typed field aliases: J2Coefficient, DragCoefficient, AreaToMass,
  SrpCoefficient replacing raw f64 fields
- Thread DynamicsContext through rk4, dopri5, stm; all return Result
- Replace integrators::Tolerance with qtty::IntegratorTolerances
- Re-export J2Coefficient and IntegratorTolerances from siderust::qtty
- Fix drag_decays_orbit_altitude test to use 360 steps (3 h) so the
  satellite stays above the surface with the aggressive test density
…n driver

- Added DOP853 integrator for high-precision adaptive step size control in orbit propagation.
- Introduced PropagatorConfig for high-level configuration of propagation parameters.
- Created a generic propagation driver that utilizes the DOP853 integrator and supports event detection.
- Implemented event detection for altitude crossings with customizable terminal behavior.
- Added error handling specific to the propagation process, including step control and event evaluation errors.
- Defined result structures to encapsulate propagation outcomes and event occurrences.
- Included tests to validate the functionality and accuracy of the DOP853 integrator and propagation driver.
…rdBodyProvider

- Introduce ThirdBodyProvider trait for extensible third-body perturbation models
- Add built-in SunPerturbation and MoonPerturbation providers
- Implement ThirdBody struct with builder API (.with_sun(), .with_moon(), .with())
- Use Battin's numerically-stable formula to avoid catastrophic cancellation:
    q = r_s·(r_s − 2r_b) / |r_b|²
    F(q) = q·(3 + 3q + q²) / (1 + √(1+q)³)
    a = −μ·(r_b·F(q) + r_s) / (|r_b|³·(1+F(q)))
- Deprecate ThirdBodySunMoon as a type alias pointing to ThirdBody
- Export ThirdBody, ThirdBodyProvider, SunPerturbation, MoonPerturbation from forces::*
- 10 tests: Battin vs naive accuracy (< 1e-10 relative), edge cases, builders
… Nrlmsise00LiteApprox

- Extend DensityProvider trait: add name(), change density() to return
  Result<KilogramsPerCubicMeter, DynamicsError>
- Add AtmosphereProvider type alias (dyn DensityProvider + Send + Sync)
- Update ExponentialAtmosphere and ConstantDensity to return Result;
  ExponentialAtmosphere now errors on altitude < 0
- Add Nrlmsise00LiteApprox: log-linear table model, F10.7=140, 50–1000 km,
  accuracy ±50 % under mean conditions (teaching/regression quality)
- Add geodetic_altitude(): Bowring (1985) iterative method, WGS-84, 3 iterations;
  placeholder identity GCRS↔ITRF rotation (error ≤20 km at poles)
- Rewrite DragForce as non-generic; reads density from ctx.require_atmosphere()
- Add omega_earth: Vector<GCRS, InverseSecond> typed field (default IAU ω_⊕)
- Implement rotating-atmosphere correction via ω × r cross product
- Add DragForce::new() and DragForce::with_omega() constructors
- ExponentialDrag = DragForce type alias (API compatibility, no longer generic)
- Re-export ExponentialAtmosphere and Nrlmsise00LiteApprox from forces/mod.rs
- Add tests: no-provider error, drag direction, below-surface error,
  rotating-atmosphere fractional change, orbit decay, NRLMSISE via context
Replace gravity.rs with a gravity/ module containing:

- gravity/provider.rs: updated GravityFieldProvider trait with gm(),
  reference_radius(), max_degree(), max_order(), c_normalized(), s_normalized();
  backward-compat default methods constants(), c_nm(), s_nm()

- gravity/egm_low_degree.rs: TwoBodyEarth (n=0) and LowDegreeEarth (n=0..4)
  with hardcoded EGM2008 normalised Stokes coefficients; C̄₂₀ pinned to
  -J2/√5 (J2 = 1.082_626_68e-3) to match J2 force model exactly

- gravity/acceleration.rs: geopotential_acceleration() kernel using
  spherical-coordinate gradient over fully-normalised P̄_nm; verified
  against analytic two-body and J2 formulas

- forces/geopotential.rs: Geopotential { degree, order } ForceModel
  calling ctx.require_gravity_field() and geopotential_acceleration()

- errors.rs: add GravityFieldUnavailable and GeopotentialDegreeOutOfRange
  variants with Display and source() impl

- context.rs: add require_gravity_field() returning GravityFieldUnavailable
Implements analytic state-transition matrix (STM) propagation via
variational equations, integrated with classical fixed-step RK4.

New module: src/astro/dynamics/variational/

- equations.rs: build_a_matrix, mat6_mul/add/scale, identity_6x6,
  variational_derivative — assembles the 6×6 dynamics Jacobian
  A = [[0, I], [A_r, A_v]] and computes dΦ/dt = A·Φ.

- propagator.rs: propagate_stm (default 6 s step) and
  propagate_stm_with (explicit VariationalConfig), both jointly
  integrating the orbit state and STM through all four RK4 stages.
  StateTransitionMatrix<F> type alias for FrameMatrix6<F>.

- mod.rs: public re-exports.

Tests (all passing):
- identity_at_zero_time: Φ(t₀,t₀) = I to 1e-12
- propagate_stm_is_deterministic
- stm_determinant_near_one_two_body / _j2: |det Φ − 1| < 5e-3
- two_body_stm_agrees_with_fd: ‖Φδy₀ − δy(T)‖/‖δy(T)‖ < 1e-6
- j2_stm_agrees_with_fd: same, < 1e-6
- composite_stm_agrees_with_fd: TwoBody+J2, < 1e-5

Patches affn git dep to use local path for FrameMatrix6 support.
Fix all six defects in the DOP853 8th-order adaptive RK integrator:

1. Butcher tableau A-matrix (stages K9–K12):
   - a96:   2.722e1  → 2.759209969944671e1
   - a107:  1.531e1  → 1.527923363288242e1
   - a108: -3.324e1  → -3.328821096898486e1
   - a109: +8.1e-1   → -2.033120170850863e-2  (wrong sign & magnitude)
   - All of a111..a1110 (K11 row) replaced with Hairer/ode-solvers values
   - All of a121..a1211 (K12 row) replaced with Hairer/ode-solvers values
   Incorrect A-coefficients caused wrong intermediate stage evaluations,
   propagating into both d_new (solution) and err_d (error estimate).

2. Error coefficients er1–er12: replaced with canonical Hairer values
   (sum ≈ 0 as required by construction; er9 was -35.033 instead of -0.35033).

3. Second error vector: added err_bhh = d_new - bhh1*k1 - bhh2*k9 - bhh3*k12
   for PI-controller denominator stabilisation.

4. Error norm formula: replaced ad-hoc formula with Hairer's canonical
   err_norm = |h| * err_a * sqrt(1/(deno*6)) with deno = err_a + 0.01*err_b.

5. Step controller: corrected exponent to 1/8 (8th-order method), accept
   clamp to [1/6, 6], reject clamp to [1/6, 1].

6. Initial step: added Hairer p.169 hinit() algorithm; dop853_propagate
   now calls it instead of using an arbitrary fixed h.

Also re-enables the five previously #[ignore]d tests; all five now pass.
Removes temporary debug instrumentation.
…cate FD-STM

- Rename PropagatorConfig → PropagationConfig (low-level driver config) to
  free up the name for the new user-facing PropagatorConfig (integrator
  choice + tolerances + max_steps).
- Add IntegratorChoice enum (Rk4, Dopri5, Dop853) and PropagatorConfig.
- Add Propagator<C,F,FM> struct with:
  - new() — generic constructor
  - propagate() — dispatches to rk4_propagate / dopri5_propagate / dop853_propagate
  - propagate_with_stm() — delegates to variational::propagate_stm
  - propagate_with_events() — uses generic driver with FixedRk4Adapter
- Add FixedRk4Adapter: wraps a fixed step size as AdaptiveStepper<Geocentric,GCRS>
  so the event-capable driver can use RK4 without a specialized impl.
- Mark StateTransition<F>, finite_diff_stm, and finite_diff_stm_series in
  internal uses within the same module.
- Update propagation/mod.rs and dynamics/mod.rs re-exports.
- Add variational::propagate_stm and StateTransitionMatrix to dynamics re-exports.
- Add 5 tests: RK4/DOPRI5/DOP853 orbit closure, STM identity at dt=0, and
  altitude event detection on a perturbed orbit.

All 155 dynamics tests pass; clippy clean with -D warnings.
- Fix failing test propagate_with_events_altitude_event_fires: trigger
  altitude was below periapsis (628 km → 750 km) so the orbit never crossed
  the event surface; changed to 750 km (r=7121 km, between peri/apogee).

- Add targeted unit tests to 14 files that were below 90%:
    forces/composite.rs       (0 → 100%)
    forces/geopotential.rs    (84 → 99%)
    forces/srp.rs             (78 → 99.7%)
    forces/traits.rs          (55 → 95%)
    gravity/provider.rs       (0 → 97%)
    integrators/dopri5.rs     (86 → 97%)
    integrators/rk4.rs        (90 → 100%)
    propagation/config.rs     (59 → 100%)
    propagation/driver.rs     (73 → 96%)
    propagation/error.rs      (0 → 100%)
    propagation/events.rs     (77 → 95%)
    propagation/propagator.rs (84 → 99.5%)
    state.rs                  (90 → 99.6%)
    stm.rs                    (89 → 99.6%)

- All test code is in #[cfg(test)] blocks; no public API changes.

- Add scripts/check_dynamics_coverage.sh: CI enforcement script that runs
  cargo llvm-cov, parses the JSON report, and exits 1 if any dynamics file
  falls below 90% line coverage.

- Append Coverage section to src/astro/dynamics/README.md documenting the
  gate and how to run the script.

Result: 222 tests pass, 0 failed; all 32 dynamics files ≥ 90% line coverage.
- Added `dynamics.rs` module for spacecraft dynamics context, orbit states, and propagators.
- Introduced `SiderustDynamicsStatus` for error handling in dynamics functions.
- Implemented FFI functions for creating and managing dynamics contexts, orbit states, and two-body propagators.
- Added C-callback vtables for atmosphere density and gravity field providers.
- Created regression tests for the dynamics FFI surface, validating lifecycle and propagation accuracy.
- Updated `lib.rs` to include the new `dynamics` module.
- Added tests for dynamics context creation, orbit state management, and propagation accuracy.
- Fixed minor issues in `qtty` module exports.
- Improved the structure and readability of the `c_normalized` and `s_normalized` methods in `GravityFieldProvider` implementations.
- Updated the `dopri5` and `dop853` integrators to include step rejection counts in their return values, enhancing error handling and diagnostics.
- Added linear interpolation for state estimation during event crossings in the propagation driver.
- Adjusted the propagation configuration to handle minimum and maximum step sizes more effectively.
- Enhanced test coverage for various propagation scenarios, ensuring robustness against edge cases.
- Cleaned up code formatting and organization across multiple modules for better maintainability.
…oblem

- Added `lambert` module with typed entry points for solving Lambert's problem.
- Implemented `lambert` and `lambert_n_rev` functions for single and multi-revolution transfers.
- Introduced `TypedLambertSolution` struct to encapsulate results and diagnostics.
- Created low-level numeric backend functions `solve_lambert` and `solve_lambert_n_rev` for raw array inputs.
- Updated `astro` module to include the new `lambert` module.
- Refactored orbit calculations to utilize new Lambert solver where applicable.
- Added tests for frame bias rotations between GCRS/ICRS and EME2000.
    - Bump qtty 0.7 → 0.8 and tempoch 0.4 → 0.5 (with tempoch-ffi) in all Cargo.tomls
    - Add [patch.crates-io] pointing to local tempoch 0.5 path
    - Update API usage throughout:
      - EncodedTime::new(f64) → from_raw_unchecked(qtty::Day::new(f64))
      - .jd_value()/.mjd_value() → .raw().value()
      - EncodedTime arithmetic (±Quantity, subtraction) → raw-value operations
      - .julian_millennias() → manual (raw - 2451545) / 365250 formula
      - RepresentationForScale → FormatForScale
      - InfallibleRepresentationForScale → InfallibleFormatForScale
      - J2000_TT → J2000 const from raw value
    - Add JD, MJD, JulianDate/ModifiedJulianDate generic aliases to time.rs
    - Add UT1 re-export to time.rs
VPRamon added 29 commits May 31, 2026 11:47
Add targeted unit tests to reach 90.08% line coverage (up from 86.41%):

- errors.rs: full variant coverage for all dynamics error types
- srp.rs: cylindrical/conical shadow factors, eclipse model impls, CannonballSrp
- opm.rs: OPM read/write roundtrip including Keplerian block
- tdm.rs: TDM roundtrip for all observation types
- orbex.rs: ORB/CLK/ATT entries, velocity, short-record strict/permissive
- adsb/mod.rs: identification decode (TC=4), velocity decode, wrong-TC errors
- nonlinear.rs: Gauss-Newton convergence, validation error paths
- noise.rs: process noise error paths and matrix_is_psd branches
- stars.rs: Star builder API, Trackable impl, position_at
- registry.rs: all shadow models, empirical variants, batch force build

Fix test data bugs:
- orbex.rs: use [].join("\n") instead of \n\ continuation (was stripping leading spaces)
- adsb/mod.rs: replace invalid-CRC IDENT_FRAME with CRC-verified TC=4 frame
- nonlinear.rs: set tol_chi2_rel=2.0 so iter-2 chi2_rel=1.0 satisfies convergence
… module

- Added `TerrainMask` struct for piece-wise linear terrain-mask elevation profiles, including methods for elevation retrieval and mask clearance checks.
- Introduced `Location` struct to represent observation sites with optional terrain masks.
- Created a new `mod.rs` file for mission analysis building blocks, organizing related modules.
- Removed the old `mission_geometry.rs` file to streamline the codebase and improve modularity.
- Updated tests to validate new terrain masking and location functionalities.
- Refactored code for improved readability and maintainability, including consistent formatting and error handling.
… catalogs/

- Merge src/qtty/{mod,dimensionless}.rs into flat src/qtty.rs (no API changes)
- Replace src/catalogs.rs + src/observatories/ with src/catalogs/ module dir:
  - record.rs: CatalogRecord with typed Radians/MilliArcseconds/KmPerSeconds fields
  - catalog.rs: LargeStarCatalog with typed cone_search* API
  - ingest.rs: parse_csv_chunk / CatalogIngestError
  - observatories.rs: Observatory struct + ROQUE, EL_PARANAL, MAUNA_KEA, LA_SILLA
    (upgrade MAUNA_KEA and LA_SILLA_OBSERVATORY from bare Geodetic to Observatory)
- Remove pub mod observatories from lib.rs; public path is now catalogs::observatories
- Update 4 call-site files (moon_cache, altitude_periods, example, integration test)
- All 294 tests pass
- Fixed N-body solver convergence precision (three bugs):
  * omega now uses true angular velocity z_norm/d² instead of the
    circular-orbit approximation sqrt(GM/r³), which diverged by ±3.4%
    over Earth's elliptical orbit shifting the pseudo-equilibrium by
    thousands of km in the soft y/z directions
  * RESIDUAL_TOL_KM_S2 tightened from 1e-9 to 1e-14 (previously
    allowing up to 8,475 km positional error in the y-direction at L1
    because |Ω_yy| ≈ 1.18e-13 s⁻² is very soft)
  * Removed backward seed propagation from fit_with_order and
    validate_fit — passing the previous position as seed caused
    Newton overshoots at non-monotone Chebyshev nodes
- Added best-effort convergence fallback for L3/L4/L5 saddle/triangular
  points where Newton oscillates over the shallow effective-potential
  direction; residuals below a practical threshold (1e-6 km/s²) are now
  returned as Ok instead of DidNotConverge
- Rewrote generate-lagrange-cheby binary to produce SCK (Siderust
  Chebyshev Kernel v1) binary files and manifest.toml per point
- L1 and L2 now converge to < 100 m max error (87 m and 63 m); L3/L4/L5
  are skipped with a warning (require a more robust trust-region solver)
- Added FIT_FROM_JD and FIT_TO_JD constants to the lagrange public API
- All 981 unit tests pass; cargo clippy and cargo fmt clean
Phase 5/6/7/8 of the archive migration plan (plans/archive-plan.md):

- New Cargo features: archive-data (build-time manifest parsing),
  embedded-data, generated-tables, external-data. Default builds
  remain lightweight and ignore the archive submodule.
- build.rs now emits OUT_DIR/archive_registry.rs from
  archive/MANIFEST.toml (or an empty stub if archive-data is off /
  submodule is absent), with cargo:rerun-if-changed wired up for the
  top-level and per-family manifests. Datasets are never regenerated
  during a normal build.
- New module siderust::data::archive exposes ARCHIVE_ENTRIES, the
  ArchiveEntry struct (family, dataset_id, kind, paths, validity,
  checksum), and a lookup_family helper.
- New module siderust::formats::sck reads Siderust Chebyshev Kernel
  v1 binary files generated by the Lagrange generator.
- The Lagrange generator accepts --block-days and writes a manifest
  alongside the SCK payloads in the archive lagrange directory.
- Cargo.toml registers `toml` (optional, parse-only) for runtime
  registry assembly and as a build dependency.

Verified with cargo fmt, cargo clippy --all-targets --all-features
(no warnings), cargo test --lib (980 default / 1184 all-features),
and cargo build --features archive-data.
…archive SCK

- Delete src/data/compiled/lagrange/mod.rs (296,825 lines; 5×59,358-float
  RECORDS_L{1..5} arrays). Replace with five binary SCK kernels at
  archive/lagrange/vsop87/l{1..5}.sck (~475 KB each, 2283 records per file,
  full 1900-2100 coverage, max error ≤ 1.12 m). Kernels are embedded via
  include_bytes! in the new src/ephemeris/lagrange/embedded.rs and parsed
  lazily on first access through std::sync::LazyLock.

- Delete src/data/compiled/{vsop87a,vsop87e,elp_data,nut00a_tables,pluto_tables}.rs
  and move each file next to its sole consumer:
    src/ephemeris/vsop87/vsop87a_data.rs     (was vsop87a.rs)
    src/ephemeris/vsop87/vsop87e_data.rs     (was vsop87e.rs)
    src/ephemeris/elp2000/elp_data.rs        (was elp_data.rs)
    src/astro/nutation/nut00a_tables.rs      (was nut00a_tables.rs)
    src/ephemeris/pluto_tables.rs            (was pluto_tables.rs)

  crate::ephemeris::.

- Delete src/data/source/lagrange/ (superseded by archive manifest).
- data::compiled now contains only the feature-gated JPL DE sub-modules.
- Update archive/lagrange/vsop87/manifest.toml with full-range checksums,
  ncoeff=8, 2283 records, and all five Lagrange points (L1-L5).
- Update CHANGELOG [Unreleased] with migration notes.
- checksum.rs → src/checksum.rs (top-level pub mod)
- archive.rs  → src/archive.rs  (top-level pub mod)
- catalog.rs + runtime/ → src/datasets/ (new pub mod)
- compiled/jpl/ → src/ephemeris/jpl/jpl_data/ (co-located)
- provenance.rs deleted; consumers use optica::data::{Provenance,DataSource} directly
- file/o3trans.dat → src/atmosphere/o3trans.dat
- file/passbands/ → src/photometry/passbands/bessell1990/
- Update examples/12_runtime_ephemeris.rs: siderust::data → siderust::datasets
- Update CHANGELOG [Unreleased] with dissolution notes

All 302 tests pass, cargo fmt + clippy clean.
Point the archive submodule at the new commit that introduces the shared
siderust-archive-data crate (manifests, checksums, provenance, runtime IERS
time-data download) and the archive/time/eop dataset. Document under
[Unreleased].
- Remove archive/ git submodule and .gitmodules. The reusable
  siderust-archive crate (renamed from siderust-archive-data) is now
  published independently on crates.io.
- build.rs: archive root resolution order is now
    1. $SIDERUST_ARCHIVE_ROOT (if it contains MANIFEST.toml),
    2. ./archive/,
    3. ../archive/.
  When archive-data is enabled but none is found, build emits an actionable
  cargo:warning instead of the former "git submodule update --init --recursive".
- build.rs: emit OUT_DIR/lagrange_paths.rs that declares
  L1_BYTES..L5_BYTES via include_bytes! pointing at the resolved archive.
  If lagrange-centers is enabled but the SCK kernels are missing, build emits
  a compile_error! with an actionable message.
- src/ephemeris/lagrange/embedded.rs: include the generated paths file
  instead of hard-coding $CARGO_MANIFEST_DIR/archive/lagrange/vsop87/.
- Regenerated siderust-ffi C header to add SGP4/TLE opaque types (cbindgen,
  unrelated drift picked up by full test build).
- All tests pass (cargo test --all with SIDERUST_ARCHIVE_ROOT set). fmt +
  clippy clean.
- CHANGELOG.md updated under [unreleased].
- Updated documentation in `src/formats/mod.rs` to reference the `siderust_archive` crate for dataset catalog information.
- Changed error handling in `src/formats/spice/error.rs` to use `siderust_archive::ArchiveError` instead of `crate::datasets::DatasetError`.
- Modified `src/lib.rs` to remove references to the `datasets` module and clarify the role of the `formats` module.
- Simplified tests in `tests/test_ephemeris.rs` by removing deprecated DE440 tests and updating comments regarding runtime ephemeris.
- Cleaned up `tests/test_high_precision_earth_rotation_regression.rs` by removing unused `NullEop` path comparisons.
- Added `pipeline.rs` to orchestrate the VSOP87 build process, integrating data collection, code generation, and output stages.
- Introduced `collect.rs` for parsing VSOP87 data files and building an in-memory `VersionMap`.
- Created `codegen.rs` to generate Rust source code from the collected data, including provenance information.
- Implemented `io.rs` for writing generated code to the output directory.
- Added SHA-256 verification for dataset integrity during regeneration.
- Included utility functions for handling empty directories and generating ISO-8601 timestamps.
- Introduced `elp/pipeline.rs` for ELP2000 dataset processing, including SHA-256 fingerprinting and Rust code generation.
- Deleted `collect.rs`, `io.rs`, and `pipeline.rs` as they are no longer needed for the VSOP87 data processing pipeline.
- Updated `04_all_center_conversions.rs` example to include Sun-Earth Lagrange center shifts when built with `lagrange-centers` feature.
- Removed the deprecated `update_generated_tables.sh` script, directing users to the new `siderust-archive` repository for dataset management.
- Adjusted `eop.rs` to clarify that the IERS EOP provider now loads data at runtime via `tempoch`.
- Refined `embedded.rs` to reflect changes in how Sun-Earth Lagrange Chebyshev kernels are loaded and parsed.
- Updated documentation in `mod.rs` and `lib.rs` to clarify crate composition and dataset handling.
- Enhanced `time.rs` documentation to emphasize its role as a facade over `tempoch`, detailing the re-exported types and their usage.
- Deleted the JPL pipeline implementation in `scripts/jpl/pipeline.rs` and the SPK segment reader in `scripts/jpl/spk.rs`.
- Removed the Lagrange Chebyshev generation script in `scripts/lagrange/generate-lagrange-cheby.rs`.
- Eliminated the dataset prefetching script `scripts/prefetch_datasets.sh`.
- Removed the script for publishing changed packages `scripts/publish-changed.sh`.
- Deleted the deprecated script for updating generated tables `scripts/update_generated_tables.sh`.
- Updated the `Cargo.toml` for `siderust-ffi` to reference the local path for `siderust-archive`.
- Enhanced documentation in `src/checksum.rs`, `src/formats/spice/daf.rs`, and `src/formats/spice/spk.rs` to clarify the separation of runtime and build-time functionalities.
- Enhanced documentation for Earth rotation helpers, clarifying the distinction between UT1/UTC Julian Dates and TT.
- Introduced error handling in `try_jd_utc_from_tt` to return `EopError::NoData` when no runtime EOP bundle is available.
- Updated `jd_utc_from_tt` to use the new `try_jd_utc_from_tt` function, ensuring proper error handling.
- Modified `AstroContext` and `DynAstroContext` to handle EOP lookups more robustly, falling back to ΔT when necessary.
- Replaced deprecated `JULIAN_YEAR_DAYS` with `qtty::time::JULIAN_YEAR` in various modules, ensuring consistency and clarity.
- Adjusted tests to reflect changes in EOP handling and the new Julian year constant usage.
- Updated `tempoch` and `tempoch-ffi` dependencies to version 0.6.3 in Cargo.toml files.
- Removed unused dependencies and cleaned up Cargo.lock.
- Revised documentation in datasets.md to clarify dataset management and runtime acquisition.
- Updated FFI header to support C++20 features and improve compatibility.
- Refactored runtime ephemeris handling to utilize new JPL dataset management.
- Enhanced IERS data documentation to reflect runtime loading from `tempoch`.
- Clarified context for astronomical transformations and EOP data usage.
@VPRamon VPRamon force-pushed the dynamics-and-pod branch from 4a4c3cf to dfe56bc Compare May 31, 2026 09:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant