Expand description
§Outfit
Outfit is a modern Rust library for orbit determination and propagation of small Solar System bodies.
It provides a memory-safe, modular, and extensible implementation of algorithms that transform raw astrometric observations into orbital solutions, and propagate them through time.
§Why Outfit?
- Safe Rust: strong typing, memory safety, and explicit error handling.
- Modular: interchangeable ephemerides, error models, and IOD algorithms.
- Scientific grounding: consistent with established astronomical standards.
- Scalable workflows: designed for survey-scale batch processing.
§Features
- Initial Orbit Determination (IOD):
- Classical Gauss method for three observations.
- Orbital elements:
- Classical Keplerian elements,
- Equinoctial elements with conversions and two-body solver.
- Reference frames & preprocessing:
- Precession, nutation (IAU 1980), aberration, and light-time correction,
- Ecliptic ↔ equatorial conversions, RA/DEC parsing, time systems.
- Ephemerides:
- Built-in support for JPL DE440 (NAIF/SPICE kernels and Horizons format).
- Observation I/O:
- MPC 80-column, ADES XML, and Parquet (batch) readers,
- Optimized batched loading, automatic per-observer error assignments.
- Observer management:
- Build from MPC observatory code or custom geodetic coordinates.
- Residuals & quality metrics:
- RMS computation of normalized astrometric residuals, filtering utilities.
- Examples & benches:
- End-to-end examples in
examples/, Criterion benchmarks for IOD.
- End-to-end examples in
- Parallel IOD (feature
parallel):- Batched multi-core execution via Rayon,
optional global progress bar when combined with the
progressfeature.
- Batched multi-core execution via Rayon,
optional global progress bar when combined with the
§Planned extensions
- Vaisalä method for short arcs,
- Full support for hyperbolic trajectories,
§Workflow at a Glance
- Load observations (MPC/ADES/Parquet).
- Initialize an
Outfitenvironment with JPL ephemerides. - Form triplets and run the Gauss IOD solver.
- Evaluate residuals (RMS) and select the best candidate.
- Propagate using Keplerian dynamics or convert to equinoctial elements as needed.
§Example (MPC 80-column)
use camino::Utf8Path;
use rand::{rngs::StdRng, SeedableRng};
use outfit::{Outfit, ErrorModel, IODParams};
use outfit::constants::ObjectNumber;
use outfit::TrajectorySet;
use outfit::prelude::*; // TrajectoryExt, ObservationIOD
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut env = Outfit::new("horizon:DE440", ErrorModel::FCCT14)?;
// Load observations (80-col MPC).
let mut trajs = TrajectorySet::new_from_80col(
&mut env,
Utf8Path::new("tests/data/2015AB.obs"),
);
trajs.add_from_80col(&mut env, Utf8Path::new("tests/data/8467.obs"));
// Select an object.
let obj = ObjectNumber::String("K09R05F".into());
let obs = trajs.get_mut(&obj).expect("object not found");
// Configure IOD.
let params = IODParams::builder()
.n_noise_realizations(10)
.noise_scale(1.1)
.max_obs_for_triplets(obs.len())
.max_triplets(30)
.build()?;
let mut rng = StdRng::seed_from_u64(42);
// Run Gauss IOD.
let (best_orbit, best_rms) = obs.estimate_best_orbit(
&mut env,
&ErrorModel::FCCT14,
&mut rng,
¶ms,
)?;
println!("Best orbit: {:?}", best_orbit);
println!("RMS: {}", best_rms);
Ok(())
}For more end-to-end flows, see the examples/ folder (e.g. parquet_to_orbit.rs).
§Example (Parallel batched IOD)
This example requires the parallel feature (and optionally progress for a global progress bar).
use camino::Utf8Path;
use rand::{rngs::StdRng, SeedableRng};
use outfit::{Outfit, ErrorModel, IODParams};
use outfit::constants::ObjectNumber;
use outfit::TrajectorySet;
use outfit::TrajectoryFit;
use outfit::prelude::*; // TrajectoryExt, ObservationIOD
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut env = Outfit::new("horizon:DE440", ErrorModel::FCCT14)?;
let test_data = "tests/data/test_from_fink.parquet";
let path_file = Utf8Path::new(test_data);
let ztf_observer = env.get_observer_from_mpc_code(&"I41".into());
let mut traj_set = TrajectorySet::new_from_parquet(
&mut env,
path_file,
ztf_observer,
0.5,
0.5,
None
)?;
let params = IODParams::builder()
.max_obs_for_triplets(12)
.n_noise_realizations(10)
.build()?;
let mut rng = StdRng::seed_from_u64(42);
let batch_size = 256; // tune for locality & memory
let results = traj_set.estimate_all_orbits_in_batches_parallel(&env, &mut rng, ¶ms, batch_size);
for (obj, res) in results {
match res {
Ok((gauss, rms)) => {
println!("{} → RMS = {rms:.4}", obj);
println!("{gauss}");
}
Err(e) => eprintln!("{} → error: {e}", obj),
}
}
Ok(())
}
Notes
- Batches are processed in parallel; each batch is handled sequentially to preserve cache locality.
- Per-object RNG seeds are deterministically derived from a single base seed.
- Set
RAYON_NUM_THREADS=Nto cap threads if needed.
§Data Formats
- MPC 80-column — standard fixed-width astrometry
https://minorplanetcenter.net/iau/info/OpticalObs.html - ADES XML — IAU’s Astrometric Data Exchange Standard
https://www.iau.org/static/science/scientific_bodies/commissions/f1/ADES-Specification.html - Parquet — columnar format for large batch processing (typical columns:
ra,dec,jd,trajectory_id)
https://parquet.apache.org/docs/
§Cargo Features
-
jpl-download
Automatically download JPL ephemerides (NAIF/Horizons) into a local cache.Cache layout (Linux):
~/.cache/outfit_cache/jpl_ephem/ ├── jpl_horizon/ │ └── DE440.bsp └── naif/ └── de440.bspThis feature enables some integration tests and pulls
reqwest,tokio,tokio-stream. -
progress(optional)
Enables lightweight progress bars (viaindicatif) and loop timing utilities for long-running jobs. -
parallel(optional)
Enables multi-core IOD via Rayon, exposingTrajectorySet::estimate_all_orbits_in_batches_parallel. Combine withprogressfor a thread-safe global progress bar.
[dependencies]
outfit = { version = "...", features = ["jpl-download"] }
# with progress indicators
outfit = { version = "...", features = ["jpl-download", "progress"] }
# with multi-core IOD
outfit = { version = "...", features = ["parallel"] }
# combine as needed
outfit = { version = "...", features = ["jpl-download", "progress", "parallel"] }§Error Handling
Outfit uses thiserror for descriptive error types and idiomatic Result<T, E> returns,
with transparent conversions via #[from] where appropriate.
§MSRV & Platforms
- Tested on stable Rust (see
Cargo.tomland CI for the current MSRV policy). - Linux/macOS are primary targets; Windows is expected to work but may have different I/O performance.
§Scientific Background
- Milani, A. & Gronchi, G. F. (2010), Theory of Orbit Determination, Cambridge University Press.
- The open-source OrbFit software suite.
§License
Distributed under the CeCILL-C license. See
LICENSE.
§Authors
Developed by FusRoman and contributors.
§Useful Modules (See also)
initial_orbit_determination— Gauss IOD and helpers.observations— Readers (MPC/ADES/Parquet) and trajectory utilities.observers— Observatory registry and geodetic utilities.jpl_ephem— Ephemerides backends (Horizons/NAIF).ref_system— Reference frame conversions and rotations.
Re-exports§
pub use crate::outfit::Outfit;pub use crate::constants::Observations;pub use crate::constants::ArcSec;pub use crate::constants::Degree;pub use crate::constants::ObjectNumber;pub use crate::constants::MJD;pub use crate::observers::Observer;pub use crate::trajectories::TrajectorySet;pub use crate::orbit_type::cometary_element::CometaryElements;pub use crate::orbit_type::equinoctial_element::EquinoctialElements;pub use crate::orbit_type::keplerian_element::KeplerianElements;pub use crate::orbit_type::OrbitalElements;pub use crate::error_models::ErrorModel;pub use crate::outfit_errors::OutfitError;pub use crate::initial_orbit_determination::gauss_result::GaussResult;pub use crate::initial_orbit_determination::IODParams;pub use crate::observations::display::ObservationsDisplayExt;pub use crate::observations::observations_ext::ObservationIOD;pub use crate::trajectories::trajectory_file::TrajectoryFile;pub use crate::trajectories::trajectory_fit::FullOrbitResult;pub use crate::trajectories::trajectory_fit::TrajectoryFit;pub use crate::constants::AU;pub use crate::constants::GAUSS_GRAV;pub use crate::constants::RADEG;pub use crate::constants::RADH;pub use crate::constants::RADSEC;pub use crate::constants::SECONDS_PER_DAY;pub use crate::constants::T2000;pub use crate::constants::VLIGHT_AU;pub use crate::jpl_ephem::JPLEphem;
Modules§
- constants
- Constants and astronomical unit conversions.
- conversion
- Coordinate conversions (RA/DEC, spherical ↔ cartesian, etc.).
- earth_
orientation - Earth orientation parameters and related corrections (nutation, precession).
- env_
state - Environment state: ephemerides, dynamical models, configuration.
- error_
models - Error models used for weighting astrometric residuals.
- initial_
orbit_ determination - Initial Orbit Determination algorithms (Gauss method).
- jpl_
ephem - JPL ephemerides management (Horizon/NAIF kernels). Unified access to JPL ephemerides (legacy DE binaries and NAIF SPK/DAF).
- kepler
- Keplerian solver for propagation.
- observations
- Observation handling (RA, DEC, times).
- observers
- Observers and observatory positions.
- orb_
elem - Orbital elements utilities (conversion, normalization).
- orbit_
type - Orbital types and conversions between them.
- outfit
- Main Outfit struct: central orchestrator for orbit determination.
- outfit_
errors - Errors returned by Outfit operations.
- prelude
- Prelude with common imports for quick-start users.
- ref_
system - Reference frame transformations.
- time
- Time management and conversions (UTC, TDB, TT).
- trajectories
- Trajectory management and file I/O.