72 lines
2.9 KiB
Rust
72 lines
2.9 KiB
Rust
//! This crate's propagator against Orekit's, on the fixtures in `tests/fixtures/orekit`.
|
|
//!
|
|
//! Generated by `scripts/generate-orekit-fixtures.sh`. Each fixture records the setup
|
|
//! Orekit was given, so a disagreement can be attributed to the models rather than left
|
|
//! as a mystery; see `tests/common/mod.rs` for what has to match and why.
|
|
//!
|
|
//! The only fixture so far is a point mass. That is deliberate as a first step: with no
|
|
//! field, no third body, no atmosphere and an inertial frame, there is nothing left to
|
|
//! mismatch, so the figure it produces measures the comparison itself — frames, time
|
|
//! scale, units and `mu` — rather than any model. Anything added after this is measured
|
|
//! against a harness already known to be sound.
|
|
|
|
mod common;
|
|
|
|
use astrokit::prelude::*;
|
|
use common::ReferenceArc;
|
|
use nalgebra::Vector3;
|
|
use std::path::Path;
|
|
|
|
/// Propagates the fixture's initial state with this crate and returns the worst position
|
|
/// and velocity disagreement over the arc.
|
|
fn compare(arc: &ReferenceArc, forces: &[Dynamics]) -> (f64, f64) {
|
|
let start = &arc.states[0];
|
|
let epoch = Epoch::from_gregorian_utc_hms(2026, 1, 1, 0, 0, 0);
|
|
let mut propagation = Propagation::new(
|
|
epoch,
|
|
Orbit
|
|
.with_position(Vector3::from_column_slice(&start.position))
|
|
.with_velocity(Vector3::from_column_slice(&start.velocity)),
|
|
forces,
|
|
)
|
|
.frame(Frame::EARTH_J2000)
|
|
.duration(Duration::from_seconds(arc.duration()))
|
|
.accuracy(Accuracy::High);
|
|
|
|
let solution = propagation.run();
|
|
let (mut worst_position, mut worst_velocity) = (0.0_f64, 0.0_f64);
|
|
for state in &arc.states {
|
|
let ours = Orbit.state(solution.interpolate(state.elapsed));
|
|
worst_position = worst_position
|
|
.max((ours.position() - Vector3::from_column_slice(&state.position)).norm());
|
|
worst_velocity = worst_velocity
|
|
.max((ours.velocity() - Vector3::from_column_slice(&state.velocity)).norm());
|
|
}
|
|
(worst_position, worst_velocity)
|
|
}
|
|
|
|
#[test]
|
|
fn test_a_point_mass_arc_agrees_with_orekit() {
|
|
let path = Path::new("tests/fixtures/orekit/two-body-low-earth.json");
|
|
let arc = ReferenceArc::load(path).expect("the fixture is committed");
|
|
|
|
assert_eq!(arc.setup.tool, "orekit");
|
|
assert_eq!(arc.duration(), 86400.0);
|
|
assert_eq!(arc.states.len(), 1441);
|
|
|
|
let (position, velocity) = compare(&arc, &[TwoBody { body: Body::EARTH }]);
|
|
|
|
// Sub-millimeter over a day. Nothing in this case can disagree except the two
|
|
// integrators and the arithmetic, so this is the floor the comparison can measure to:
|
|
// a later fixture that disagrees by more than this is disagreeing about physics.
|
|
assert!(
|
|
position < 1.0e-3,
|
|
"worst position disagreement {position:.3e} m over the day"
|
|
);
|
|
assert!(
|
|
velocity < 1.0e-6,
|
|
"worst velocity disagreement {velocity:.3e} m/s over the day"
|
|
);
|
|
println!("point mass: {position:.3e} m, {velocity:.3e} m/s");
|
|
}
|