empyrean-sys 0.9.0

Low-level FFI bindings to the libempyrean astrodynamics C ABI. For an ergonomic Rust API, use the empyrean crate.
Documentation

empyrean-sys

Low-level FFI bindings to the libempyrean astrodynamics C ABI


empyrean-sys exposes the C ABI of libempyrean to Rust as raw, unsafe, bindgen-generated declarations. It does not attempt to wrap, type-check, or RAII-manage the underlying handles.

[dependencies]
empyrean-sys = "0.9.0"
use empyrean_sys::*;

// All entry points are unsafe; pointer ownership and lifetime are the
// caller's responsibility. See include/empyrean.h at the repository
// root for the authoritative C ABI documentation.
unsafe {
    // Null data_dir = the platform default data directory; downloads
    // any missing kernels. Returns null on error (see empyrean_last_error).
    let ctx: *mut EmpyreanContext = empyrean_context_from_data_dir(std::ptr::null());
    assert!(!ctx.is_null());
    empyrean_context_free(ctx);
}

Most users want the safe wrapper instead — see the empyrean crate, which builds on empyrean-sys to provide typed handles, Result-returning entry points, and Rust-native lifetime management.

What the bindings cover

The declarations track the full C ABI at EMPYREAN_ABI_VERSION (currently 2), including the v0.9.0 wide-parameter fitting surface and the ABI-2 output surface below. ABI 2 grew existing struct shapes by appending fields, so consumers must recompile against the matching header. Each type below maps 1:1 onto a C struct; consult include/empyrean.h at the repository root for field-level semantics.

  • Wide-parameter OD. empyrean_determine / empyrean_refine solve beyond the 6-parameter state and the Marsden A1/A2/A3 non-gravitational block for the cometary outgassing time delay DT, the SRP area-to-mass ratio AMRAT, and per-segment thrust Δv corrections on continuous-thrust arcs — each partial produced analytically by the hyperdual integrator. The per-axis EmpyreanSolveFor (marsden / dt / amrat / thrust_segments) is read under EMPYREAN_SOLVE_FOR_EXPLICIT. DT / AMRAT / thrust are refine-path solves: the input orbit must carry the corresponding prior (its declared variance) to open the axis, and requesting an axis without its prior errors out rather than returning a zeroed or defaulted column.
  • Tagged solved covariance. EmpyreanSolvedCovariance carries the fitted-parameter identities alongside the matrix: marsden_slot, dt_slot, amrat_slot, and thrust_slots locate each parameter's row/column, with EMPYREAN_SLOT_NONE marking an axis that was not solved. Read a parameter's variance by its slot — the width alone is ambiguous.
  • Post-OD photometry. With EmpyreanODConfig::has_photometry set, EmpyreanPhotometryConfig requests a fit recovering absolute magnitude H and the phase-function slopes from the observation magnitudes, climbing the H-only → HG12 → HG1G2 ladder (Muinonen et al. 2010) to the richest model the arc's phase coverage supports. EmpyreanODPhotometryResult reports the fitted h / slope1 / slope2, the model_used, a 3×3 covariance giving an honest 1σ on h, plus n_mags_dropped_unconvertible and the distinct offending band codes in dropped_bands when magnitudes could not be converted to V — the observations' astrometry is unaffected.
  • Ephemeris covariances and warnings. Each EmpyreanEphemerisEntry carries a 6×6 sky-plane covariance over (rho, RA, Dec) and their rates in (AU, deg) units, and the aberrated (light-time corrected) barycentric ICRF Cartesian state at the photon-emission epoch with its own 6×6 covariance — has_covariance / has_aberrated_covariance gate each block (absent unless the input orbit carried a state covariance). EmpyreanEphemerisResult returns run-level non-fatal warnings, e.g. Earth-orientation kernel coverage gaps served by the analytic IAU 2006 fallback, or rows whose sensitivity chain was skipped.
  • Per-observation diagnostics. EmpyreanObservationResult carries radar delay/Doppler residuals (observed − predicted, seconds / hertz, with radar_chi2, radar_dof, radar_probability, and the combined radar_variance), the D-optimality influence_information_loss on removal (+∞ marks an indispensable observation), and along_cross_covariance_arcsec2 completing the 2×2 along/cross-track covariance.
  • Covariance trust verdict. EmpyreanODResult::covariance_trust reports an event-aware verdict on the delivered covariance (EMPYREAN_COVARIANCE_TRUST_*): TRUSTED, ENCOUNTER_INTERVENES (with the intervening close-approach or high-nonlinearity event and whether a second-order state-only correction can recover it), or WEAKLY_DETERMINED_HIGH_N. NOT_EVALUATED means no gate ran — absence of a verdict is not trust.
  • Impact-probability detail. Each EmpyreanImpactProbability row carries the geodetic impact point (latitude / longitude / altitude on the body's reference ellipsoid, when the surface projection is available), the Monte-Carlo 95% binomial confidence half-width on ip_mc, the second-order corrected mean miss distance with its 1σ uncertainty and skewness, the closest-approach distance gradient (6-vector) and distance_hessian (6×6) with respect to the initial state, and the adaptive Gaussian-mixture component count.
  • Plan evaluation. Radar candidates in EmpyreanPlanCandidate carry the effective SNR (linear power ratio), one-way range (km), link-budget provenance notes, and the measurement mode; EmpyreanPlanResult carries the predicted optical ephemeris (epoch MJD TDB, RA, Dec per optical candidate).
  • Basis-tagged mixture components. Each EmpyreanMixtureComponent is tagged with the reference frame and center-body origin (NAIF id) its mean and covariance are expressed in.

Runtime requirement

empyrean-sys opens libempyrean.{dylib,so} at run time via libloading (dlopen). The library is distributed separately as a binary release on GitHub and inside the published Python wheel. The path is resolved from the EMPYREAN_LIB environment variable if set, else a libempyrean.* sitting next to the loaded module, else a build-time location — an EMPYREAN_LIB_DIR override, a sibling ../target/release build, or a checksum-pinned download from the GitHub release (in that order). The FFI bindings are pre-generated and committed, so no C header, libclang, or bindgen is needed to build.

Prebuilt engine binaries are currently published for four targets: macOS arm64 (macos-aarch64), macOS x86_64 (macos-x86_64), Linux x86_64 (linux-x86_64), and Linux aarch64 (linux-aarch64). On other targets the build stops with an error unless EMPYREAN_LIB_DIR points at an engine build.

License

Source code in this crate is licensed under the BSD 3-Clause License. The closed-source libempyrean runtime it loads at runtime is governed by a separate proprietary binary license; see the main repository for the dual-license breakdown.

Copyright © 2024–2026 Joachim Moeyens. All rights reserved.