/* automatically generated by rust-bindgen 0.72.1 */
pub const EMPYREAN_BUILTSYSTEM_OK: u32 = 0;
pub const EMPYREAN_BUILTSYSTEM_NULL_POINTER: i32 = -1;
pub const EMPYREAN_BUILTSYSTEM_INVALID_ARGUMENT: i32 = -2;
pub const EMPYREAN_BUILTSYSTEM_PROPAGATION: i32 = -3;
pub const EMPYREAN_BUILTSYSTEM_ALLOC: i32 = -5;
pub const EMPYREAN_BUILTSYSTEM_DATA_MISMATCH: i32 = -20;
pub const EMPYREAN_BUILTSYSTEM_KEY_MISMATCH_FRAME: i32 = -21;
pub const EMPYREAN_BUILTSYSTEM_KEY_MISMATCH_FORCE_MODEL: i32 = -22;
pub const EMPYREAN_BUILTSYSTEM_KEY_MISMATCH_DIVISOR: i32 = -23;
pub const EMPYREAN_BUILTSYSTEM_STALE: i32 = -24;
pub const EMPYREAN_BUILTSYSTEM_PANIC: i32 = -99;
pub const EMPYREAN_KERNEL_KIND_SPK: u32 = 0;
pub const EMPYREAN_KERNEL_KIND_BPC: u32 = 1;
pub const EMPYREAN_KERNEL_KIND_TPC: u32 = 2;
pub const EMPYREAN_KERNEL_KIND_GRAVITY: u32 = 3;
pub const EMPYREAN_KERNEL_KIND_OBSCODES: u32 = 4;
pub const EMPYREAN_KERNEL_PROVENANCE_FILE: u32 = 0;
pub const EMPYREAN_KERNEL_PROVENANCE_IN_MEMORY: u32 = 1;
pub const EMPYREAN_KERNEL_PROVENANCE_BUILT_IN: u32 = 2;
pub const EMPYREAN_RADAR_KIND_DELAY: u32 = 0;
pub const EMPYREAN_RADAR_KIND_DOPPLER: u32 = 1;
pub const EMPYREAN_REJECTION_ACCEPTED: u32 = 0;
pub const EMPYREAN_REJECTION_CHI_SQUARED: u32 = 1;
pub const EMPYREAN_REJECTION_SIGMA_CLIP: u32 = 2;
pub const EMPYREAN_REJECTION_COOKS_DISTANCE: u32 = 3;
pub const EMPYREAN_REJECTION_ADAPTIVE: u32 = 4;
pub const EMPYREAN_REJECTION_UNSUPPORTED_OBSERVATORY: u32 = 5;
pub const EMPYREAN_REJECTION_CMC2003: u32 = 6;
pub const EMPYREAN_REJECTION_RADAR_UNSUPPORTED: u32 = 7;
pub const EMPYREAN_REJECTION_OCCULTATION_UNSUPPORTED: u32 = 8;
pub const EMPYREAN_REJECTION_OUTSIDE_ARC: u32 = 9;
pub const EMPYREAN_REJECTION_NOT_EVALUATED: i32 = -1;
pub const EMPYREAN_REJECTION_KIND_ADAPTIVE: u32 = 0;
pub const EMPYREAN_REJECTION_KIND_CMC2003: u32 = 1;
pub const EMPYREAN_WEIGHTING_PRESET_NONE: u32 = 0;
pub const EMPYREAN_WEIGHTING_PRESET_VFC17: u32 = 1;
pub const EMPYREAN_WEIGHTING_PRESET_NEODYS: u32 = 2;
pub const EMPYREAN_SIGMA_POLICY_DEFAULT_ONLY: u32 = 0;
pub const EMPYREAN_SIGMA_POLICY_FLOOR: u32 = 1;
pub const EMPYREAN_WEIGHTING_LAYER_OBSERVATORY_RULE: u32 = 0;
pub const EMPYREAN_WEIGHTING_LAYER_NIGHTLY_DEWEIGHTING: u32 = 1;
pub const EMPYREAN_DEBIASING_TABLE_EFCC2020: u32 = 0;
pub const EMPYREAN_DEBIASING_RESOLUTION_STANDARD: u32 = 0;
pub const EMPYREAN_DEBIASING_RESOLUTION_HIRES: u32 = 1;
pub const EMPYREAN_SOLVE_FOR_STATE_ONLY: u32 = 0;
pub const EMPYREAN_SOLVE_FOR_STATE_AND_NONGRAV: u32 = 1;
pub const EMPYREAN_SOLVE_FOR_AUTO: u32 = 2;
pub const EMPYREAN_ORIGIN_POLICY_AUTO: u32 = 0;
pub const EMPYREAN_ORIGIN_POLICY_EXPLICIT: u32 = 1;
pub const EMPYREAN_OUTPUT_EPOCH_MID_ARC: u32 = 0;
pub const EMPYREAN_OUTPUT_EPOCH_LAST_OBSERVATION: u32 = 1;
pub const EMPYREAN_OUTPUT_EPOCH_EXPLICIT: u32 = 2;
pub const EMPYREAN_OUTPUT_EPOCH_IOD_EPOCH: u32 = 3;
pub const EMPYREAN_REPRESENTATION_CARTESIAN: u32 = 0;
pub const EMPYREAN_REPRESENTATION_KEPLERIAN: u32 = 1;
pub const EMPYREAN_REPRESENTATION_COMETARY: u32 = 2;
pub const EMPYREAN_REPRESENTATION_SPHERICAL: u32 = 3;
pub const EMPYREAN_PHASE_FUNCTION_NONE: i32 = -1;
pub const EMPYREAN_PHASE_FUNCTION_HG: u32 = 0;
pub const EMPYREAN_PHASE_FUNCTION_HG1G2: u32 = 1;
pub const EMPYREAN_PHASE_FUNCTION_HG12: u32 = 2;
pub const EMPYREAN_STEERING_LAW_CONSTANT_RTN: u32 = 0;
pub const EMPYREAN_STEERING_LAW_VELOCITY_TANGENT: u32 = 1;
pub const EMPYREAN_STEERING_LAW_INERTIAL_FIXED: u32 = 2;
pub const EMPYREAN_INTEGRATOR_GR15: u32 = 0;
pub const EMPYREAN_INTEGRATOR_DOP853: u32 = 1;
pub const EMPYREAN_ORIGIN_SWITCHING_DEFAULT: u32 = 0;
pub const EMPYREAN_ORIGIN_SWITCHING_ON: u32 = 1;
pub const EMPYREAN_ORIGIN_SWITCHING_OFF: u32 = 2;
pub const EMPYREAN_UNCERTAINTY_FIRST: u32 = 0;
pub const EMPYREAN_UNCERTAINTY_SECOND: u32 = 1;
pub const EMPYREAN_UNCERTAINTY_SIGMA_POINT: u32 = 2;
pub const EMPYREAN_UNCERTAINTY_MONTE_CARLO: u32 = 3;
pub const EMPYREAN_UNCERTAINTY_AUTO: u32 = 4;
pub const EMPYREAN_COVARIANCE_KIND_LINEAR: u32 = 0;
pub const EMPYREAN_COVARIANCE_KIND_SECOND_ORDER: u32 = 1;
pub const EMPYREAN_COVARIANCE_KIND_THIRD_ORDER: u32 = 2;
pub const EMPYREAN_COVARIANCE_KIND_MIXTURE: u32 = 3;
pub const EMPYREAN_COVARIANCE_KIND_MONTE_CARLO: u32 = 4;
pub const EMPYREAN_COVARIANCE_KIND_SIGMA_POINT: u32 = 5;
pub const EMPYREAN_COVARIANCE_QUALITY_POSITIVE_DEFINITE: u32 = 0;
pub const EMPYREAN_COVARIANCE_QUALITY_INDEFINITE: u32 = 1;
pub const EMPYREAN_COVARIANCE_QUALITY_REPAIRED: u32 = 2;
pub const EMPYREAN_TARGET_FUNCTIONAL_CARTESIAN_STATE: u32 = 0;
pub const EMPYREAN_TARGET_FUNCTIONAL_CLOSE_APPROACH_MISS_DISTANCE: u32 = 1;
pub const EMPYREAN_TAGGED_COV_OK: u32 = 0;
pub const EMPYREAN_TAGGED_COV_NULL_POINTER: i32 = -1;
pub const EMPYREAN_TAGGED_COV_ORBIT_INDEX_OUT_OF_RANGE: i32 = -2;
pub const EMPYREAN_TAGGED_COV_NO_INITIAL_COVARIANCE: i32 = -3;
pub const EMPYREAN_TAGGED_COV_NO_DENSE_TRAJECTORY: i32 = -4;
pub const EMPYREAN_TAGGED_COV_STATE_MISSING: i32 = -5;
pub const EMPYREAN_TAGGED_COV_TRANSFORM: i32 = -6;
pub const EMPYREAN_TAGGED_COV_UNCERTAINTY: i32 = -7;
pub const EMPYREAN_TAGGED_COV_EPOCH_INDEX_OUT_OF_RANGE: i32 = -8;
pub const EMPYREAN_TAGGED_COV_SAMPLE_COVARIANCE_MISSING: i32 = -9;
pub const EMPYREAN_TAGGED_COV_PANIC: i32 = -99;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Context {
_unused: [u8; 0],
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Session {
_unused: [u8; 0],
}
#[doc = " Opaque handle wrapping a pre-assembled force model plus the\n kernel-identity snapshot taken from the context at construction (so\n [`empyrean_builtsystem_describe`] is self-contained). Construct with\n [`empyrean_builtsystem_new`]; release with [`empyrean_builtsystem_free`].\n\n The handle is `Send + Sync`: hand `&EmpyreanBuiltSystem` (via a `const`\n pointer) to as many threads as you like. It borrows nothing from the\n context after construction."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanBuiltSystem {
_unused: [u8; 0],
}
#[doc = " C FFI opaque handle. Internally an [`empyrean_core::Context`]; the\n C header forward-declares `struct EmpyreanContext` — callers only\n see the pointer."]
pub type EmpyreanContext = Context;
#[doc = " Per-crate version strings reported by the empyrean stack.\n\n Mirrors [`empyrean_core::Versions`]. Each pointer is a heap-allocated\n NUL-terminated UTF-8 string owned by [`EmpyreanVersions`]; release\n the whole struct with [`empyrean_versions_free`] (do not free the\n individual fields with [`empyrean_string_free`])."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanVersions {
#[doc = " `empyrean-core` crate version (semver string from `Cargo.toml`)."]
pub empyrean_core: *mut ::std::os::raw::c_char,
#[doc = " `villeneuve` crate version (`<tag>+<sha>` git-populated)."]
pub villeneuve: *mut ::std::os::raw::c_char,
#[doc = " `scott` crate version (`<tag>+<sha>` git-populated)."]
pub scott: *mut ::std::os::raw::c_char,
#[doc = " `nolan` crate version (`<tag>+<sha>` git-populated)."]
pub nolan: *mut ::std::os::raw::c_char,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanVersions"][::std::mem::size_of::<EmpyreanVersions>() - 32usize];
["Alignment of EmpyreanVersions"][::std::mem::align_of::<EmpyreanVersions>() - 8usize];
["Offset of field: EmpyreanVersions::empyrean_core"]
[::std::mem::offset_of!(EmpyreanVersions, empyrean_core) - 0usize];
["Offset of field: EmpyreanVersions::villeneuve"]
[::std::mem::offset_of!(EmpyreanVersions, villeneuve) - 8usize];
["Offset of field: EmpyreanVersions::scott"]
[::std::mem::offset_of!(EmpyreanVersions, scott) - 16usize];
["Offset of field: EmpyreanVersions::nolan"]
[::std::mem::offset_of!(EmpyreanVersions, nolan) - 24usize];
};
impl Default for EmpyreanVersions {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Flat C-ABI compatible coordinate state.\n\n Field-identical to [`empyrean_core::convert::CoordinateState`]; the\n duplicate definition exists so cbindgen (which has `parse_deps =\n false`) can emit the matching C struct in `empyrean.h` without\n traversing into the empyrean-core crate."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct CoordinateState {
pub epoch_mjd_tdb: f64,
pub elements: [f64; 6usize],
pub covariance: [[f64; 6usize]; 6usize],
pub has_covariance: u8,
pub representation: i32,
pub frame: i32,
pub origin: i32,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of CoordinateState"][::std::mem::size_of::<CoordinateState>() - 360usize];
["Alignment of CoordinateState"][::std::mem::align_of::<CoordinateState>() - 8usize];
["Offset of field: CoordinateState::epoch_mjd_tdb"]
[::std::mem::offset_of!(CoordinateState, epoch_mjd_tdb) - 0usize];
["Offset of field: CoordinateState::elements"]
[::std::mem::offset_of!(CoordinateState, elements) - 8usize];
["Offset of field: CoordinateState::covariance"]
[::std::mem::offset_of!(CoordinateState, covariance) - 56usize];
["Offset of field: CoordinateState::has_covariance"]
[::std::mem::offset_of!(CoordinateState, has_covariance) - 344usize];
["Offset of field: CoordinateState::representation"]
[::std::mem::offset_of!(CoordinateState, representation) - 348usize];
["Offset of field: CoordinateState::frame"]
[::std::mem::offset_of!(CoordinateState, frame) - 352usize];
["Offset of field: CoordinateState::origin"]
[::std::mem::offset_of!(CoordinateState, origin) - 356usize];
};
#[doc = " A single continuous-thrust arc, mirroring\n [`empyrean_core::nongrav::ThrustArc`] as a flat `#[repr(C)]` record.\n\n Arcs are supplied through [`EmpyreanOrbit::thrust_arcs`] as a\n caller-owned side array borrowed read-only for the duration of the call.\n\n The acceleration during the arc is\n \\\\[ \\mathbf{a}(t) = \\sigma(t)\\,\\frac{F}{m(t)}\\,\\hat{d} \\\\]\n with a smooth \\\\(\\tanh\\\\) switch \\\\(\\sigma(t)\\\\) of width set by\n `sharpness`, steering direction \\\\(\\hat{d}\\\\) from `steering_law`, and\n mass \\\\(m(t)\\\\) that depletes when `isp_s` is finite."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanThrustArc {
#[doc = " Arc start epoch (MJD TDB)."]
pub start_mjd_tdb: f64,
#[doc = " Arc end epoch (MJD TDB)."]
pub end_mjd_tdb: f64,
#[doc = " Engine thrust force in Newtons."]
pub thrust_n: f64,
#[doc = " Spacecraft mass at arc start in kilograms."]
pub mass_kg: f64,
#[doc = " Specific impulse in seconds. Any non-finite value (`NaN` or `±∞`)\n selects constant mass (no depletion); a finite value depletes mass at\n \\\\(\\dot m = F/(I_{sp} g_0)\\\\). This is the `Option<f64>` NaN-sentinel\n convention shared with [`EmpyreanOrbit::non_grav_dt`]."]
pub isp_s: f64,
#[doc = " Steering-law selector — see the `EMPYREAN_STEERING_LAW_*` tag\n constants. An unrecognized value errors loudly."]
pub steering_law: i32,
#[doc = " `CONSTANT_RTN` in-plane angle α from radial toward transverse\n (radians). Read only when `steering_law == CONSTANT_RTN`."]
pub steering_alpha_rad: f64,
#[doc = " `CONSTANT_RTN` out-of-plane angle β toward orbit normal (radians).\n Read only when `steering_law == CONSTANT_RTN`."]
pub steering_beta_rad: f64,
#[doc = " `INERTIAL_FIXED` direction vector (normalized internally). Read only\n when `steering_law == INERTIAL_FIXED`."]
pub steering_direction: [f64; 3usize],
#[doc = " \\\\(\\tanh\\\\) switching sharpness (1/days). Higher = sharper on/off."]
pub sharpness: f64,
#[doc = " Central-body NAIF id for the RTN / velocity-tangent frame reference\n (same encoding as [`EmpyreanOrbit`]'s `state.origin`, e.g. `399` for\n Earth, `10` for the Sun). An unknown NAIF id errors loudly."]
pub central_body_naif_id: i32,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanThrustArc"][::std::mem::size_of::<EmpyreanThrustArc>() - 104usize];
["Alignment of EmpyreanThrustArc"][::std::mem::align_of::<EmpyreanThrustArc>() - 8usize];
["Offset of field: EmpyreanThrustArc::start_mjd_tdb"]
[::std::mem::offset_of!(EmpyreanThrustArc, start_mjd_tdb) - 0usize];
["Offset of field: EmpyreanThrustArc::end_mjd_tdb"]
[::std::mem::offset_of!(EmpyreanThrustArc, end_mjd_tdb) - 8usize];
["Offset of field: EmpyreanThrustArc::thrust_n"]
[::std::mem::offset_of!(EmpyreanThrustArc, thrust_n) - 16usize];
["Offset of field: EmpyreanThrustArc::mass_kg"]
[::std::mem::offset_of!(EmpyreanThrustArc, mass_kg) - 24usize];
["Offset of field: EmpyreanThrustArc::isp_s"]
[::std::mem::offset_of!(EmpyreanThrustArc, isp_s) - 32usize];
["Offset of field: EmpyreanThrustArc::steering_law"]
[::std::mem::offset_of!(EmpyreanThrustArc, steering_law) - 40usize];
["Offset of field: EmpyreanThrustArc::steering_alpha_rad"]
[::std::mem::offset_of!(EmpyreanThrustArc, steering_alpha_rad) - 48usize];
["Offset of field: EmpyreanThrustArc::steering_beta_rad"]
[::std::mem::offset_of!(EmpyreanThrustArc, steering_beta_rad) - 56usize];
["Offset of field: EmpyreanThrustArc::steering_direction"]
[::std::mem::offset_of!(EmpyreanThrustArc, steering_direction) - 64usize];
["Offset of field: EmpyreanThrustArc::sharpness"]
[::std::mem::offset_of!(EmpyreanThrustArc, sharpness) - 88usize];
["Offset of field: EmpyreanThrustArc::central_body_naif_id"]
[::std::mem::offset_of!(EmpyreanThrustArc, central_body_naif_id) - 96usize];
};
#[doc = " An orbit with optional non-gravitational parameters, continuous-thrust\n arcs, and photometry.\n\n Thrust: when `n_thrust_arcs > 0`, [`thrust_arcs`](Self::thrust_arcs)\n (plus the optional [`dv_corrections`](Self::dv_corrections) /\n [`correction_covariances`](Self::correction_covariances) side arrays)\n build a [`ThrustParams`] for this orbit. All-zero `a1/a2/a3` and\n `n_thrust_arcs == 0` is a pure-gravity orbit.\n\n `a1/a2/a3` are the Marsden–Sekanina RTN coefficients (radial,\n transverse, normal) in AU/day². `ng_alpha … ng_k` parameterize the\n g(r) distance-dependent scaling:\n \\\\[ g(r) = \\alpha \\\\, (r/r_0)^{-m} \\\\, (1 + (r/r_0)^n)^{-k} \\\\].\n All-zeros for the g-function fields selects the inverse-square\n default (Yarkovsky / SRP asteroid case): \\\\(\\alpha = r_0 = 1\\\\),\n \\\\(m = 2\\\\), \\\\(n = k = 0\\\\). Comets typically pass SBDB's\n Marsden water-ice values\n (\\\\(\\alpha = 0.1113, r_0 = 2.808, m = 2.15, n = 5.093, k = 4.6142\\\\)).\n\n Photometry: when `phot_system` is one of the `EMPYREAN_PHASE_FUNCTION_*`\n non-`NONE` constants, ephemeris generation produces apparent magnitude\n using the (`H`, `slope1`, `slope2`) triple per the chosen phase function:\n\n | Model | `H` | `slope1` | `slope2` |\n |-------|-----|----------|----------|\n | `HG` | absolute magnitude | G | unused (0) |\n | `HG1G2` | absolute magnitude | G₁ | G₂ |\n | `HG12` | absolute magnitude | G₁₂ | unused (0) |"]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanOrbit {
pub state: CoordinateState,
#[doc = " Caller-supplied orbit identifier — primary key for joining\n outputs (propagated states, events, ephemeris, B-planes, IP) to\n the input row. NUL-terminated UTF-8. A null pointer or empty\n string causes the C ABI to fabricate a positional `\"orbit_{i}\"`\n tag instead — set this whenever you want stable joins.\n\n **Ownership:** read-only borrow from the caller; the C ABI does\n not free it."]
pub orbit_id: *const ::std::os::raw::c_char,
#[doc = " Caller-supplied object identifier (e.g. SBDB designation).\n Distinct from `orbit_id` so multiple orbit hypotheses for the\n same object can share an `object_id`. NUL-terminated UTF-8.\n Empty string or null = no object identifier.\n\n **Ownership:** read-only borrow from the caller; the C ABI does\n not free it."]
pub object_id: *const ::std::os::raw::c_char,
#[doc = " Marsden-Sekanina A1 coefficient (radial). 0 ⇒ no non-grav."]
pub a1: f64,
#[doc = " Marsden-Sekanina A2 coefficient (transverse)."]
pub a2: f64,
#[doc = " Marsden-Sekanina A3 coefficient (normal)."]
pub a3: f64,
#[doc = " g(r) normalizing constant α. All-zero g-fields → inverse_square."]
pub ng_alpha: f64,
#[doc = " g(r) reference distance r₀ (AU)."]
pub ng_r0: f64,
#[doc = " g(r) inner power-law exponent m."]
pub ng_m: f64,
#[doc = " g(r) outer power-law exponent n."]
pub ng_n: f64,
#[doc = " g(r) outer damping exponent k."]
pub ng_k: f64,
#[doc = " SBDB non-grav time delay in days. Use NaN for no delay (the\n asteroid default and the Marsden water-ice default for comets\n SBDB doesn't fit a delay for). Set to a finite value (positive\n or negative) when SBDB's `model_pars[]` exposes a `DT` field —\n e.g. 67P (+45.7d), 46P/Wirtanen (−14.1d), 2I/Borisov (−65.1d)."]
pub non_grav_dt: f64,
#[doc = " 1 when `non_grav_covariance` carries a non-grav prior covariance; 0\n otherwise. Set by the OD output path (a fitted orbit) so it re-feeds\n into a StateAndNonGrav refine without losing its non-grav prior;\n leave 0 for hand-built / SBDB / propagate inputs."]
pub has_non_grav_covariance: u8,
#[doc = " Non-grav 3×3 covariance for (A1, A2, A3), row-major. Only read when\n `has_non_grav_covariance = 1`."]
pub non_grav_covariance: [[f64; 3usize]; 3usize],
#[doc = " Phase-function model. `EMPYREAN_PHASE_FUNCTION_NONE` disables\n magnitude computation; the other values map to villeneuve's\n `PhaseFunction` enum."]
pub phot_system: i32,
#[doc = " Absolute magnitude H. Ignored when `phot_system == NONE`."]
pub h_mag: f64,
#[doc = " Slope parameter slot 1 — G (HG), G₁ (HG1G2), or G₁₂ (HG12)."]
pub slope1: f64,
#[doc = " Slope parameter slot 2 — G₂ (HG1G2 only); unused (0) for HG / HG12."]
pub slope2: f64,
#[doc = " Continuous-thrust arcs (variable length). Null / `n_thrust_arcs == 0`\n ⇒ no thrust (gravity + non-grav only).\n\n **Ownership:** caller-owned; borrowed read-only for the duration of\n the call. The C ABI never frees it. A null pointer with\n `n_thrust_arcs > 0` is a loud argument error, not a silent skip; a\n non-null pointer with `n_thrust_arcs == 0` is treated as absent (the\n pointer is not read)."]
pub thrust_arcs: *const EmpyreanThrustArc,
#[doc = " Number of arcs in [`thrust_arcs`](Self::thrust_arcs)."]
pub n_thrust_arcs: usize,
#[doc = " Optional per-arc Δv corrections (AU/day), positional with\n [`thrust_arcs`](Self::thrust_arcs). Null / `n_dv_corrections == 0` ⇒\n no targeting corrections. Supplying corrections without any arc is a\n loud argument error.\n\n **Ownership:** caller-owned; borrowed read-only for the call."]
pub dv_corrections: *const [f64; 3usize],
#[doc = " Number of corrections in [`dv_corrections`](Self::dv_corrections)."]
pub n_dv_corrections: usize,
#[doc = " Optional 3×3 covariance (AU/day)² per Δv correction, positional with\n [`dv_corrections`](Self::dv_corrections). When non-empty its length\n MUST equal `n_dv_corrections`; a non-empty covariance triggers the\n wide-Jet burn-sensitivity propagation. The engine's higher-order\n (third-order) propagation path does not implement thrust-correction\n covariance and rejects that combination loudly upstream\n (`Not implemented: … ThirdOrder with thrust-correction covariance …`,\n surfaced as a propagation error) rather than silently dropping the\n covariance.\n\n **Ownership:** caller-owned; borrowed read-only for the call."]
pub correction_covariances: *const [[f64; 3usize]; 3usize],
#[doc = " Number of entries in\n [`correction_covariances`](Self::correction_covariances)."]
pub n_correction_covariances: usize,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanOrbit"][::std::mem::size_of::<EmpyreanOrbit>() - 608usize];
["Alignment of EmpyreanOrbit"][::std::mem::align_of::<EmpyreanOrbit>() - 8usize];
["Offset of field: EmpyreanOrbit::state"]
[::std::mem::offset_of!(EmpyreanOrbit, state) - 0usize];
["Offset of field: EmpyreanOrbit::orbit_id"]
[::std::mem::offset_of!(EmpyreanOrbit, orbit_id) - 360usize];
["Offset of field: EmpyreanOrbit::object_id"]
[::std::mem::offset_of!(EmpyreanOrbit, object_id) - 368usize];
["Offset of field: EmpyreanOrbit::a1"][::std::mem::offset_of!(EmpyreanOrbit, a1) - 376usize];
["Offset of field: EmpyreanOrbit::a2"][::std::mem::offset_of!(EmpyreanOrbit, a2) - 384usize];
["Offset of field: EmpyreanOrbit::a3"][::std::mem::offset_of!(EmpyreanOrbit, a3) - 392usize];
["Offset of field: EmpyreanOrbit::ng_alpha"]
[::std::mem::offset_of!(EmpyreanOrbit, ng_alpha) - 400usize];
["Offset of field: EmpyreanOrbit::ng_r0"]
[::std::mem::offset_of!(EmpyreanOrbit, ng_r0) - 408usize];
["Offset of field: EmpyreanOrbit::ng_m"]
[::std::mem::offset_of!(EmpyreanOrbit, ng_m) - 416usize];
["Offset of field: EmpyreanOrbit::ng_n"]
[::std::mem::offset_of!(EmpyreanOrbit, ng_n) - 424usize];
["Offset of field: EmpyreanOrbit::ng_k"]
[::std::mem::offset_of!(EmpyreanOrbit, ng_k) - 432usize];
["Offset of field: EmpyreanOrbit::non_grav_dt"]
[::std::mem::offset_of!(EmpyreanOrbit, non_grav_dt) - 440usize];
["Offset of field: EmpyreanOrbit::has_non_grav_covariance"]
[::std::mem::offset_of!(EmpyreanOrbit, has_non_grav_covariance) - 448usize];
["Offset of field: EmpyreanOrbit::non_grav_covariance"]
[::std::mem::offset_of!(EmpyreanOrbit, non_grav_covariance) - 456usize];
["Offset of field: EmpyreanOrbit::phot_system"]
[::std::mem::offset_of!(EmpyreanOrbit, phot_system) - 528usize];
["Offset of field: EmpyreanOrbit::h_mag"]
[::std::mem::offset_of!(EmpyreanOrbit, h_mag) - 536usize];
["Offset of field: EmpyreanOrbit::slope1"]
[::std::mem::offset_of!(EmpyreanOrbit, slope1) - 544usize];
["Offset of field: EmpyreanOrbit::slope2"]
[::std::mem::offset_of!(EmpyreanOrbit, slope2) - 552usize];
["Offset of field: EmpyreanOrbit::thrust_arcs"]
[::std::mem::offset_of!(EmpyreanOrbit, thrust_arcs) - 560usize];
["Offset of field: EmpyreanOrbit::n_thrust_arcs"]
[::std::mem::offset_of!(EmpyreanOrbit, n_thrust_arcs) - 568usize];
["Offset of field: EmpyreanOrbit::dv_corrections"]
[::std::mem::offset_of!(EmpyreanOrbit, dv_corrections) - 576usize];
["Offset of field: EmpyreanOrbit::n_dv_corrections"]
[::std::mem::offset_of!(EmpyreanOrbit, n_dv_corrections) - 584usize];
["Offset of field: EmpyreanOrbit::correction_covariances"]
[::std::mem::offset_of!(EmpyreanOrbit, correction_covariances) - 592usize];
["Offset of field: EmpyreanOrbit::n_correction_covariances"]
[::std::mem::offset_of!(EmpyreanOrbit, n_correction_covariances) - 600usize];
};
impl Default for EmpyreanOrbit {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Uncertainty-propagation method, mirroring\n [`empyrean_core::propagation::UncertaintyMethod`] as a flat C struct.\n Fields outside the active variant are ignored — set them to zero /\n NaN.\n\n | tag | Variant | Active fields |\n |-----|---------|---------------|\n | 0 | First | (none) |\n | 1 | Second | (none) |\n | 2 | SigmaPoint | `sp_n_sigma`, `sp_samples_per_plane` |\n | 3 | MonteCarlo | `mc_n_samples`, `mc_seed_some` (1 = use `mc_seed`) |\n | 4 | Auto | `auto_threshold_first`, `auto_threshold_mixture`, `auto_threshold_ip_skip`, `auto_gmm_max_depth`, `auto_gmm_components_per_split` |"]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanUncertaintyMethod {
#[doc = " Variant tag — see `EMPYREAN_UNCERTAINTY_*` constants."]
pub tag: u8,
#[doc = " SigmaPoint: number of sigma deviations (default 1.0)."]
pub sp_n_sigma: f64,
#[doc = " SigmaPoint: points per coordinate-plane pair (default 8 → 120 total)."]
pub sp_samples_per_plane: u64,
#[doc = " MonteCarlo: number of random samples."]
pub mc_n_samples: u64,
#[doc = " MonteCarlo: 1 if `mc_seed` is set, 0 to draw from `thread_rng`."]
pub mc_seed_some: u8,
#[doc = " MonteCarlo: RNG seed when `mc_seed_some == 1`."]
pub mc_seed: u64,
#[doc = " Auto: first-order regime tuning parameter."]
pub auto_threshold_first: f64,
#[doc = " Auto: adaptive-mixture regime tuning parameter."]
pub auto_threshold_mixture: f64,
#[doc = " Auto: impact-probability tuning parameter for the higher-order pass."]
pub auto_threshold_ip_skip: f64,
#[doc = " Auto: adaptive-Gaussian-mixture maximum recursion depth."]
pub auto_gmm_max_depth: u64,
#[doc = " Auto: adaptive-Gaussian-mixture components per split (odd)."]
pub auto_gmm_components_per_split: u64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanUncertaintyMethod"]
[::std::mem::size_of::<EmpyreanUncertaintyMethod>() - 88usize];
["Alignment of EmpyreanUncertaintyMethod"]
[::std::mem::align_of::<EmpyreanUncertaintyMethod>() - 8usize];
["Offset of field: EmpyreanUncertaintyMethod::tag"]
[::std::mem::offset_of!(EmpyreanUncertaintyMethod, tag) - 0usize];
["Offset of field: EmpyreanUncertaintyMethod::sp_n_sigma"]
[::std::mem::offset_of!(EmpyreanUncertaintyMethod, sp_n_sigma) - 8usize];
["Offset of field: EmpyreanUncertaintyMethod::sp_samples_per_plane"]
[::std::mem::offset_of!(EmpyreanUncertaintyMethod, sp_samples_per_plane) - 16usize];
["Offset of field: EmpyreanUncertaintyMethod::mc_n_samples"]
[::std::mem::offset_of!(EmpyreanUncertaintyMethod, mc_n_samples) - 24usize];
["Offset of field: EmpyreanUncertaintyMethod::mc_seed_some"]
[::std::mem::offset_of!(EmpyreanUncertaintyMethod, mc_seed_some) - 32usize];
["Offset of field: EmpyreanUncertaintyMethod::mc_seed"]
[::std::mem::offset_of!(EmpyreanUncertaintyMethod, mc_seed) - 40usize];
["Offset of field: EmpyreanUncertaintyMethod::auto_threshold_first"]
[::std::mem::offset_of!(EmpyreanUncertaintyMethod, auto_threshold_first) - 48usize];
["Offset of field: EmpyreanUncertaintyMethod::auto_threshold_mixture"]
[::std::mem::offset_of!(EmpyreanUncertaintyMethod, auto_threshold_mixture) - 56usize];
["Offset of field: EmpyreanUncertaintyMethod::auto_threshold_ip_skip"]
[::std::mem::offset_of!(EmpyreanUncertaintyMethod, auto_threshold_ip_skip) - 64usize];
["Offset of field: EmpyreanUncertaintyMethod::auto_gmm_max_depth"]
[::std::mem::offset_of!(EmpyreanUncertaintyMethod, auto_gmm_max_depth) - 72usize];
["Offset of field: EmpyreanUncertaintyMethod::auto_gmm_components_per_split"][::std::mem::offset_of!(
EmpyreanUncertaintyMethod,
auto_gmm_components_per_split
) - 80usize];
};
#[doc = " Event-detection configuration. Mirrors\n [`villeneuve::events::EventConfig`] (less the `enrichment` sub-config,\n which carries internal nested data that doesn't translate cleanly\n through C — it always uses upstream defaults).\n\n `body_filter_naif` is non-owning: caller must keep the array alive\n for the duration of the propagation call. Pass `null` /\n `num_body_filter = 0` to monitor all bodies."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanEventConfig {
pub close_approaches: u8,
pub impacts: u8,
pub atmospheric: u8,
pub possible_impacts: u8,
pub shadow_events: u8,
#[doc = " Number of NAIF IDs in [`body_filter_naif`]; 0 = monitor all bodies."]
pub num_body_filter: usize,
#[doc = " Pointer to `num_body_filter` NAIF IDs to restrict event monitoring."]
pub body_filter_naif: *const i32,
#[doc = " Insert dense output points around close approaches. 1 = on (auto-enables\n `cache_integrator_steps`), 0 = off (default)."]
pub dense_output: u8,
#[doc = " Cadence (days) of dense output. 0.0 → upstream default (5 minutes)."]
pub dense_output_cadence_days: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanEventConfig"][::std::mem::size_of::<EmpyreanEventConfig>() - 40usize];
["Alignment of EmpyreanEventConfig"][::std::mem::align_of::<EmpyreanEventConfig>() - 8usize];
["Offset of field: EmpyreanEventConfig::close_approaches"]
[::std::mem::offset_of!(EmpyreanEventConfig, close_approaches) - 0usize];
["Offset of field: EmpyreanEventConfig::impacts"]
[::std::mem::offset_of!(EmpyreanEventConfig, impacts) - 1usize];
["Offset of field: EmpyreanEventConfig::atmospheric"]
[::std::mem::offset_of!(EmpyreanEventConfig, atmospheric) - 2usize];
["Offset of field: EmpyreanEventConfig::possible_impacts"]
[::std::mem::offset_of!(EmpyreanEventConfig, possible_impacts) - 3usize];
["Offset of field: EmpyreanEventConfig::shadow_events"]
[::std::mem::offset_of!(EmpyreanEventConfig, shadow_events) - 4usize];
["Offset of field: EmpyreanEventConfig::num_body_filter"]
[::std::mem::offset_of!(EmpyreanEventConfig, num_body_filter) - 8usize];
["Offset of field: EmpyreanEventConfig::body_filter_naif"]
[::std::mem::offset_of!(EmpyreanEventConfig, body_filter_naif) - 16usize];
["Offset of field: EmpyreanEventConfig::dense_output"]
[::std::mem::offset_of!(EmpyreanEventConfig, dense_output) - 24usize];
["Offset of field: EmpyreanEventConfig::dense_output_cadence_days"]
[::std::mem::offset_of!(EmpyreanEventConfig, dense_output_cadence_days) - 32usize];
};
impl Default for EmpyreanEventConfig {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Per-trajectory diagnostic outputs (sensitivity, nonlinearity, …).\n Mirrors [`villeneuve::diagnostics::DiagnosticsConfig`].\n\n All metrics default to off. Sentinel: `0` for `sample_stride` →\n upstream default (1); a NaN threshold means \"no event emission for\n that metric\"."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanDiagnosticsConfig {
#[doc = " Frobenius norm of position-STM block. 1 = on, 0 = off."]
pub sensitivity: u8,
#[doc = " Hessian/gradient ratio (Jet2 only). 1 = on, 0 = off."]
pub nonlinearity: u8,
#[doc = " Finite-time Lyapunov exponent. 1 = on, 0 = off."]
pub lyapunov: u8,
#[doc = " Keyhole detection at close approaches (Jet1+). 1 = on, 0 = off."]
pub keyholes: u8,
#[doc = " Bifurcation detection at close approaches (Jet2 only). 1 = on, 0 = off."]
pub bifurcations: u8,
#[doc = " Timeseries sampling stride: every Nth integration step. 0 → upstream default (1)."]
pub sample_stride: usize,
#[doc = " Threshold for `HighSensitivity` events. NaN → no emission."]
pub sensitivity_threshold: f64,
#[doc = " Threshold for `ChaoticRegion` events. NaN → no emission."]
pub lyapunov_threshold: f64,
#[doc = " Threshold for `HighNonlinearity` events (Jet2 only). NaN → no emission."]
pub nonlinearity_threshold: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanDiagnosticsConfig"]
[::std::mem::size_of::<EmpyreanDiagnosticsConfig>() - 40usize];
["Alignment of EmpyreanDiagnosticsConfig"]
[::std::mem::align_of::<EmpyreanDiagnosticsConfig>() - 8usize];
["Offset of field: EmpyreanDiagnosticsConfig::sensitivity"]
[::std::mem::offset_of!(EmpyreanDiagnosticsConfig, sensitivity) - 0usize];
["Offset of field: EmpyreanDiagnosticsConfig::nonlinearity"]
[::std::mem::offset_of!(EmpyreanDiagnosticsConfig, nonlinearity) - 1usize];
["Offset of field: EmpyreanDiagnosticsConfig::lyapunov"]
[::std::mem::offset_of!(EmpyreanDiagnosticsConfig, lyapunov) - 2usize];
["Offset of field: EmpyreanDiagnosticsConfig::keyholes"]
[::std::mem::offset_of!(EmpyreanDiagnosticsConfig, keyholes) - 3usize];
["Offset of field: EmpyreanDiagnosticsConfig::bifurcations"]
[::std::mem::offset_of!(EmpyreanDiagnosticsConfig, bifurcations) - 4usize];
["Offset of field: EmpyreanDiagnosticsConfig::sample_stride"]
[::std::mem::offset_of!(EmpyreanDiagnosticsConfig, sample_stride) - 8usize];
["Offset of field: EmpyreanDiagnosticsConfig::sensitivity_threshold"]
[::std::mem::offset_of!(EmpyreanDiagnosticsConfig, sensitivity_threshold) - 16usize];
["Offset of field: EmpyreanDiagnosticsConfig::lyapunov_threshold"]
[::std::mem::offset_of!(EmpyreanDiagnosticsConfig, lyapunov_threshold) - 24usize];
["Offset of field: EmpyreanDiagnosticsConfig::nonlinearity_threshold"]
[::std::mem::offset_of!(EmpyreanDiagnosticsConfig, nonlinearity_threshold) - 32usize];
};
#[doc = " Origin-switching configuration for trajectory splitting at body\n Laplace spheres of influence (Amato/Baù/Bombardelli 2017 §6).\n\n Default disabled (`enabled = 0`). When enabled, integration\n switches to a body-centric frame inside the SOI of each eligible\n body and back to SSB on exit.\n\n At the C-ABI surface, the per-body opt-in list (`bodies` in\n villeneuve) is not yet exposed — `EMPYREAN_ORIGIN_SWITCHING_ON`\n selects all monitored bodies. File a request if per-body scoping\n is needed from the C-ABI surface."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanOriginSwitchingConfig {
#[doc = " Trajectory-splitting policy. Tri-state, see\n `EMPYREAN_ORIGIN_SWITCHING_*` constants:\n - `0 = DEFAULT` — use the upstream default (currently `ON`).\n This is what `memset(0)` gives, matching the same sentinel\n convention used for `dt_min` / `dt_initial` / `epsilon` /\n `hysteresis` etc. — external C consumers can zero-init the\n config struct and get the right behavior automatically.\n - `1 = ON` — force trajectory-splitting on (matches the prior\n semantic for `enabled = 1`, backward-compatible).\n - `2 = OFF` — force trajectory-splitting off. (The prior\n semantic for `enabled = 0` is now reachable only via this\n explicit value, since 0 now means DEFAULT.)\n\n Unknown values fall back to the upstream default."]
pub enabled: u8,
#[doc = " Fractional band around the acceleration-ratio crossover used\n to suppress chatter (default 0.2 = ±20 %). 0.0 → upstream\n default."]
pub hysteresis: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanOriginSwitchingConfig"]
[::std::mem::size_of::<EmpyreanOriginSwitchingConfig>() - 16usize];
["Alignment of EmpyreanOriginSwitchingConfig"]
[::std::mem::align_of::<EmpyreanOriginSwitchingConfig>() - 8usize];
["Offset of field: EmpyreanOriginSwitchingConfig::enabled"]
[::std::mem::offset_of!(EmpyreanOriginSwitchingConfig, enabled) - 0usize];
["Offset of field: EmpyreanOriginSwitchingConfig::hysteresis"]
[::std::mem::offset_of!(EmpyreanOriginSwitchingConfig, hysteresis) - 8usize];
};
#[doc = " Integrator tuning. Mirrors\n [`villeneuve::propagation::AdvancedIntegratorConfig`]. The default\n integrator backend is Gauss-Radau 15 (GR15), derived solely from the\n published papers; `epsilon` is interpreted as the relative b₆\n truncation tolerance.\n\n Sentinel rule: `0.0` requests the upstream default for `epsilon` /\n `encounter_timescale_divisor`; `dt_initial` / `dt_min` use NaN to\n mean \"auto-compute\"; `0` requests the upstream defaults for\n `max_steps` and `max_dense_steps`."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanAdvancedIntegratorConfig {
#[doc = " Integrator backend (0 = GR15 default, 1 = DOP853). See\n `EMPYREAN_INTEGRATOR_*` constants."]
pub integrator: i32,
#[doc = " Truncation-error tolerance (relative b₆ for GR15, rtol for\n DOP853 paired with a fixed atol = 1e-14). 0.0 → upstream\n default (1e-9)."]
pub epsilon: f64,
#[doc = " Initial step size in days. NaN → auto from orbital timescale."]
pub dt_initial: f64,
#[doc = " Minimum allowed step size in days. NaN → auto."]
pub dt_min: f64,
#[doc = " Encounter dynamical-timescale step floor divisor. 0.0 → upstream default (1000.0)."]
pub encounter_timescale_divisor: f64,
#[doc = " Maximum integration steps before aborting. 0 → upstream default (10_000_000)."]
pub max_steps: usize,
#[doc = " Memory cap on the per-step b-coefficient cache. 0 → upstream default (100_000)."]
pub max_dense_steps: usize,
#[doc = " Cache the integrator's per-step b-coefficients for fast\n interpolation (light-time iteration, dense output around close\n approaches, arbitrary-epoch state queries). 1 = on, 0 = off\n (default)."]
pub cache_integrator_steps: u8,
#[doc = " Origin-switching trajectory-splitting configuration. Default\n enabled."]
pub origin_switching: EmpyreanOriginSwitchingConfig,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanAdvancedIntegratorConfig"]
[::std::mem::size_of::<EmpyreanAdvancedIntegratorConfig>() - 80usize];
["Alignment of EmpyreanAdvancedIntegratorConfig"]
[::std::mem::align_of::<EmpyreanAdvancedIntegratorConfig>() - 8usize];
["Offset of field: EmpyreanAdvancedIntegratorConfig::integrator"]
[::std::mem::offset_of!(EmpyreanAdvancedIntegratorConfig, integrator) - 0usize];
["Offset of field: EmpyreanAdvancedIntegratorConfig::epsilon"]
[::std::mem::offset_of!(EmpyreanAdvancedIntegratorConfig, epsilon) - 8usize];
["Offset of field: EmpyreanAdvancedIntegratorConfig::dt_initial"]
[::std::mem::offset_of!(EmpyreanAdvancedIntegratorConfig, dt_initial) - 16usize];
["Offset of field: EmpyreanAdvancedIntegratorConfig::dt_min"]
[::std::mem::offset_of!(EmpyreanAdvancedIntegratorConfig, dt_min) - 24usize];
["Offset of field: EmpyreanAdvancedIntegratorConfig::encounter_timescale_divisor"][::std::mem::offset_of!(
EmpyreanAdvancedIntegratorConfig,
encounter_timescale_divisor
) - 32usize];
["Offset of field: EmpyreanAdvancedIntegratorConfig::max_steps"]
[::std::mem::offset_of!(EmpyreanAdvancedIntegratorConfig, max_steps) - 40usize];
["Offset of field: EmpyreanAdvancedIntegratorConfig::max_dense_steps"]
[::std::mem::offset_of!(EmpyreanAdvancedIntegratorConfig, max_dense_steps) - 48usize];
["Offset of field: EmpyreanAdvancedIntegratorConfig::cache_integrator_steps"][::std::mem::offset_of!(
EmpyreanAdvancedIntegratorConfig,
cache_integrator_steps
) - 56usize];
["Offset of field: EmpyreanAdvancedIntegratorConfig::origin_switching"]
[::std::mem::offset_of!(EmpyreanAdvancedIntegratorConfig, origin_switching) - 64usize];
};
#[doc = " Propagation configuration.\n\n Mirrors [`villeneuve::propagation::PropagationConfig`] structurally:\n shared scalar fields at the top, nested config bundles for events,\n diagnostics, and integrator tuning. Sentinel rule for primitive\n fields: `0` / `0.0` requests the upstream default; documented\n negative-value sentinels retain their special meanings.\n\n `stop_condition` and `events.enrichment` are not exposed at this\n surface — both carry internal nested data that doesn't translate\n cleanly. They use upstream defaults; reach for empyrean-core's\n Rust API when they need to be overridden."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanPropagationConfig {
#[doc = " Force-model tier: 0=Approximate, 1=Basic, 2=Standard."]
pub force_model: i32,
#[doc = " Number of `excluded_perturbers` in [`excluded_perturbers_naif`]; 0 = none."]
pub num_excluded_perturbers: usize,
#[doc = " NAIF IDs to exclude (self-perturbation avoidance for SB441-N16\n bodies). Non-owning. Pass `null` / count 0 to use the full\n perturber set."]
pub excluded_perturbers_naif: *const i32,
#[doc = " Uncertainty-propagation method (tag + per-variant params)."]
pub uncertainty_method: EmpyreanUncertaintyMethod,
#[doc = " Force `Jet1<6>` integration even without input covariance.\n 1 = on, 0 = off (default)."]
pub compute_stm: u8,
#[doc = " Output reference frame: 0=ICRF, 1=EclipticJ2000."]
pub frame: i32,
pub events: EmpyreanEventConfig,
pub diagnostics: EmpyreanDiagnosticsConfig,
#[doc = " Threads for multi-orbit propagation. 0 = use all cores\n (Rayon default); positive N = exactly N cores."]
pub num_threads: usize,
pub advanced: EmpyreanAdvancedIntegratorConfig,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanPropagationConfig"]
[::std::mem::size_of::<EmpyreanPropagationConfig>() - 288usize];
["Alignment of EmpyreanPropagationConfig"]
[::std::mem::align_of::<EmpyreanPropagationConfig>() - 8usize];
["Offset of field: EmpyreanPropagationConfig::force_model"]
[::std::mem::offset_of!(EmpyreanPropagationConfig, force_model) - 0usize];
["Offset of field: EmpyreanPropagationConfig::num_excluded_perturbers"]
[::std::mem::offset_of!(EmpyreanPropagationConfig, num_excluded_perturbers) - 8usize];
["Offset of field: EmpyreanPropagationConfig::excluded_perturbers_naif"]
[::std::mem::offset_of!(EmpyreanPropagationConfig, excluded_perturbers_naif) - 16usize];
["Offset of field: EmpyreanPropagationConfig::uncertainty_method"]
[::std::mem::offset_of!(EmpyreanPropagationConfig, uncertainty_method) - 24usize];
["Offset of field: EmpyreanPropagationConfig::compute_stm"]
[::std::mem::offset_of!(EmpyreanPropagationConfig, compute_stm) - 112usize];
["Offset of field: EmpyreanPropagationConfig::frame"]
[::std::mem::offset_of!(EmpyreanPropagationConfig, frame) - 116usize];
["Offset of field: EmpyreanPropagationConfig::events"]
[::std::mem::offset_of!(EmpyreanPropagationConfig, events) - 120usize];
["Offset of field: EmpyreanPropagationConfig::diagnostics"]
[::std::mem::offset_of!(EmpyreanPropagationConfig, diagnostics) - 160usize];
["Offset of field: EmpyreanPropagationConfig::num_threads"]
[::std::mem::offset_of!(EmpyreanPropagationConfig, num_threads) - 200usize];
["Offset of field: EmpyreanPropagationConfig::advanced"]
[::std::mem::offset_of!(EmpyreanPropagationConfig, advanced) - 208usize];
};
impl Default for EmpyreanPropagationConfig {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " A single propagated Cartesian state."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanPropagatedState {
pub epoch_mjd_tdb: f64,
pub x: f64,
pub y: f64,
pub z: f64,
pub vx: f64,
pub vy: f64,
pub vz: f64,
pub origin: i32,
pub frame: i32,
pub covariance: [[f64; 6usize]; 6usize],
pub has_covariance: u8,
#[doc = " State Transition Matrix Φ(t, t₀). Zero-filled when `has_stm` is 0."]
pub stm: [[f64; 6usize]; 6usize],
pub has_stm: u8,
#[doc = " State Transition Tensor Ψ(t, t₀). Zero-filled when `has_stt` is 0."]
pub stt: [[[f64; 6usize]; 6usize]; 6usize],
pub has_stt: u8,
#[doc = " Resolved [`CovarianceKind`](empyrean_core::propagation::CovarianceKind)\n at this output epoch — see `EMPYREAN_COVARIANCE_KIND_*`.\n Defaults to `LINEAR` for non-Auto methods and for Auto epochs\n outside CA windows."]
pub resolved_kind: u8,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanPropagatedState"]
[::std::mem::size_of::<EmpyreanPropagatedState>() - 2392usize];
["Alignment of EmpyreanPropagatedState"]
[::std::mem::align_of::<EmpyreanPropagatedState>() - 8usize];
["Offset of field: EmpyreanPropagatedState::epoch_mjd_tdb"]
[::std::mem::offset_of!(EmpyreanPropagatedState, epoch_mjd_tdb) - 0usize];
["Offset of field: EmpyreanPropagatedState::x"]
[::std::mem::offset_of!(EmpyreanPropagatedState, x) - 8usize];
["Offset of field: EmpyreanPropagatedState::y"]
[::std::mem::offset_of!(EmpyreanPropagatedState, y) - 16usize];
["Offset of field: EmpyreanPropagatedState::z"]
[::std::mem::offset_of!(EmpyreanPropagatedState, z) - 24usize];
["Offset of field: EmpyreanPropagatedState::vx"]
[::std::mem::offset_of!(EmpyreanPropagatedState, vx) - 32usize];
["Offset of field: EmpyreanPropagatedState::vy"]
[::std::mem::offset_of!(EmpyreanPropagatedState, vy) - 40usize];
["Offset of field: EmpyreanPropagatedState::vz"]
[::std::mem::offset_of!(EmpyreanPropagatedState, vz) - 48usize];
["Offset of field: EmpyreanPropagatedState::origin"]
[::std::mem::offset_of!(EmpyreanPropagatedState, origin) - 56usize];
["Offset of field: EmpyreanPropagatedState::frame"]
[::std::mem::offset_of!(EmpyreanPropagatedState, frame) - 60usize];
["Offset of field: EmpyreanPropagatedState::covariance"]
[::std::mem::offset_of!(EmpyreanPropagatedState, covariance) - 64usize];
["Offset of field: EmpyreanPropagatedState::has_covariance"]
[::std::mem::offset_of!(EmpyreanPropagatedState, has_covariance) - 352usize];
["Offset of field: EmpyreanPropagatedState::stm"]
[::std::mem::offset_of!(EmpyreanPropagatedState, stm) - 360usize];
["Offset of field: EmpyreanPropagatedState::has_stm"]
[::std::mem::offset_of!(EmpyreanPropagatedState, has_stm) - 648usize];
["Offset of field: EmpyreanPropagatedState::stt"]
[::std::mem::offset_of!(EmpyreanPropagatedState, stt) - 656usize];
["Offset of field: EmpyreanPropagatedState::has_stt"]
[::std::mem::offset_of!(EmpyreanPropagatedState, has_stt) - 2384usize];
["Offset of field: EmpyreanPropagatedState::resolved_kind"]
[::std::mem::offset_of!(EmpyreanPropagatedState, resolved_kind) - 2385usize];
};
#[doc = " A detected dynamical event from propagation.\n\n For `event_type = \"covariance_regime_change\"` the audit-trail\n fields (`previous_kind`, `resolved_kind`, `kappa`,\n `threshold_below`, `threshold_above`) carry the\n [`CovarianceRegimeChange`](empyrean_core::propagation::events::DynamicalEvent::CovarianceRegimeChange)\n payload and the body / distance / velocity fields are zeroed\n (regime changes don't carry a body or geometry — they're audit\n markers from\n [`UncertaintyMethod::Auto`](empyrean_core::propagation::UncertaintyMethod::Auto)).\n For all other events these fields are sentinel-filled\n (`0xFF` / NaN).\n\n Field names mirror empyrean-core's variant fields for the\n regime-change payload — no per-variant prefix."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanEvent {
pub event_type: *mut ::std::os::raw::c_char,
pub orbit_id: *mut ::std::os::raw::c_char,
#[doc = " Object identifier looked up by `orbit_id` from the input batch.\n Empty string when the input had no `object_id`. Owning C string —\n caller frees via `*_result_free`."]
pub object_id: *mut ::std::os::raw::c_char,
pub body: *mut ::std::os::raw::c_char,
pub body_naif_id: i32,
pub epoch_mjd_tdb: f64,
pub distance_au: f64,
pub distance_km: f64,
pub relative_velocity_au_day: f64,
#[doc = " `CovarianceRegimeChange` payload: previous resolved kind.\n Sentinel `0xFF` for non-regime events."]
pub previous_kind: u8,
#[doc = " `CovarianceRegimeChange` payload: new resolved kind.\n Sentinel `0xFF` for non-regime events."]
pub resolved_kind: u8,
#[doc = " `CovarianceRegimeChange` payload: local nonlinearity κ\n recorded at the CA. NaN for non-regime events."]
pub kappa: f64,
#[doc = " `CovarianceRegimeChange` payload: lower κ value recorded in\n this audit payload. NaN for non-regime events."]
pub threshold_below: f64,
#[doc = " `CovarianceRegimeChange` payload: upper κ value recorded in\n this audit payload. NaN for non-regime events."]
pub threshold_above: f64,
#[doc = " `CaptureStart` / `CaptureEnd` payload: two-body energy w.r.t. the\n capturing body (AU²/day²). NaN for non-capture events."]
pub two_body_energy: f64,
#[doc = " `CaptureStart` / `CaptureEnd` payload: Jacobi constant in the\n CR3BP. NaN for non-capture events or when unavailable."]
pub jacobi_constant: f64,
#[doc = " `CaptureStart` / `CaptureEnd` payload: 1σ uncertainty on the\n Jacobi constant. NaN when unavailable."]
pub jacobi_constant_sigma: f64,
#[doc = " `CaptureStart` / `CaptureEnd` payload: Jacobi constant at the L1\n gateway. NaN when unavailable."]
pub jacobi_constant_l1: f64,
#[doc = " `CaptureStart` / `CaptureEnd` payload: Jacobi constant at the L2\n gateway. NaN when unavailable."]
pub jacobi_constant_l2: f64,
#[doc = " `CaptureEnd` payload: number of periapsis passages during the\n temporary capture. `-1` sentinel for non-`CaptureEnd` events."]
pub n_periapses: i32,
#[doc = " `Impact` payload: planetodetic latitude of the surface intercept\n (degrees). NaN for non-impact events or when unresolved."]
pub impact_latitude_deg: f64,
#[doc = " `Impact` payload: planetodetic longitude of the surface intercept\n (degrees). NaN for non-impact events or when unresolved."]
pub impact_longitude_deg: f64,
#[doc = " `Impact` payload: altitude of the surface intercept above the\n reference ellipsoid (km). NaN for non-impact events or when\n unresolved."]
pub impact_altitude_km: f64,
#[doc = " `ShadowEntry` / `ShadowExit` payload: fraction of the Sun's disk\n occulted by the body (0 = none, 1 = full umbra). NaN for\n non-shadow events."]
pub shadow_fraction: f64,
#[doc = " `ShadowEntry` / `ShadowExit` payload: fraction of incident\n sunlight reaching the particle (1 = full sun, 0 = total eclipse).\n NaN for non-shadow events."]
pub illumination: f64,
#[doc = " `Periapsis` payload: relative position w.r.t. the approached body\n (AU), components x/y/z. NaN for non-periapsis events."]
pub relative_x: f64,
pub relative_y: f64,
pub relative_z: f64,
#[doc = " `Periapsis` payload: relative velocity w.r.t. the approached body\n (AU/day), components vx/vy/vz. NaN for non-periapsis events."]
pub relative_vx: f64,
pub relative_vy: f64,
pub relative_vz: f64,
#[doc = " `PossibleImpact` payload: effective capture radius with\n gravitational focusing (AU / km). NaN for non-possible-impact events."]
pub effective_radius_au: f64,
pub effective_radius_km: f64,
#[doc = " `PossibleImpact` payload: 1σ uncertainty along the miss direction\n (AU). NaN for non-possible-impact events."]
pub sigma_distance_au: f64,
#[doc = " `PossibleImpact` payload: linear (STM-mapped) impact probability.\n NaN for non-possible-impact events."]
pub ip_linear: f64,
#[doc = " `PossibleImpact` payload: second-order (Edgeworth) impact\n probability. NaN for non-possible-impact / first-order runs."]
pub ip_second_order: f64,
#[doc = " `PossibleImpact` payload: local nonlinearity κ at the encounter.\n NaN when unavailable."]
pub nonlinearity: f64,
#[doc = " `PossibleImpact` payload: adaptive-Gaussian-mixture impact\n probability. NaN when not an AGM run."]
pub ip_agm: f64,
#[doc = " `PossibleImpact` payload: Monte-Carlo impact probability. NaN when\n not a Monte-Carlo run."]
pub ip_mc: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanEvent"][::std::mem::size_of::<EmpyreanEvent>() - 304usize];
["Alignment of EmpyreanEvent"][::std::mem::align_of::<EmpyreanEvent>() - 8usize];
["Offset of field: EmpyreanEvent::event_type"]
[::std::mem::offset_of!(EmpyreanEvent, event_type) - 0usize];
["Offset of field: EmpyreanEvent::orbit_id"]
[::std::mem::offset_of!(EmpyreanEvent, orbit_id) - 8usize];
["Offset of field: EmpyreanEvent::object_id"]
[::std::mem::offset_of!(EmpyreanEvent, object_id) - 16usize];
["Offset of field: EmpyreanEvent::body"][::std::mem::offset_of!(EmpyreanEvent, body) - 24usize];
["Offset of field: EmpyreanEvent::body_naif_id"]
[::std::mem::offset_of!(EmpyreanEvent, body_naif_id) - 32usize];
["Offset of field: EmpyreanEvent::epoch_mjd_tdb"]
[::std::mem::offset_of!(EmpyreanEvent, epoch_mjd_tdb) - 40usize];
["Offset of field: EmpyreanEvent::distance_au"]
[::std::mem::offset_of!(EmpyreanEvent, distance_au) - 48usize];
["Offset of field: EmpyreanEvent::distance_km"]
[::std::mem::offset_of!(EmpyreanEvent, distance_km) - 56usize];
["Offset of field: EmpyreanEvent::relative_velocity_au_day"]
[::std::mem::offset_of!(EmpyreanEvent, relative_velocity_au_day) - 64usize];
["Offset of field: EmpyreanEvent::previous_kind"]
[::std::mem::offset_of!(EmpyreanEvent, previous_kind) - 72usize];
["Offset of field: EmpyreanEvent::resolved_kind"]
[::std::mem::offset_of!(EmpyreanEvent, resolved_kind) - 73usize];
["Offset of field: EmpyreanEvent::kappa"]
[::std::mem::offset_of!(EmpyreanEvent, kappa) - 80usize];
["Offset of field: EmpyreanEvent::threshold_below"]
[::std::mem::offset_of!(EmpyreanEvent, threshold_below) - 88usize];
["Offset of field: EmpyreanEvent::threshold_above"]
[::std::mem::offset_of!(EmpyreanEvent, threshold_above) - 96usize];
["Offset of field: EmpyreanEvent::two_body_energy"]
[::std::mem::offset_of!(EmpyreanEvent, two_body_energy) - 104usize];
["Offset of field: EmpyreanEvent::jacobi_constant"]
[::std::mem::offset_of!(EmpyreanEvent, jacobi_constant) - 112usize];
["Offset of field: EmpyreanEvent::jacobi_constant_sigma"]
[::std::mem::offset_of!(EmpyreanEvent, jacobi_constant_sigma) - 120usize];
["Offset of field: EmpyreanEvent::jacobi_constant_l1"]
[::std::mem::offset_of!(EmpyreanEvent, jacobi_constant_l1) - 128usize];
["Offset of field: EmpyreanEvent::jacobi_constant_l2"]
[::std::mem::offset_of!(EmpyreanEvent, jacobi_constant_l2) - 136usize];
["Offset of field: EmpyreanEvent::n_periapses"]
[::std::mem::offset_of!(EmpyreanEvent, n_periapses) - 144usize];
["Offset of field: EmpyreanEvent::impact_latitude_deg"]
[::std::mem::offset_of!(EmpyreanEvent, impact_latitude_deg) - 152usize];
["Offset of field: EmpyreanEvent::impact_longitude_deg"]
[::std::mem::offset_of!(EmpyreanEvent, impact_longitude_deg) - 160usize];
["Offset of field: EmpyreanEvent::impact_altitude_km"]
[::std::mem::offset_of!(EmpyreanEvent, impact_altitude_km) - 168usize];
["Offset of field: EmpyreanEvent::shadow_fraction"]
[::std::mem::offset_of!(EmpyreanEvent, shadow_fraction) - 176usize];
["Offset of field: EmpyreanEvent::illumination"]
[::std::mem::offset_of!(EmpyreanEvent, illumination) - 184usize];
["Offset of field: EmpyreanEvent::relative_x"]
[::std::mem::offset_of!(EmpyreanEvent, relative_x) - 192usize];
["Offset of field: EmpyreanEvent::relative_y"]
[::std::mem::offset_of!(EmpyreanEvent, relative_y) - 200usize];
["Offset of field: EmpyreanEvent::relative_z"]
[::std::mem::offset_of!(EmpyreanEvent, relative_z) - 208usize];
["Offset of field: EmpyreanEvent::relative_vx"]
[::std::mem::offset_of!(EmpyreanEvent, relative_vx) - 216usize];
["Offset of field: EmpyreanEvent::relative_vy"]
[::std::mem::offset_of!(EmpyreanEvent, relative_vy) - 224usize];
["Offset of field: EmpyreanEvent::relative_vz"]
[::std::mem::offset_of!(EmpyreanEvent, relative_vz) - 232usize];
["Offset of field: EmpyreanEvent::effective_radius_au"]
[::std::mem::offset_of!(EmpyreanEvent, effective_radius_au) - 240usize];
["Offset of field: EmpyreanEvent::effective_radius_km"]
[::std::mem::offset_of!(EmpyreanEvent, effective_radius_km) - 248usize];
["Offset of field: EmpyreanEvent::sigma_distance_au"]
[::std::mem::offset_of!(EmpyreanEvent, sigma_distance_au) - 256usize];
["Offset of field: EmpyreanEvent::ip_linear"]
[::std::mem::offset_of!(EmpyreanEvent, ip_linear) - 264usize];
["Offset of field: EmpyreanEvent::ip_second_order"]
[::std::mem::offset_of!(EmpyreanEvent, ip_second_order) - 272usize];
["Offset of field: EmpyreanEvent::nonlinearity"]
[::std::mem::offset_of!(EmpyreanEvent, nonlinearity) - 280usize];
["Offset of field: EmpyreanEvent::ip_agm"]
[::std::mem::offset_of!(EmpyreanEvent, ip_agm) - 288usize];
["Offset of field: EmpyreanEvent::ip_mc"]
[::std::mem::offset_of!(EmpyreanEvent, ip_mc) - 296usize];
};
impl Default for EmpyreanEvent {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " One Gaussian sub-component of an AGM mixture decomposition.\n\n Mirrors\n [`empyrean_core::propagation::MixtureComponent`]. The mean carries\n the *propagated* sub-Gaussian centroid at the CA epoch (f64 from\n the Jet2 integrator); the covariance is the linearly-mapped\n \\\\(\\Phi \\, \\Sigma_k \\, \\Phi^\\top\\\\) over the same propagation\n segment. A consumer can evaluate\n \\\\(\\sum_k w_k \\\\, \\mathcal{N}(x \\mid \\mu_k, \\Sigma_k)\\\\) directly\n at the CA epoch."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanMixtureComponent {
pub weight: f64,
pub mean: [f64; 6usize],
pub covariance: [[f64; 6usize]; 6usize],
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanMixtureComponent"]
[::std::mem::size_of::<EmpyreanMixtureComponent>() - 344usize];
["Alignment of EmpyreanMixtureComponent"]
[::std::mem::align_of::<EmpyreanMixtureComponent>() - 8usize];
["Offset of field: EmpyreanMixtureComponent::weight"]
[::std::mem::offset_of!(EmpyreanMixtureComponent, weight) - 0usize];
["Offset of field: EmpyreanMixtureComponent::mean"]
[::std::mem::offset_of!(EmpyreanMixtureComponent, mean) - 8usize];
["Offset of field: EmpyreanMixtureComponent::covariance"]
[::std::mem::offset_of!(EmpyreanMixtureComponent, covariance) - 56usize];
};
#[doc = " Per-orbit AGM mixture decomposition retained by Auto / Mixture.\n\n Mirrors [`empyrean_core::propagation::MixtureChain`] in flat form.\n `ca_epochs_mjd_tdb` and `components_per_epoch` are\n `num_ca_epochs`-length parallel arrays. Components are flattened\n into a single `components` array — for CA index `k`, the slice is\n `components[components_offset[k] .. components_offset[k] +\n components_per_epoch[k]]`. `components_offset[k]` is the\n prefix-sum of `components_per_epoch[0..k]` (so\n `components_offset[0] == 0`).\n\n Only orbits whose AGM splits actually fired carry a chain;\n non-mixture orbits get one entry whose `num_ca_epochs == 0` and\n whose pointers are null."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanMixtureChain {
#[doc = " Owning C string — caller frees via `*_result_free`."]
pub orbit_id: *mut ::std::os::raw::c_char,
#[doc = " `num_ca_epochs`-length array of CA epochs (mjd_tdb)."]
pub ca_epochs_mjd_tdb: *mut f64,
pub num_ca_epochs: usize,
#[doc = " `num_ca_epochs`-length array of per-epoch component counts."]
pub components_per_epoch: *mut usize,
#[doc = " `num_ca_epochs`-length array of starting offsets into the\n flattened `components` array. `components_offset[k]` is the\n prefix-sum of `components_per_epoch[0..k]`."]
pub components_offset: *mut usize,
#[doc = " Flattened components — total length =\n sum(components_per_epoch)."]
pub components: *mut EmpyreanMixtureComponent,
pub num_components_total: usize,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanMixtureChain"][::std::mem::size_of::<EmpyreanMixtureChain>() - 56usize];
["Alignment of EmpyreanMixtureChain"][::std::mem::align_of::<EmpyreanMixtureChain>() - 8usize];
["Offset of field: EmpyreanMixtureChain::orbit_id"]
[::std::mem::offset_of!(EmpyreanMixtureChain, orbit_id) - 0usize];
["Offset of field: EmpyreanMixtureChain::ca_epochs_mjd_tdb"]
[::std::mem::offset_of!(EmpyreanMixtureChain, ca_epochs_mjd_tdb) - 8usize];
["Offset of field: EmpyreanMixtureChain::num_ca_epochs"]
[::std::mem::offset_of!(EmpyreanMixtureChain, num_ca_epochs) - 16usize];
["Offset of field: EmpyreanMixtureChain::components_per_epoch"]
[::std::mem::offset_of!(EmpyreanMixtureChain, components_per_epoch) - 24usize];
["Offset of field: EmpyreanMixtureChain::components_offset"]
[::std::mem::offset_of!(EmpyreanMixtureChain, components_offset) - 32usize];
["Offset of field: EmpyreanMixtureChain::components"]
[::std::mem::offset_of!(EmpyreanMixtureChain, components) - 40usize];
["Offset of field: EmpyreanMixtureChain::num_components_total"]
[::std::mem::offset_of!(EmpyreanMixtureChain, num_components_total) - 48usize];
};
impl Default for EmpyreanMixtureChain {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Propagation result containing states, events, and object identifiers.\n\n `mixtures` parallels `object_ids` only when populated — it is\n per-orbit (not per-state), so its length is the distinct orbit\n count, not `num_states`."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanPropagationResult {
pub states: *mut EmpyreanPropagatedState,
pub num_states: usize,
pub object_ids: *mut *mut ::std::os::raw::c_char,
pub events: *mut EmpyreanEvent,
pub num_events: usize,
#[doc = " One [`EmpyreanMixtureChain`] per input orbit (positional with\n the input orbit batch). Empty / null when no orbits produced\n mixtures (the typical case for FirstOrder / SecondOrder /\n SigmaPoint / MonteCarlo)."]
pub mixtures: *mut EmpyreanMixtureChain,
pub num_mixtures: usize,
#[doc = " Opaque retained handle to the rich propagation result, enabling\n the on-demand tagged-covariance accessors\n (`empyrean_propagation_covariance_series_cartesian` /\n `_covariance_at_cartesian`). **Do not dereference from C** — it is\n freed by `empyrean_propagation_result_free`. Null when the\n propagation produced no retainable result."]
pub lazy_handle: *mut ::std::os::raw::c_void,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanPropagationResult"]
[::std::mem::size_of::<EmpyreanPropagationResult>() - 64usize];
["Alignment of EmpyreanPropagationResult"]
[::std::mem::align_of::<EmpyreanPropagationResult>() - 8usize];
["Offset of field: EmpyreanPropagationResult::states"]
[::std::mem::offset_of!(EmpyreanPropagationResult, states) - 0usize];
["Offset of field: EmpyreanPropagationResult::num_states"]
[::std::mem::offset_of!(EmpyreanPropagationResult, num_states) - 8usize];
["Offset of field: EmpyreanPropagationResult::object_ids"]
[::std::mem::offset_of!(EmpyreanPropagationResult, object_ids) - 16usize];
["Offset of field: EmpyreanPropagationResult::events"]
[::std::mem::offset_of!(EmpyreanPropagationResult, events) - 24usize];
["Offset of field: EmpyreanPropagationResult::num_events"]
[::std::mem::offset_of!(EmpyreanPropagationResult, num_events) - 32usize];
["Offset of field: EmpyreanPropagationResult::mixtures"]
[::std::mem::offset_of!(EmpyreanPropagationResult, mixtures) - 40usize];
["Offset of field: EmpyreanPropagationResult::num_mixtures"]
[::std::mem::offset_of!(EmpyreanPropagationResult, num_mixtures) - 48usize];
["Offset of field: EmpyreanPropagationResult::lazy_handle"]
[::std::mem::offset_of!(EmpyreanPropagationResult, lazy_handle) - 56usize];
};
impl Default for EmpyreanPropagationResult {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " A single observer state for the C API."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanObserver {
#[doc = " MPC 3-character code, null-terminated (4 bytes)."]
pub obs_code: [u8; 4usize],
#[doc = " Epoch as MJD TDB."]
pub epoch_mjd_tdb: f64,
#[doc = " Position in ICRF relative to SSB (AU)."]
pub x: f64,
pub y: f64,
pub z: f64,
#[doc = " Velocity in ICRF relative to SSB (AU/day)."]
pub vx: f64,
pub vy: f64,
pub vz: f64,
#[doc = " Observing night as YYYYMMDD integer, or -1 if unavailable."]
pub observing_night: i32,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanObserver"][::std::mem::size_of::<EmpyreanObserver>() - 72usize];
["Alignment of EmpyreanObserver"][::std::mem::align_of::<EmpyreanObserver>() - 8usize];
["Offset of field: EmpyreanObserver::obs_code"]
[::std::mem::offset_of!(EmpyreanObserver, obs_code) - 0usize];
["Offset of field: EmpyreanObserver::epoch_mjd_tdb"]
[::std::mem::offset_of!(EmpyreanObserver, epoch_mjd_tdb) - 8usize];
["Offset of field: EmpyreanObserver::x"][::std::mem::offset_of!(EmpyreanObserver, x) - 16usize];
["Offset of field: EmpyreanObserver::y"][::std::mem::offset_of!(EmpyreanObserver, y) - 24usize];
["Offset of field: EmpyreanObserver::z"][::std::mem::offset_of!(EmpyreanObserver, z) - 32usize];
["Offset of field: EmpyreanObserver::vx"]
[::std::mem::offset_of!(EmpyreanObserver, vx) - 40usize];
["Offset of field: EmpyreanObserver::vy"]
[::std::mem::offset_of!(EmpyreanObserver, vy) - 48usize];
["Offset of field: EmpyreanObserver::vz"]
[::std::mem::offset_of!(EmpyreanObserver, vz) - 56usize];
["Offset of field: EmpyreanObserver::observing_night"]
[::std::mem::offset_of!(EmpyreanObserver, observing_night) - 64usize];
};
#[doc = " Ephemeris-generation configuration.\n\n Wraps the inner [`EmpyreanPropagationConfig`] (force model,\n uncertainty method, output frame) plus the light-time iteration\n controls and a diagnostics toggle. The propagation runs internally\n to bring each orbit to its observation epoch, so every\n propagation-level knob applies here too."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanEphemerisConfig {
#[doc = " Inner propagation configuration applied to the trajectory that\n brings each orbit to its observation epoch."]
pub propagation: EmpyreanPropagationConfig,
#[doc = " Maximum iterations for light-time convergence. 0 → use the\n upstream default (3)."]
pub max_light_time_iterations: usize,
#[doc = " Tolerance (days) for light-time convergence. 0.0 → upstream\n default (1e-10)."]
pub light_time_tolerance_days: f64,
#[doc = " 1 = compute phase angle / elongation / heliocentric distance /\n apparent magnitude. 0 = skip (faster; appropriate for OD inner\n loops that only need RA/Dec)."]
pub compute_diagnostics: u8,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanEphemerisConfig"]
[::std::mem::size_of::<EmpyreanEphemerisConfig>() - 312usize];
["Alignment of EmpyreanEphemerisConfig"]
[::std::mem::align_of::<EmpyreanEphemerisConfig>() - 8usize];
["Offset of field: EmpyreanEphemerisConfig::propagation"]
[::std::mem::offset_of!(EmpyreanEphemerisConfig, propagation) - 0usize];
["Offset of field: EmpyreanEphemerisConfig::max_light_time_iterations"]
[::std::mem::offset_of!(EmpyreanEphemerisConfig, max_light_time_iterations) - 288usize];
["Offset of field: EmpyreanEphemerisConfig::light_time_tolerance_days"]
[::std::mem::offset_of!(EmpyreanEphemerisConfig, light_time_tolerance_days) - 296usize];
["Offset of field: EmpyreanEphemerisConfig::compute_diagnostics"]
[::std::mem::offset_of!(EmpyreanEphemerisConfig, compute_diagnostics) - 304usize];
};
impl Default for EmpyreanEphemerisConfig {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " A single predicted ephemeris entry."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanEphemerisEntry {
#[doc = " Orbit identifier (heap-allocated, freed by empyrean_ephemeris_result_free)."]
pub orbit_id: *mut ::std::os::raw::c_char,
#[doc = " Epoch as MJD TDB."]
pub epoch_mjd_tdb: f64,
#[doc = " Right ascension (degrees)."]
pub ra_deg: f64,
#[doc = " Declination (degrees)."]
pub dec_deg: f64,
#[doc = " Topocentric distance (AU)."]
pub rho_au: f64,
#[doc = " Radial velocity (AU/day)."]
pub vrho_au_day: f64,
#[doc = " RA rate (deg/day)."]
pub vra_deg_day: f64,
#[doc = " Dec rate (deg/day)."]
pub vdec_deg_day: f64,
#[doc = " One-way light time (days). NaN if unavailable."]
pub light_time_days: f64,
#[doc = " Phase angle (degrees). NaN if unavailable."]
pub phase_angle_deg: f64,
#[doc = " Solar elongation (degrees). NaN if unavailable."]
pub elongation_deg: f64,
#[doc = " Heliocentric distance (AU). NaN if unavailable."]
pub heliocentric_distance_au: f64,
#[doc = " Predicted apparent magnitude. NaN if unavailable."]
pub mag: f64,
#[doc = " Magnitude uncertainty. NaN if unavailable."]
pub mag_sigma: f64,
#[doc = " Topocentric zenith angle (degrees). NaN if unavailable (e.g. no\n observer geodetic position)."]
pub zenith_angle_deg: f64,
#[doc = " Topocentric azimuth, East of North (degrees). NaN if unavailable."]
pub azimuth_deg: f64,
#[doc = " Local hour angle (degrees). NaN if unavailable."]
pub hour_angle_deg: f64,
#[doc = " Angular separation from the Moon (degrees). NaN if unavailable."]
pub lunar_elongation_deg: f64,
#[doc = " Position angle of motion, East of North (degrees). NaN if unavailable."]
pub position_angle_deg: f64,
#[doc = " Total apparent sky-plane rate of motion (degrees/day). NaN if\n unavailable."]
pub sky_rate_deg_day: f64,
#[doc = " Observer code, null-terminated (4 bytes)."]
pub obs_code: [u8; 4usize],
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanEphemerisEntry"][::std::mem::size_of::<EmpyreanEphemerisEntry>() - 168usize];
["Alignment of EmpyreanEphemerisEntry"]
[::std::mem::align_of::<EmpyreanEphemerisEntry>() - 8usize];
["Offset of field: EmpyreanEphemerisEntry::orbit_id"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, orbit_id) - 0usize];
["Offset of field: EmpyreanEphemerisEntry::epoch_mjd_tdb"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, epoch_mjd_tdb) - 8usize];
["Offset of field: EmpyreanEphemerisEntry::ra_deg"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, ra_deg) - 16usize];
["Offset of field: EmpyreanEphemerisEntry::dec_deg"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, dec_deg) - 24usize];
["Offset of field: EmpyreanEphemerisEntry::rho_au"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, rho_au) - 32usize];
["Offset of field: EmpyreanEphemerisEntry::vrho_au_day"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, vrho_au_day) - 40usize];
["Offset of field: EmpyreanEphemerisEntry::vra_deg_day"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, vra_deg_day) - 48usize];
["Offset of field: EmpyreanEphemerisEntry::vdec_deg_day"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, vdec_deg_day) - 56usize];
["Offset of field: EmpyreanEphemerisEntry::light_time_days"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, light_time_days) - 64usize];
["Offset of field: EmpyreanEphemerisEntry::phase_angle_deg"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, phase_angle_deg) - 72usize];
["Offset of field: EmpyreanEphemerisEntry::elongation_deg"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, elongation_deg) - 80usize];
["Offset of field: EmpyreanEphemerisEntry::heliocentric_distance_au"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, heliocentric_distance_au) - 88usize];
["Offset of field: EmpyreanEphemerisEntry::mag"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, mag) - 96usize];
["Offset of field: EmpyreanEphemerisEntry::mag_sigma"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, mag_sigma) - 104usize];
["Offset of field: EmpyreanEphemerisEntry::zenith_angle_deg"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, zenith_angle_deg) - 112usize];
["Offset of field: EmpyreanEphemerisEntry::azimuth_deg"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, azimuth_deg) - 120usize];
["Offset of field: EmpyreanEphemerisEntry::hour_angle_deg"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, hour_angle_deg) - 128usize];
["Offset of field: EmpyreanEphemerisEntry::lunar_elongation_deg"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, lunar_elongation_deg) - 136usize];
["Offset of field: EmpyreanEphemerisEntry::position_angle_deg"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, position_angle_deg) - 144usize];
["Offset of field: EmpyreanEphemerisEntry::sky_rate_deg_day"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, sky_rate_deg_day) - 152usize];
["Offset of field: EmpyreanEphemerisEntry::obs_code"]
[::std::mem::offset_of!(EmpyreanEphemerisEntry, obs_code) - 160usize];
};
impl Default for EmpyreanEphemerisEntry {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " One observation-sensitivity row — the partial derivatives of the\n sky-plane observable w.r.t. the input state, for a single\n `(orbit, observer, epoch)`. One row per observation epoch within each\n `(orbit_id, obs_code)` chain. Owning struct: free\n the whole result with [`empyrean_ephemeris_result_free`]."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanObservationSensitivity {
#[doc = " Orbit identifier. Owning C string."]
pub orbit_id: *mut ::std::os::raw::c_char,
#[doc = " Object identifier (owning C string) or null when absent."]
pub object_id: *mut ::std::os::raw::c_char,
#[doc = " MPC observatory code, null-terminated (4 bytes)."]
pub obs_code: [u8; 4usize],
#[doc = " Observation epoch (MJD TDB)."]
pub epoch_mjd_tdb: f64,
#[doc = " Solved-parameter dimension: 6 (state) or 9 (state + non-grav)."]
pub n_params: u8,
#[doc = " Jacobian ∂(observable)/∂(input), row-major `[6][n_params]` flattened\n (length `6 * n_params`). Null when this epoch carries no Jacobian."]
pub jacobian: *mut f64,
#[doc = " Length of `jacobian` (`6 * n_params`), 0 when null."]
pub jacobian_len: usize,
#[doc = " Hessian ∂²(observable)/∂(input)², row-major `[6][n_params][n_params]`\n flattened (length `6 * n_params * n_params`). Null unless a\n second-order method (Jet2) ran."]
pub hessian: *mut f64,
#[doc = " Length of `hessian` (`6 * n_params²`), 0 when null."]
pub hessian_len: usize,
#[doc = " Frame of the input axis (Frame enum as int)."]
pub frame: i32,
#[doc = " Origin of the input axis (NAIF id)."]
pub origin: i32,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanObservationSensitivity"]
[::std::mem::size_of::<EmpyreanObservationSensitivity>() - 80usize];
["Alignment of EmpyreanObservationSensitivity"]
[::std::mem::align_of::<EmpyreanObservationSensitivity>() - 8usize];
["Offset of field: EmpyreanObservationSensitivity::orbit_id"]
[::std::mem::offset_of!(EmpyreanObservationSensitivity, orbit_id) - 0usize];
["Offset of field: EmpyreanObservationSensitivity::object_id"]
[::std::mem::offset_of!(EmpyreanObservationSensitivity, object_id) - 8usize];
["Offset of field: EmpyreanObservationSensitivity::obs_code"]
[::std::mem::offset_of!(EmpyreanObservationSensitivity, obs_code) - 16usize];
["Offset of field: EmpyreanObservationSensitivity::epoch_mjd_tdb"]
[::std::mem::offset_of!(EmpyreanObservationSensitivity, epoch_mjd_tdb) - 24usize];
["Offset of field: EmpyreanObservationSensitivity::n_params"]
[::std::mem::offset_of!(EmpyreanObservationSensitivity, n_params) - 32usize];
["Offset of field: EmpyreanObservationSensitivity::jacobian"]
[::std::mem::offset_of!(EmpyreanObservationSensitivity, jacobian) - 40usize];
["Offset of field: EmpyreanObservationSensitivity::jacobian_len"]
[::std::mem::offset_of!(EmpyreanObservationSensitivity, jacobian_len) - 48usize];
["Offset of field: EmpyreanObservationSensitivity::hessian"]
[::std::mem::offset_of!(EmpyreanObservationSensitivity, hessian) - 56usize];
["Offset of field: EmpyreanObservationSensitivity::hessian_len"]
[::std::mem::offset_of!(EmpyreanObservationSensitivity, hessian_len) - 64usize];
["Offset of field: EmpyreanObservationSensitivity::frame"]
[::std::mem::offset_of!(EmpyreanObservationSensitivity, frame) - 72usize];
["Offset of field: EmpyreanObservationSensitivity::origin"]
[::std::mem::offset_of!(EmpyreanObservationSensitivity, origin) - 76usize];
};
impl Default for EmpyreanObservationSensitivity {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Result containing an array of ephemeris entries and, when an\n uncertainty method traced the STM, the observation-sensitivity chains."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanEphemerisResult {
pub entries: *mut EmpyreanEphemerisEntry,
pub num_entries: usize,
#[doc = " Per-`(orbit, observer, epoch)` sensitivity rows. Null / 0 when no\n STM was traced (e.g. an f64-only path)."]
pub sensitivity: *mut EmpyreanObservationSensitivity,
pub num_sensitivity: usize,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanEphemerisResult"][::std::mem::size_of::<EmpyreanEphemerisResult>() - 32usize];
["Alignment of EmpyreanEphemerisResult"]
[::std::mem::align_of::<EmpyreanEphemerisResult>() - 8usize];
["Offset of field: EmpyreanEphemerisResult::entries"]
[::std::mem::offset_of!(EmpyreanEphemerisResult, entries) - 0usize];
["Offset of field: EmpyreanEphemerisResult::num_entries"]
[::std::mem::offset_of!(EmpyreanEphemerisResult, num_entries) - 8usize];
["Offset of field: EmpyreanEphemerisResult::sensitivity"]
[::std::mem::offset_of!(EmpyreanEphemerisResult, sensitivity) - 16usize];
["Offset of field: EmpyreanEphemerisResult::num_sensitivity"]
[::std::mem::offset_of!(EmpyreanEphemerisResult, num_sensitivity) - 24usize];
};
impl Default for EmpyreanEphemerisResult {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " One entry of the kernel-identity manifest captured by a handle.\n\n Names the provenance of each loaded data file — never any tuning\n rationale. Free the owning [`EmpyreanSystemDescription`] with\n [`empyrean_builtsystem_description_free`]; do not free these fields\n individually."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanKernelRecord {
#[doc = " Category of the entry (`EMPYREAN_KERNEL_KIND_*`)."]
pub kind: i32,
#[doc = " Where the entry came from (`EMPYREAN_KERNEL_PROVENANCE_*`)."]
pub provenance: i32,
#[doc = " Absolute path the kernel was loaded from. Non-null only for a\n `FILE` provenance; null otherwise. NUL-terminated UTF-8."]
pub path: *mut ::std::os::raw::c_char,
#[doc = " Lowercase-hex SHA-256 of the file's bytes (64 chars). Non-null only\n for a `FILE` provenance; null otherwise. NUL-terminated UTF-8."]
pub sha256: *mut ::std::os::raw::c_char,
#[doc = " Hashed file size in bytes. 0 unless `FILE` provenance."]
pub bytes: u64,
#[doc = " Human-readable model name. Non-null only for a `BUILT_IN`\n provenance; null otherwise. NUL-terminated UTF-8."]
pub name: *mut ::std::os::raw::c_char,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanKernelRecord"][::std::mem::size_of::<EmpyreanKernelRecord>() - 40usize];
["Alignment of EmpyreanKernelRecord"][::std::mem::align_of::<EmpyreanKernelRecord>() - 8usize];
["Offset of field: EmpyreanKernelRecord::kind"]
[::std::mem::offset_of!(EmpyreanKernelRecord, kind) - 0usize];
["Offset of field: EmpyreanKernelRecord::provenance"]
[::std::mem::offset_of!(EmpyreanKernelRecord, provenance) - 4usize];
["Offset of field: EmpyreanKernelRecord::path"]
[::std::mem::offset_of!(EmpyreanKernelRecord, path) - 8usize];
["Offset of field: EmpyreanKernelRecord::sha256"]
[::std::mem::offset_of!(EmpyreanKernelRecord, sha256) - 16usize];
["Offset of field: EmpyreanKernelRecord::bytes"]
[::std::mem::offset_of!(EmpyreanKernelRecord, bytes) - 24usize];
["Offset of field: EmpyreanKernelRecord::name"]
[::std::mem::offset_of!(EmpyreanKernelRecord, name) - 32usize];
};
impl Default for EmpyreanKernelRecord {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " A reproducibility summary of a handle's frozen force model plus its\n captured kernel-identity manifest.\n\n Populated in full by [`empyrean_builtsystem_describe`] — every field\n reflects the assembled system; nothing is defaulted. Names the citable\n menu (tier, frame, GR, perturbers, BPC, kernel hashes) — never selection\n logic or tuning rationale. Release the heap-owned arrays with\n [`empyrean_builtsystem_description_free`]."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanSystemDescription {
#[doc = " Force-model tier: 0=Approximate, 1=Basic, 2=Standard."]
pub force_model: i32,
#[doc = " Integration/output frame: 0=ICRF, 1=EclipticJ2000, 2=ITRF93."]
pub frame: i32,
#[doc = " The frozen encounter-timescale divisor."]
pub encounter_timescale_divisor: f64,
#[doc = " 1 if the post-Newtonian (EIH) GR correction is enabled, else 0."]
pub relativistic: u8,
#[doc = " 1 if the N16 asteroid perturbers are included, else 0."]
pub asteroids: u8,
#[doc = " 1 if a BPC (body-fixed rotation) kernel is loaded, else 0."]
pub has_bpc: u8,
#[doc = " Heap array of perturbing-body NAIF ids (length `num_perturbers`).\n Null when `num_perturbers == 0`."]
pub perturber_origins: *mut i32,
#[doc = " Number of entries in [`perturber_origins`](Self::perturber_origins)."]
pub num_perturbers: usize,
#[doc = " Heap array of kernel-identity records (length `num_kernels`). Null\n when `num_kernels == 0`."]
pub kernels: *mut EmpyreanKernelRecord,
#[doc = " Number of entries in [`kernels`](Self::kernels)."]
pub num_kernels: usize,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanSystemDescription"]
[::std::mem::size_of::<EmpyreanSystemDescription>() - 56usize];
["Alignment of EmpyreanSystemDescription"]
[::std::mem::align_of::<EmpyreanSystemDescription>() - 8usize];
["Offset of field: EmpyreanSystemDescription::force_model"]
[::std::mem::offset_of!(EmpyreanSystemDescription, force_model) - 0usize];
["Offset of field: EmpyreanSystemDescription::frame"]
[::std::mem::offset_of!(EmpyreanSystemDescription, frame) - 4usize];
["Offset of field: EmpyreanSystemDescription::encounter_timescale_divisor"]
[::std::mem::offset_of!(EmpyreanSystemDescription, encounter_timescale_divisor) - 8usize];
["Offset of field: EmpyreanSystemDescription::relativistic"]
[::std::mem::offset_of!(EmpyreanSystemDescription, relativistic) - 16usize];
["Offset of field: EmpyreanSystemDescription::asteroids"]
[::std::mem::offset_of!(EmpyreanSystemDescription, asteroids) - 17usize];
["Offset of field: EmpyreanSystemDescription::has_bpc"]
[::std::mem::offset_of!(EmpyreanSystemDescription, has_bpc) - 18usize];
["Offset of field: EmpyreanSystemDescription::perturber_origins"]
[::std::mem::offset_of!(EmpyreanSystemDescription, perturber_origins) - 24usize];
["Offset of field: EmpyreanSystemDescription::num_perturbers"]
[::std::mem::offset_of!(EmpyreanSystemDescription, num_perturbers) - 32usize];
["Offset of field: EmpyreanSystemDescription::kernels"]
[::std::mem::offset_of!(EmpyreanSystemDescription, kernels) - 40usize];
["Offset of field: EmpyreanSystemDescription::num_kernels"]
[::std::mem::offset_of!(EmpyreanSystemDescription, num_kernels) - 48usize];
};
impl Default for EmpyreanSystemDescription {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " One impact-probability record emitted by\n [`empyrean_compute_impact_probabilities`]. Mirrors\n [`empyrean_core::impact::ImpactProbability`] flattened to primitives;\n nullable fields use NaN sentinels (Option<f64>) or 0 / null\n (Option<usize>).\n\n `method_tag` matches the `EMPYREAN_UNCERTAINTY_*` constants in\n `propagate.rs` and identifies which propagation produced this row."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanImpactProbability {
#[doc = " Variant tag of the [`UncertaintyMethod`] that produced this row."]
pub method_tag: u8,
#[doc = " Owning C string — caller frees via `*_result_free`."]
pub orbit_id: *mut ::std::os::raw::c_char,
pub object_id: *mut ::std::os::raw::c_char,
pub body: *mut ::std::os::raw::c_char,
pub body_naif_id: i32,
pub epoch_mjd_tdb: f64,
pub miss_distance_au: f64,
pub miss_distance_km: f64,
pub effective_radius_au: f64,
pub effective_radius_km: f64,
pub sigma_distance_au: f64,
pub sigma_distance_km: f64,
pub ip_linear: f64,
pub relative_velocity_au_day: f64,
#[doc = " `ip_second_order`, NaN when not available."]
pub ip_second_order: f64,
#[doc = " Jet2 nonlinearity κ, NaN when not available."]
pub nonlinearity: f64,
#[doc = " AGM-mixed IP, NaN when not available."]
pub ip_agm: f64,
#[doc = " MC-sampled IP, NaN when not available."]
pub ip_mc: f64,
#[doc = " Number of MC samples drawn (0 when MC was not used)."]
pub mc_n_samples: u64,
#[doc = " Number of MC samples that impacted (0 when MC was not used)."]
pub mc_n_impacts: u64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanImpactProbability"]
[::std::mem::size_of::<EmpyreanImpactProbability>() - 160usize];
["Alignment of EmpyreanImpactProbability"]
[::std::mem::align_of::<EmpyreanImpactProbability>() - 8usize];
["Offset of field: EmpyreanImpactProbability::method_tag"]
[::std::mem::offset_of!(EmpyreanImpactProbability, method_tag) - 0usize];
["Offset of field: EmpyreanImpactProbability::orbit_id"]
[::std::mem::offset_of!(EmpyreanImpactProbability, orbit_id) - 8usize];
["Offset of field: EmpyreanImpactProbability::object_id"]
[::std::mem::offset_of!(EmpyreanImpactProbability, object_id) - 16usize];
["Offset of field: EmpyreanImpactProbability::body"]
[::std::mem::offset_of!(EmpyreanImpactProbability, body) - 24usize];
["Offset of field: EmpyreanImpactProbability::body_naif_id"]
[::std::mem::offset_of!(EmpyreanImpactProbability, body_naif_id) - 32usize];
["Offset of field: EmpyreanImpactProbability::epoch_mjd_tdb"]
[::std::mem::offset_of!(EmpyreanImpactProbability, epoch_mjd_tdb) - 40usize];
["Offset of field: EmpyreanImpactProbability::miss_distance_au"]
[::std::mem::offset_of!(EmpyreanImpactProbability, miss_distance_au) - 48usize];
["Offset of field: EmpyreanImpactProbability::miss_distance_km"]
[::std::mem::offset_of!(EmpyreanImpactProbability, miss_distance_km) - 56usize];
["Offset of field: EmpyreanImpactProbability::effective_radius_au"]
[::std::mem::offset_of!(EmpyreanImpactProbability, effective_radius_au) - 64usize];
["Offset of field: EmpyreanImpactProbability::effective_radius_km"]
[::std::mem::offset_of!(EmpyreanImpactProbability, effective_radius_km) - 72usize];
["Offset of field: EmpyreanImpactProbability::sigma_distance_au"]
[::std::mem::offset_of!(EmpyreanImpactProbability, sigma_distance_au) - 80usize];
["Offset of field: EmpyreanImpactProbability::sigma_distance_km"]
[::std::mem::offset_of!(EmpyreanImpactProbability, sigma_distance_km) - 88usize];
["Offset of field: EmpyreanImpactProbability::ip_linear"]
[::std::mem::offset_of!(EmpyreanImpactProbability, ip_linear) - 96usize];
["Offset of field: EmpyreanImpactProbability::relative_velocity_au_day"]
[::std::mem::offset_of!(EmpyreanImpactProbability, relative_velocity_au_day) - 104usize];
["Offset of field: EmpyreanImpactProbability::ip_second_order"]
[::std::mem::offset_of!(EmpyreanImpactProbability, ip_second_order) - 112usize];
["Offset of field: EmpyreanImpactProbability::nonlinearity"]
[::std::mem::offset_of!(EmpyreanImpactProbability, nonlinearity) - 120usize];
["Offset of field: EmpyreanImpactProbability::ip_agm"]
[::std::mem::offset_of!(EmpyreanImpactProbability, ip_agm) - 128usize];
["Offset of field: EmpyreanImpactProbability::ip_mc"]
[::std::mem::offset_of!(EmpyreanImpactProbability, ip_mc) - 136usize];
["Offset of field: EmpyreanImpactProbability::mc_n_samples"]
[::std::mem::offset_of!(EmpyreanImpactProbability, mc_n_samples) - 144usize];
["Offset of field: EmpyreanImpactProbability::mc_n_impacts"]
[::std::mem::offset_of!(EmpyreanImpactProbability, mc_n_impacts) - 152usize];
};
impl Default for EmpyreanImpactProbability {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanImpactProbabilitiesResult {
pub records: *mut EmpyreanImpactProbability,
pub num_records: usize,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanImpactProbabilitiesResult"]
[::std::mem::size_of::<EmpyreanImpactProbabilitiesResult>() - 16usize];
["Alignment of EmpyreanImpactProbabilitiesResult"]
[::std::mem::align_of::<EmpyreanImpactProbabilitiesResult>() - 8usize];
["Offset of field: EmpyreanImpactProbabilitiesResult::records"]
[::std::mem::offset_of!(EmpyreanImpactProbabilitiesResult, records) - 0usize];
["Offset of field: EmpyreanImpactProbabilitiesResult::num_records"]
[::std::mem::offset_of!(EmpyreanImpactProbabilitiesResult, num_records) - 8usize];
};
impl Default for EmpyreanImpactProbabilitiesResult {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " One B-plane breakdown emitted by [`empyrean_compute_b_planes`].\n Mirrors [`empyrean_core::impact::BPlaneData`] flattened to primitives.\n Nullable f64 fields use NaN sentinels."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanBPlane {
#[doc = " Variant tag of the [`UncertaintyMethod`] that produced this row."]
pub method_tag: u8,
#[doc = " Owning C string — caller frees via `*_result_free`."]
pub body: *mut ::std::os::raw::c_char,
pub epoch_mjd_tdb: f64,
pub b_dot_t_km: f64,
pub b_dot_r_km: f64,
pub b_mag_km: f64,
pub v_inf_km_s: f64,
pub effective_radius_km: f64,
pub body_radius_km: f64,
#[doc = " `[σ_TT, σ_TR, σ_RR]` covariance elements (km²); NaN when no\n projected covariance is available."]
pub cov_b_plane: [f64; 3usize],
pub semi_major_3sig_km: f64,
pub semi_minor_3sig_km: f64,
pub ellipse_angle_rad: f64,
pub ip_linear: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanBPlane"][::std::mem::size_of::<EmpyreanBPlane>() - 128usize];
["Alignment of EmpyreanBPlane"][::std::mem::align_of::<EmpyreanBPlane>() - 8usize];
["Offset of field: EmpyreanBPlane::method_tag"]
[::std::mem::offset_of!(EmpyreanBPlane, method_tag) - 0usize];
["Offset of field: EmpyreanBPlane::body"]
[::std::mem::offset_of!(EmpyreanBPlane, body) - 8usize];
["Offset of field: EmpyreanBPlane::epoch_mjd_tdb"]
[::std::mem::offset_of!(EmpyreanBPlane, epoch_mjd_tdb) - 16usize];
["Offset of field: EmpyreanBPlane::b_dot_t_km"]
[::std::mem::offset_of!(EmpyreanBPlane, b_dot_t_km) - 24usize];
["Offset of field: EmpyreanBPlane::b_dot_r_km"]
[::std::mem::offset_of!(EmpyreanBPlane, b_dot_r_km) - 32usize];
["Offset of field: EmpyreanBPlane::b_mag_km"]
[::std::mem::offset_of!(EmpyreanBPlane, b_mag_km) - 40usize];
["Offset of field: EmpyreanBPlane::v_inf_km_s"]
[::std::mem::offset_of!(EmpyreanBPlane, v_inf_km_s) - 48usize];
["Offset of field: EmpyreanBPlane::effective_radius_km"]
[::std::mem::offset_of!(EmpyreanBPlane, effective_radius_km) - 56usize];
["Offset of field: EmpyreanBPlane::body_radius_km"]
[::std::mem::offset_of!(EmpyreanBPlane, body_radius_km) - 64usize];
["Offset of field: EmpyreanBPlane::cov_b_plane"]
[::std::mem::offset_of!(EmpyreanBPlane, cov_b_plane) - 72usize];
["Offset of field: EmpyreanBPlane::semi_major_3sig_km"]
[::std::mem::offset_of!(EmpyreanBPlane, semi_major_3sig_km) - 96usize];
["Offset of field: EmpyreanBPlane::semi_minor_3sig_km"]
[::std::mem::offset_of!(EmpyreanBPlane, semi_minor_3sig_km) - 104usize];
["Offset of field: EmpyreanBPlane::ellipse_angle_rad"]
[::std::mem::offset_of!(EmpyreanBPlane, ellipse_angle_rad) - 112usize];
["Offset of field: EmpyreanBPlane::ip_linear"]
[::std::mem::offset_of!(EmpyreanBPlane, ip_linear) - 120usize];
};
impl Default for EmpyreanBPlane {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanBPlanesResult {
pub records: *mut EmpyreanBPlane,
pub num_records: usize,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanBPlanesResult"][::std::mem::size_of::<EmpyreanBPlanesResult>() - 16usize];
["Alignment of EmpyreanBPlanesResult"]
[::std::mem::align_of::<EmpyreanBPlanesResult>() - 8usize];
["Offset of field: EmpyreanBPlanesResult::records"]
[::std::mem::offset_of!(EmpyreanBPlanesResult, records) - 0usize];
["Offset of field: EmpyreanBPlanesResult::num_records"]
[::std::mem::offset_of!(EmpyreanBPlanesResult, num_records) - 8usize];
};
impl Default for EmpyreanBPlanesResult {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " A batch of orbits with their identifiers.\n\n Returned by every `empyrean_orbits_read_*` and consumed by every\n `empyrean_orbits_write_*`. `orbit_ids` and `object_ids` are parallel\n to `orbits` (same length); each `object_ids[i]` may be null when the\n underlying orbit had no object designation.\n\n Free with [`empyrean_orbits_batch_free`] when done."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanOrbitBatch {
#[doc = " Heap-allocated array of `EmpyreanOrbit`. Null when `num_orbits == 0`."]
pub orbits: *mut EmpyreanOrbit,
#[doc = " Heap-allocated array of orbit identifiers (null-terminated UTF-8).\n Each `orbit_ids[i]` is non-null when `i < num_orbits`."]
pub orbit_ids: *mut *mut ::std::os::raw::c_char,
#[doc = " Heap-allocated array of optional object identifiers\n (null-terminated UTF-8 or null pointer when absent)."]
pub object_ids: *mut *mut ::std::os::raw::c_char,
#[doc = " Number of orbits in the batch."]
pub num_orbits: usize,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanOrbitBatch"][::std::mem::size_of::<EmpyreanOrbitBatch>() - 32usize];
["Alignment of EmpyreanOrbitBatch"][::std::mem::align_of::<EmpyreanOrbitBatch>() - 8usize];
["Offset of field: EmpyreanOrbitBatch::orbits"]
[::std::mem::offset_of!(EmpyreanOrbitBatch, orbits) - 0usize];
["Offset of field: EmpyreanOrbitBatch::orbit_ids"]
[::std::mem::offset_of!(EmpyreanOrbitBatch, orbit_ids) - 8usize];
["Offset of field: EmpyreanOrbitBatch::object_ids"]
[::std::mem::offset_of!(EmpyreanOrbitBatch, object_ids) - 16usize];
["Offset of field: EmpyreanOrbitBatch::num_orbits"]
[::std::mem::offset_of!(EmpyreanOrbitBatch, num_orbits) - 24usize];
};
impl Default for EmpyreanOrbitBatch {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Per-observation result from orbit determination or evaluation.\n\n Mirrors scott's [`ObservationResult`](scott::results::ObservationResult)\n — every field upstream produces is carried across the C ABI. NaN /\n `EMPYREAN_REJECTION_NOT_EVALUATED` mark fields that aren't populated\n for the call type (e.g. evaluate doesn't compute rejection or\n influence diagnostics).\n\n `obs_id` is a heap-allocated NUL-terminated UTF-8 string; the\n pointer is freed by [`empyrean_od_result_free`] /\n [`empyrean_evaluate_result_free`] when the parent array is freed.\n Do NOT free it manually."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanObservationResult {
#[doc = " ADES `obsID` (or scott auto-assigned). Owned by the parent array\n — freed by the matching `*_result_free` call."]
pub obs_id: *mut ::std::os::raw::c_char,
#[doc = " MPC observatory code (3-byte + NUL)."]
pub obs_code: [u8; 4usize],
#[doc = " Star catalog used for astrometric reduction (ADES `astCat`).\n Heap-allocated; null when ADES did not carry one. Freed with the array."]
pub ast_cat: *mut ::std::os::raw::c_char,
#[doc = " Observation epoch (MJD TDB)."]
pub epoch_mjd_tdb: f64,
#[doc = " RA·cosδ residual (observed - predicted), arcsec."]
pub ra_residual_arcsec: f64,
#[doc = " Dec residual, arcsec."]
pub dec_residual_arcsec: f64,
#[doc = " Mahalanobis χ² of this observation. NaN if covariance unavailable."]
pub chi2: f64,
#[doc = " Degrees of freedom (number of non-NaN residual dimensions)."]
pub dof: u32,
#[doc = " χ² survival probability."]
pub probability: f64,
#[doc = " Whether this observation was used in the fit (1 = yes, 0 = no)."]
pub selected: u8,
#[doc = " Combined obs+predicted RA covariance (arcsec²). NaN if absent."]
pub residual_cov_ra: f64,
#[doc = " Combined obs+predicted Dec covariance (arcsec²). NaN if absent."]
pub residual_cov_dec: f64,
#[doc = " Off-diagonal correlation coefficient (dimensionless, [-1, 1]). NaN if absent."]
pub residual_cov_corr: f64,
#[doc = " Reason this observation was kept / rejected. One of the\n `EMPYREAN_REJECTION_*` codes; `EMPYREAN_REJECTION_NOT_EVALUATED`\n when the call did not run rejection (e.g. `empyrean_evaluate`)."]
pub rejection_reason: i32,
#[doc = " Criterion value (chi², Cook's D, …) tested against the threshold. NaN if not evaluated."]
pub rejection_criterion: f64,
#[doc = " Static threshold the criterion was compared against. NaN if not evaluated."]
pub rejection_threshold: f64,
#[doc = " Effective threshold for adaptive rejection (Layer 3). NaN otherwise."]
pub rejection_effective_threshold: f64,
#[doc = " D-optimality information loss from removing this observation. NaN if not computed."]
pub rejection_information_loss: f64,
#[doc = " Cook's distance. NaN if no influence pass was run."]
pub cooks_distance: f64,
#[doc = " Scalar leverage h_ii ∈ [0, 2]. NaN if no influence pass."]
pub leverage: f64,
#[doc = " D-optimality fractional information contribution\n `f_i = tr(N⁻¹ I_i)`. NaN if no influence pass."]
pub fractional_information: f64,
#[doc = " Along-track residual (arcsec). NaN if no sky-motion rates."]
pub along_track_arcsec: f64,
#[doc = " Cross-track residual (arcsec). NaN if no sky-motion rates."]
pub cross_track_arcsec: f64,
#[doc = " Along-track 1σ (arcsec). NaN if unavailable."]
pub along_track_error_arcsec: f64,
#[doc = " Cross-track 1σ (arcsec). NaN if unavailable."]
pub cross_track_error_arcsec: f64,
#[doc = " Position angle of sky motion (degrees, East of North). NaN if unavailable."]
pub track_position_angle_deg: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanObservationResult"]
[::std::mem::size_of::<EmpyreanObservationResult>() - 208usize];
["Alignment of EmpyreanObservationResult"]
[::std::mem::align_of::<EmpyreanObservationResult>() - 8usize];
["Offset of field: EmpyreanObservationResult::obs_id"]
[::std::mem::offset_of!(EmpyreanObservationResult, obs_id) - 0usize];
["Offset of field: EmpyreanObservationResult::obs_code"]
[::std::mem::offset_of!(EmpyreanObservationResult, obs_code) - 8usize];
["Offset of field: EmpyreanObservationResult::ast_cat"]
[::std::mem::offset_of!(EmpyreanObservationResult, ast_cat) - 16usize];
["Offset of field: EmpyreanObservationResult::epoch_mjd_tdb"]
[::std::mem::offset_of!(EmpyreanObservationResult, epoch_mjd_tdb) - 24usize];
["Offset of field: EmpyreanObservationResult::ra_residual_arcsec"]
[::std::mem::offset_of!(EmpyreanObservationResult, ra_residual_arcsec) - 32usize];
["Offset of field: EmpyreanObservationResult::dec_residual_arcsec"]
[::std::mem::offset_of!(EmpyreanObservationResult, dec_residual_arcsec) - 40usize];
["Offset of field: EmpyreanObservationResult::chi2"]
[::std::mem::offset_of!(EmpyreanObservationResult, chi2) - 48usize];
["Offset of field: EmpyreanObservationResult::dof"]
[::std::mem::offset_of!(EmpyreanObservationResult, dof) - 56usize];
["Offset of field: EmpyreanObservationResult::probability"]
[::std::mem::offset_of!(EmpyreanObservationResult, probability) - 64usize];
["Offset of field: EmpyreanObservationResult::selected"]
[::std::mem::offset_of!(EmpyreanObservationResult, selected) - 72usize];
["Offset of field: EmpyreanObservationResult::residual_cov_ra"]
[::std::mem::offset_of!(EmpyreanObservationResult, residual_cov_ra) - 80usize];
["Offset of field: EmpyreanObservationResult::residual_cov_dec"]
[::std::mem::offset_of!(EmpyreanObservationResult, residual_cov_dec) - 88usize];
["Offset of field: EmpyreanObservationResult::residual_cov_corr"]
[::std::mem::offset_of!(EmpyreanObservationResult, residual_cov_corr) - 96usize];
["Offset of field: EmpyreanObservationResult::rejection_reason"]
[::std::mem::offset_of!(EmpyreanObservationResult, rejection_reason) - 104usize];
["Offset of field: EmpyreanObservationResult::rejection_criterion"]
[::std::mem::offset_of!(EmpyreanObservationResult, rejection_criterion) - 112usize];
["Offset of field: EmpyreanObservationResult::rejection_threshold"]
[::std::mem::offset_of!(EmpyreanObservationResult, rejection_threshold) - 120usize];
["Offset of field: EmpyreanObservationResult::rejection_effective_threshold"][::std::mem::offset_of!(
EmpyreanObservationResult,
rejection_effective_threshold
) - 128usize];
["Offset of field: EmpyreanObservationResult::rejection_information_loss"]
[::std::mem::offset_of!(EmpyreanObservationResult, rejection_information_loss) - 136usize];
["Offset of field: EmpyreanObservationResult::cooks_distance"]
[::std::mem::offset_of!(EmpyreanObservationResult, cooks_distance) - 144usize];
["Offset of field: EmpyreanObservationResult::leverage"]
[::std::mem::offset_of!(EmpyreanObservationResult, leverage) - 152usize];
["Offset of field: EmpyreanObservationResult::fractional_information"]
[::std::mem::offset_of!(EmpyreanObservationResult, fractional_information) - 160usize];
["Offset of field: EmpyreanObservationResult::along_track_arcsec"]
[::std::mem::offset_of!(EmpyreanObservationResult, along_track_arcsec) - 168usize];
["Offset of field: EmpyreanObservationResult::cross_track_arcsec"]
[::std::mem::offset_of!(EmpyreanObservationResult, cross_track_arcsec) - 176usize];
["Offset of field: EmpyreanObservationResult::along_track_error_arcsec"]
[::std::mem::offset_of!(EmpyreanObservationResult, along_track_error_arcsec) - 184usize];
["Offset of field: EmpyreanObservationResult::cross_track_error_arcsec"]
[::std::mem::offset_of!(EmpyreanObservationResult, cross_track_error_arcsec) - 192usize];
["Offset of field: EmpyreanObservationResult::track_position_angle_deg"]
[::std::mem::offset_of!(EmpyreanObservationResult, track_position_angle_deg) - 200usize];
};
impl Default for EmpyreanObservationResult {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Result containing an array of observer states."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanObserverResult {
pub observers: *mut EmpyreanObserver,
pub num_observers: usize,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanObserverResult"][::std::mem::size_of::<EmpyreanObserverResult>() - 16usize];
["Alignment of EmpyreanObserverResult"]
[::std::mem::align_of::<EmpyreanObserverResult>() - 8usize];
["Offset of field: EmpyreanObserverResult::observers"]
[::std::mem::offset_of!(EmpyreanObserverResult, observers) - 0usize];
["Offset of field: EmpyreanObserverResult::num_observers"]
[::std::mem::offset_of!(EmpyreanObserverResult, num_observers) - 8usize];
};
impl Default for EmpyreanObserverResult {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " A single optical observation for orbit determination — full ADES schema.\n\n String fields are nullable (`null` pointer = absent). Float fields\n use NaN as the absent sentinel. The `n_stars` integer uses `-1` as\n the absent sentinel (since `u32::MAX` is a valid count). The\n `obs_code` is fixed-size 4-byte null-padded to keep the common case\n allocation-free.\n\n Mirrors scott's `OpticalObservation` field-for-field — every named\n PSV column round-trips losslessly except for ADES extension fields\n not yet in the upstream schema."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanObservation {
#[doc = " IAU permanent designation (nullable)."]
pub perm_id: *mut ::std::os::raw::c_char,
#[doc = " MPC provisional designation (nullable)."]
pub prov_id: *mut ::std::os::raw::c_char,
#[doc = " Observer-assigned tracklet identifier (nullable)."]
pub trk_sub: *mut ::std::os::raw::c_char,
#[doc = " MPC-assigned observation identifier (`obsid`, nullable)."]
pub obs_id: *mut ::std::os::raw::c_char,
#[doc = " Observer-assigned sub-identifier (`obsSubID`, nullable)."]
pub obs_sub_id: *mut ::std::os::raw::c_char,
#[doc = " Track identifier (`trkID`, nullable)."]
pub trk_id: *mut ::std::os::raw::c_char,
#[doc = " MPC observatory code, null-padded to 4 bytes."]
pub obs_code: [u8; 4usize],
#[doc = " Observation mode (CCD, CMOS, etc.) (nullable)."]
pub mode: *mut ::std::os::raw::c_char,
#[doc = " MPC program code (nullable)."]
pub prog: *mut ::std::os::raw::c_char,
#[doc = " Coordinate system for observer position (nullable)."]
pub sys: *mut ::std::os::raw::c_char,
#[doc = " Center body NAIF ID. NaN if unset."]
pub ctr: f64,
#[doc = " Position component 1 (lon for WGS84, X for ICRF_KM). NaN if unset."]
pub pos1: f64,
#[doc = " Position component 2 (lat for WGS84, Y for ICRF_KM). NaN if unset."]
pub pos2: f64,
#[doc = " Position component 3 (alt for WGS84, Z for ICRF_KM). NaN if unset."]
pub pos3: f64,
#[doc = " Observation time as ISO 8601 UTC string."]
pub obs_time: *mut ::std::os::raw::c_char,
#[doc = " Right ascension (degrees)."]
pub ra_deg: f64,
#[doc = " Declination (degrees)."]
pub dec_deg: f64,
#[doc = " RA·cos(Dec) uncertainty (arcseconds). NaN if unavailable."]
pub rms_ra_arcsec: f64,
#[doc = " Dec uncertainty (arcseconds). NaN if unavailable."]
pub rms_dec_arcsec: f64,
#[doc = " RA-Dec correlation coefficient [-1, 1]. NaN if unavailable."]
pub rms_corr: f64,
#[doc = " Star catalog used for astrometric reduction (nullable)."]
pub ast_cat: *mut ::std::os::raw::c_char,
#[doc = " Apparent magnitude. NaN if unavailable."]
pub mag: f64,
#[doc = " Magnitude uncertainty. NaN if unavailable."]
pub rms_mag: f64,
#[doc = " Photometric passband (nullable)."]
pub band: *mut ::std::os::raw::c_char,
#[doc = " Photometric catalog (nullable)."]
pub phot_cat: *mut ::std::os::raw::c_char,
#[doc = " Photometric aperture (arcseconds). NaN if unavailable."]
pub phot_ap: f64,
#[doc = " log10(SNR) of the detection. NaN if unavailable."]
pub log_snr: f64,
#[doc = " Seeing FWHM (arcseconds). NaN if unavailable."]
pub seeing: f64,
#[doc = " Exposure time (seconds). NaN if unavailable."]
pub exp: f64,
#[doc = " RMS of astrometric fit (arcseconds). NaN if unavailable."]
pub rms_fit: f64,
#[doc = " Number of reference stars in astrometric fit. -1 if unavailable."]
pub n_stars: i32,
#[doc = " MPC note flags (nullable)."]
pub notes: *mut ::std::os::raw::c_char,
#[doc = " Free-text observer remarks (nullable)."]
pub remarks: *mut ::std::os::raw::c_char,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanObservation"][::std::mem::size_of::<EmpyreanObservation>() - 264usize];
["Alignment of EmpyreanObservation"][::std::mem::align_of::<EmpyreanObservation>() - 8usize];
["Offset of field: EmpyreanObservation::perm_id"]
[::std::mem::offset_of!(EmpyreanObservation, perm_id) - 0usize];
["Offset of field: EmpyreanObservation::prov_id"]
[::std::mem::offset_of!(EmpyreanObservation, prov_id) - 8usize];
["Offset of field: EmpyreanObservation::trk_sub"]
[::std::mem::offset_of!(EmpyreanObservation, trk_sub) - 16usize];
["Offset of field: EmpyreanObservation::obs_id"]
[::std::mem::offset_of!(EmpyreanObservation, obs_id) - 24usize];
["Offset of field: EmpyreanObservation::obs_sub_id"]
[::std::mem::offset_of!(EmpyreanObservation, obs_sub_id) - 32usize];
["Offset of field: EmpyreanObservation::trk_id"]
[::std::mem::offset_of!(EmpyreanObservation, trk_id) - 40usize];
["Offset of field: EmpyreanObservation::obs_code"]
[::std::mem::offset_of!(EmpyreanObservation, obs_code) - 48usize];
["Offset of field: EmpyreanObservation::mode"]
[::std::mem::offset_of!(EmpyreanObservation, mode) - 56usize];
["Offset of field: EmpyreanObservation::prog"]
[::std::mem::offset_of!(EmpyreanObservation, prog) - 64usize];
["Offset of field: EmpyreanObservation::sys"]
[::std::mem::offset_of!(EmpyreanObservation, sys) - 72usize];
["Offset of field: EmpyreanObservation::ctr"]
[::std::mem::offset_of!(EmpyreanObservation, ctr) - 80usize];
["Offset of field: EmpyreanObservation::pos1"]
[::std::mem::offset_of!(EmpyreanObservation, pos1) - 88usize];
["Offset of field: EmpyreanObservation::pos2"]
[::std::mem::offset_of!(EmpyreanObservation, pos2) - 96usize];
["Offset of field: EmpyreanObservation::pos3"]
[::std::mem::offset_of!(EmpyreanObservation, pos3) - 104usize];
["Offset of field: EmpyreanObservation::obs_time"]
[::std::mem::offset_of!(EmpyreanObservation, obs_time) - 112usize];
["Offset of field: EmpyreanObservation::ra_deg"]
[::std::mem::offset_of!(EmpyreanObservation, ra_deg) - 120usize];
["Offset of field: EmpyreanObservation::dec_deg"]
[::std::mem::offset_of!(EmpyreanObservation, dec_deg) - 128usize];
["Offset of field: EmpyreanObservation::rms_ra_arcsec"]
[::std::mem::offset_of!(EmpyreanObservation, rms_ra_arcsec) - 136usize];
["Offset of field: EmpyreanObservation::rms_dec_arcsec"]
[::std::mem::offset_of!(EmpyreanObservation, rms_dec_arcsec) - 144usize];
["Offset of field: EmpyreanObservation::rms_corr"]
[::std::mem::offset_of!(EmpyreanObservation, rms_corr) - 152usize];
["Offset of field: EmpyreanObservation::ast_cat"]
[::std::mem::offset_of!(EmpyreanObservation, ast_cat) - 160usize];
["Offset of field: EmpyreanObservation::mag"]
[::std::mem::offset_of!(EmpyreanObservation, mag) - 168usize];
["Offset of field: EmpyreanObservation::rms_mag"]
[::std::mem::offset_of!(EmpyreanObservation, rms_mag) - 176usize];
["Offset of field: EmpyreanObservation::band"]
[::std::mem::offset_of!(EmpyreanObservation, band) - 184usize];
["Offset of field: EmpyreanObservation::phot_cat"]
[::std::mem::offset_of!(EmpyreanObservation, phot_cat) - 192usize];
["Offset of field: EmpyreanObservation::phot_ap"]
[::std::mem::offset_of!(EmpyreanObservation, phot_ap) - 200usize];
["Offset of field: EmpyreanObservation::log_snr"]
[::std::mem::offset_of!(EmpyreanObservation, log_snr) - 208usize];
["Offset of field: EmpyreanObservation::seeing"]
[::std::mem::offset_of!(EmpyreanObservation, seeing) - 216usize];
["Offset of field: EmpyreanObservation::exp"]
[::std::mem::offset_of!(EmpyreanObservation, exp) - 224usize];
["Offset of field: EmpyreanObservation::rms_fit"]
[::std::mem::offset_of!(EmpyreanObservation, rms_fit) - 232usize];
["Offset of field: EmpyreanObservation::n_stars"]
[::std::mem::offset_of!(EmpyreanObservation, n_stars) - 240usize];
["Offset of field: EmpyreanObservation::notes"]
[::std::mem::offset_of!(EmpyreanObservation, notes) - 248usize];
["Offset of field: EmpyreanObservation::remarks"]
[::std::mem::offset_of!(EmpyreanObservation, remarks) - 256usize];
};
impl Default for EmpyreanObservation {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " A single radar (delay or Doppler) observation for orbit determination —\n the ADES `<radar>` schema.\n\n ADES models radar astrometry as its own top-level table, parallel to\n `<optical>` (not as an optical `mode`). A record carries a round-trip\n time **delay** *or* a **Doppler** shift (the ADES `RadarValue` is an\n XSD `<choice>`), referred to a transmitting (`trx`) and receiving\n (`rcv`) station — equal for a monostatic observation, distinct for a\n bistatic one.\n\n **Units are ADES-native through this FFI — the C ABI performs ZERO unit\n conversion.** The delay *value* is in **seconds** while its uncertainty\n `rms_delay_microseconds` is in **microseconds** (this asymmetry is\n intentional in the ADES schema, verified against the IAU-ADES\n `a4179_radar` reference data and the JPL SSD radar API); Doppler value\n and uncertainty are both in **Hz**; `frq_mhz` is in **MHz**. The single\n SI normalisation happens once downstream in scott's\n `Observation::from_radar`, never here.\n\n String fields are nullable (`null` pointer = absent). The `trx`/`rcv`\n station codes are fixed-size 4-byte null-padded (like `obs_code`).\n Absent f64 fields use `f64::NAN`. The `com` flag is a tri-state `i8`.\n No field is silently zeroed or defaulted.\n\n Mirrors scott's `RadarObservation` field-for-field."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanRadarObservation {
#[doc = " IAU permanent designation (nullable)."]
pub perm_id: *mut ::std::os::raw::c_char,
#[doc = " MPC provisional designation (nullable)."]
pub prov_id: *mut ::std::os::raw::c_char,
#[doc = " Observer-assigned tracklet identifier (nullable)."]
pub trk_sub: *mut ::std::os::raw::c_char,
#[doc = " MPC station code of the **transmitting** antenna (ADES `trx`),\n null-padded to 4 bytes."]
pub trx: [u8; 4usize],
#[doc = " MPC station code of the **receiving** antenna (ADES `rcv`),\n null-padded to 4 bytes. Equal to `trx` for a monostatic\n observation; differs for a bistatic one."]
pub rcv: [u8; 4usize],
#[doc = " Observation epoch as an ISO 8601 UTC string. For radar this is the\n **receive** epoch (the time the returned signal is recorded).\n Required, non-null."]
pub obs_time: *mut ::std::os::raw::c_char,
#[doc = " Measurement kind: `EMPYREAN_RADAR_KIND_DELAY` (0) or\n `EMPYREAN_RADAR_KIND_DOPPLER` (1). Selects which value pair is live."]
pub kind: u8,
#[doc = " Round-trip time delay in **seconds** (ADES-native). Valid iff\n `kind == EMPYREAN_RADAR_KIND_DELAY`, else `f64::NAN`."]
pub delay_seconds: f64,
#[doc = " 1σ uncertainty of the delay in **microseconds** (ADES-native; the\n asymmetry vs `delay_seconds` is intentional). Valid iff\n `kind == EMPYREAN_RADAR_KIND_DELAY`, else `f64::NAN`."]
pub rms_delay_microseconds: f64,
#[doc = " Doppler shift in **Hz** (ADES-native, signed). Valid iff\n `kind == EMPYREAN_RADAR_KIND_DOPPLER`, else `f64::NAN`."]
pub doppler_hz: f64,
#[doc = " 1σ uncertainty of the Doppler shift in **Hz** (ADES-native). Valid\n iff `kind == EMPYREAN_RADAR_KIND_DOPPLER`, else `f64::NAN`."]
pub rms_doppler_hz: f64,
#[doc = " Transmit carrier reference frequency in **MHz** (ADES `frq`).\n Required; relates a Doppler shift to a range rate."]
pub frq_mhz: f64,
#[doc = " Center-of-mass flag (ADES `com`), tri-state: `-1` = absent,\n `0` = false (peak-power / leading-edge reduction), `1` = true\n (reduced to target center of mass). Mirrors `Option<bool>`; a\n missing flag MUST map to `-1` (never `0`) — the ADES center-of-mass\n default is applied explicitly downstream, not silently here."]
pub com: i8,
#[doc = " log10(SNR) of the echo, if reported. `f64::NAN` if absent."]
pub log_snr: f64,
#[doc = " Free-text observer remarks (nullable)."]
pub remarks: *mut ::std::os::raw::c_char,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanRadarObservation"]
[::std::mem::size_of::<EmpyreanRadarObservation>() - 112usize];
["Alignment of EmpyreanRadarObservation"]
[::std::mem::align_of::<EmpyreanRadarObservation>() - 8usize];
["Offset of field: EmpyreanRadarObservation::perm_id"]
[::std::mem::offset_of!(EmpyreanRadarObservation, perm_id) - 0usize];
["Offset of field: EmpyreanRadarObservation::prov_id"]
[::std::mem::offset_of!(EmpyreanRadarObservation, prov_id) - 8usize];
["Offset of field: EmpyreanRadarObservation::trk_sub"]
[::std::mem::offset_of!(EmpyreanRadarObservation, trk_sub) - 16usize];
["Offset of field: EmpyreanRadarObservation::trx"]
[::std::mem::offset_of!(EmpyreanRadarObservation, trx) - 24usize];
["Offset of field: EmpyreanRadarObservation::rcv"]
[::std::mem::offset_of!(EmpyreanRadarObservation, rcv) - 28usize];
["Offset of field: EmpyreanRadarObservation::obs_time"]
[::std::mem::offset_of!(EmpyreanRadarObservation, obs_time) - 32usize];
["Offset of field: EmpyreanRadarObservation::kind"]
[::std::mem::offset_of!(EmpyreanRadarObservation, kind) - 40usize];
["Offset of field: EmpyreanRadarObservation::delay_seconds"]
[::std::mem::offset_of!(EmpyreanRadarObservation, delay_seconds) - 48usize];
["Offset of field: EmpyreanRadarObservation::rms_delay_microseconds"]
[::std::mem::offset_of!(EmpyreanRadarObservation, rms_delay_microseconds) - 56usize];
["Offset of field: EmpyreanRadarObservation::doppler_hz"]
[::std::mem::offset_of!(EmpyreanRadarObservation, doppler_hz) - 64usize];
["Offset of field: EmpyreanRadarObservation::rms_doppler_hz"]
[::std::mem::offset_of!(EmpyreanRadarObservation, rms_doppler_hz) - 72usize];
["Offset of field: EmpyreanRadarObservation::frq_mhz"]
[::std::mem::offset_of!(EmpyreanRadarObservation, frq_mhz) - 80usize];
["Offset of field: EmpyreanRadarObservation::com"]
[::std::mem::offset_of!(EmpyreanRadarObservation, com) - 88usize];
["Offset of field: EmpyreanRadarObservation::log_snr"]
[::std::mem::offset_of!(EmpyreanRadarObservation, log_snr) - 96usize];
["Offset of field: EmpyreanRadarObservation::remarks"]
[::std::mem::offset_of!(EmpyreanRadarObservation, remarks) - 104usize];
};
impl Default for EmpyreanRadarObservation {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " One element of [`EmpyreanWeightingConfig::additional_layers`].\n Tagged-union shape: the active fields depend on `kind`."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanWeightingLayer {
#[doc = " Layer kind discriminator — one of\n `EMPYREAN_WEIGHTING_LAYER_*`."]
pub kind: i32,
#[doc = " MPC observatory code, null-padded to 4 bytes."]
pub obs_code: [u8; 4usize],
#[doc = " 1σ RA·cos(δ) in arcsec."]
pub sigma_ra_arcsec: f64,
#[doc = " 1σ Dec in arcsec."]
pub sigma_dec_arcsec: f64,
#[doc = " Start of applicable time range (MJD TDB). NaN = unbounded."]
pub start_epoch_mjd_tdb: f64,
#[doc = " End of applicable time range (MJD TDB). NaN = unbounded."]
pub end_epoch_mjd_tdb: f64,
#[doc = " Scale factor on the resulting weight. 0.0 → upstream default (1.0)."]
pub scale: f64,
#[doc = " Maximum gap between observations to count as the same night\n (days). 0.0 → upstream default (0.5)."]
pub max_gap_days: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanWeightingLayer"][::std::mem::size_of::<EmpyreanWeightingLayer>() - 56usize];
["Alignment of EmpyreanWeightingLayer"]
[::std::mem::align_of::<EmpyreanWeightingLayer>() - 8usize];
["Offset of field: EmpyreanWeightingLayer::kind"]
[::std::mem::offset_of!(EmpyreanWeightingLayer, kind) - 0usize];
["Offset of field: EmpyreanWeightingLayer::obs_code"]
[::std::mem::offset_of!(EmpyreanWeightingLayer, obs_code) - 4usize];
["Offset of field: EmpyreanWeightingLayer::sigma_ra_arcsec"]
[::std::mem::offset_of!(EmpyreanWeightingLayer, sigma_ra_arcsec) - 8usize];
["Offset of field: EmpyreanWeightingLayer::sigma_dec_arcsec"]
[::std::mem::offset_of!(EmpyreanWeightingLayer, sigma_dec_arcsec) - 16usize];
["Offset of field: EmpyreanWeightingLayer::start_epoch_mjd_tdb"]
[::std::mem::offset_of!(EmpyreanWeightingLayer, start_epoch_mjd_tdb) - 24usize];
["Offset of field: EmpyreanWeightingLayer::end_epoch_mjd_tdb"]
[::std::mem::offset_of!(EmpyreanWeightingLayer, end_epoch_mjd_tdb) - 32usize];
["Offset of field: EmpyreanWeightingLayer::scale"]
[::std::mem::offset_of!(EmpyreanWeightingLayer, scale) - 40usize];
["Offset of field: EmpyreanWeightingLayer::max_gap_days"]
[::std::mem::offset_of!(EmpyreanWeightingLayer, max_gap_days) - 48usize];
};
#[doc = " Weighting configuration. Mirrors\n [`scott::weighting::WeightingConfig`] structurally; extends it\n with an `enabled` toggle and a preset selector for the common\n case of \"use the production preset\" without constructing layers\n by hand.\n\n `enabled = 0` runs OD with uniform 1″ weighting (the old\n `use_weighting = 0` behavior). `enabled = 1` activates the\n pipeline; the resulting layer chain is the preset's layers\n followed by `additional_layers` (allows e.g. VFC17 + per-survey\n override)."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanWeightingConfig {
#[doc = " 1 = enabled (default), 0 = uniform 1″ weighting."]
pub enabled: u8,
#[doc = " Preset selector. One of `EMPYREAN_WEIGHTING_PRESET_*`.\n Default `0` (NONE) means \"use additional_layers only\";\n when `enabled = 1` and zero-init, the conversion code\n substitutes `VFC17` so default-zero structs keep the\n production behavior."]
pub preset: u8,
#[doc = " Default 1σ used when no rule applies (arcsec). 0.0 →\n upstream default (1.0). Ignored when preset != NONE."]
pub default_sigma_arcsec: f64,
#[doc = " Sigma combination policy. -1 = use the preset's policy;\n otherwise one of `EMPYREAN_SIGMA_POLICY_*`."]
pub sigma_policy: i32,
#[doc = " Pointer to additional layers appended to the preset's chain.\n Non-owning — caller keeps the array alive for the OD call."]
pub additional_layers: *const EmpyreanWeightingLayer,
pub num_additional_layers: usize,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanWeightingConfig"][::std::mem::size_of::<EmpyreanWeightingConfig>() - 40usize];
["Alignment of EmpyreanWeightingConfig"]
[::std::mem::align_of::<EmpyreanWeightingConfig>() - 8usize];
["Offset of field: EmpyreanWeightingConfig::enabled"]
[::std::mem::offset_of!(EmpyreanWeightingConfig, enabled) - 0usize];
["Offset of field: EmpyreanWeightingConfig::preset"]
[::std::mem::offset_of!(EmpyreanWeightingConfig, preset) - 1usize];
["Offset of field: EmpyreanWeightingConfig::default_sigma_arcsec"]
[::std::mem::offset_of!(EmpyreanWeightingConfig, default_sigma_arcsec) - 8usize];
["Offset of field: EmpyreanWeightingConfig::sigma_policy"]
[::std::mem::offset_of!(EmpyreanWeightingConfig, sigma_policy) - 16usize];
["Offset of field: EmpyreanWeightingConfig::additional_layers"]
[::std::mem::offset_of!(EmpyreanWeightingConfig, additional_layers) - 24usize];
["Offset of field: EmpyreanWeightingConfig::num_additional_layers"]
[::std::mem::offset_of!(EmpyreanWeightingConfig, num_additional_layers) - 32usize];
};
impl Default for EmpyreanWeightingConfig {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Catalog-bias-correction configuration. Mirrors scott's\n `Option<Arc<DebiasingTable>>` field on `ODConfig`.\n\n `enabled = 0` runs OD with no catalog debiasing (matches the old\n `use_debiasing = 0` behavior). `enabled = 1` activates the\n EFCC2020 pipeline; the table is loaded from `bias_dat_path` if\n non-NULL, otherwise from the DataManager-default location at the\n requested `resolution`."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanDebiasingConfig {
#[doc = " 1 = on (default), 0 = no debiasing."]
pub enabled: u8,
#[doc = " Table identity. Currently `EFCC2020` only."]
pub table_id: i32,
#[doc = " `EMPYREAN_DEBIASING_RESOLUTION_*` — Standard (~35 MB) or Hires (~567 MB)."]
pub resolution: i32,
#[doc = " Optional path to the bias.dat file. NULL = DataManager default.\n Non-owning."]
pub bias_dat_path: *const ::std::os::raw::c_char,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanDebiasingConfig"][::std::mem::size_of::<EmpyreanDebiasingConfig>() - 24usize];
["Alignment of EmpyreanDebiasingConfig"]
[::std::mem::align_of::<EmpyreanDebiasingConfig>() - 8usize];
["Offset of field: EmpyreanDebiasingConfig::enabled"]
[::std::mem::offset_of!(EmpyreanDebiasingConfig, enabled) - 0usize];
["Offset of field: EmpyreanDebiasingConfig::table_id"]
[::std::mem::offset_of!(EmpyreanDebiasingConfig, table_id) - 4usize];
["Offset of field: EmpyreanDebiasingConfig::resolution"]
[::std::mem::offset_of!(EmpyreanDebiasingConfig, resolution) - 8usize];
["Offset of field: EmpyreanDebiasingConfig::bias_dat_path"]
[::std::mem::offset_of!(EmpyreanDebiasingConfig, bias_dat_path) - 16usize];
};
impl Default for EmpyreanDebiasingConfig {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Origin-policy selector for the OD pipeline (mirrors\n [`OriginPolicy`]).\n\n `policy = EMPYREAN_ORIGIN_POLICY_AUTO` ignores `explicit_naif`;\n `_EXPLICIT` interprets the field as the NAIF body ID of the central\n body to pin to (e.g. 10 = Sun, 399 = Earth, 4 = Mars-barycenter)."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanOriginPolicy {
pub policy: i32,
pub explicit_naif: i32,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanOriginPolicy"][::std::mem::size_of::<EmpyreanOriginPolicy>() - 8usize];
["Alignment of EmpyreanOriginPolicy"][::std::mem::align_of::<EmpyreanOriginPolicy>() - 4usize];
["Offset of field: EmpyreanOriginPolicy::policy"]
[::std::mem::offset_of!(EmpyreanOriginPolicy, policy) - 0usize];
["Offset of field: EmpyreanOriginPolicy::explicit_naif"]
[::std::mem::offset_of!(EmpyreanOriginPolicy, explicit_naif) - 4usize];
};
#[doc = " IOD ranging tuning (mirrors the IOD section of [`scott::od::ODConfig`]).\n\n Nested rather than flattened so callers can pass the bundle around\n as a single value and zero-init pulls the upstream defaults\n uniformly. Sentinel rule: `0` / `0.0` requests the upstream default;\n `opposition_gap_days < 0` disables opposition splitting."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanIODConfig {
pub max_triplet_attempts: u32,
pub max_triplet_span_days: f64,
#[doc = " `-1.0` disables opposition splitting; `0.0` uses upstream default (90)."]
pub opposition_gap_days: f64,
pub max_iod_arc_days: f64,
pub curvature_snr_threshold: f64,
pub max_iod_fractional_sigma_a: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanIODConfig"][::std::mem::size_of::<EmpyreanIODConfig>() - 48usize];
["Alignment of EmpyreanIODConfig"][::std::mem::align_of::<EmpyreanIODConfig>() - 8usize];
["Offset of field: EmpyreanIODConfig::max_triplet_attempts"]
[::std::mem::offset_of!(EmpyreanIODConfig, max_triplet_attempts) - 0usize];
["Offset of field: EmpyreanIODConfig::max_triplet_span_days"]
[::std::mem::offset_of!(EmpyreanIODConfig, max_triplet_span_days) - 8usize];
["Offset of field: EmpyreanIODConfig::opposition_gap_days"]
[::std::mem::offset_of!(EmpyreanIODConfig, opposition_gap_days) - 16usize];
["Offset of field: EmpyreanIODConfig::max_iod_arc_days"]
[::std::mem::offset_of!(EmpyreanIODConfig, max_iod_arc_days) - 24usize];
["Offset of field: EmpyreanIODConfig::curvature_snr_threshold"]
[::std::mem::offset_of!(EmpyreanIODConfig, curvature_snr_threshold) - 32usize];
["Offset of field: EmpyreanIODConfig::max_iod_fractional_sigma_a"]
[::std::mem::offset_of!(EmpyreanIODConfig, max_iod_fractional_sigma_a) - 40usize];
};
#[doc = " Output epoch specification (mirrors [`OutputEpoch`]).\n\n The `mode` field determines which variant is active:\n `EMPYREAN_OUTPUT_EPOCH_MID_ARC` / `_LAST_OBSERVATION` / `_IOD_EPOCH`\n ignore `explicit_mjd_tdb`; `_EXPLICIT` reads the field as MJD TDB."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanOutputEpoch {
pub mode: i32,
pub explicit_mjd_tdb: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanOutputEpoch"][::std::mem::size_of::<EmpyreanOutputEpoch>() - 16usize];
["Alignment of EmpyreanOutputEpoch"][::std::mem::align_of::<EmpyreanOutputEpoch>() - 8usize];
["Offset of field: EmpyreanOutputEpoch::mode"]
[::std::mem::offset_of!(EmpyreanOutputEpoch, mode) - 0usize];
["Offset of field: EmpyreanOutputEpoch::explicit_mjd_tdb"]
[::std::mem::offset_of!(EmpyreanOutputEpoch, explicit_mjd_tdb) - 8usize];
};
#[doc = " Auto-escalation policy for [`SolveForParams::Auto`]\n (mirrors [`scott::od::AutoEscalationPolicy`]). Sentinel: `0` /\n `0.0` → upstream default."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanAutoEscalationPolicy {
pub reduced_chi2: f64,
pub at_ct_ratio: f64,
pub min_arc_days: f64,
pub min_n_obs: u32,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanAutoEscalationPolicy"]
[::std::mem::size_of::<EmpyreanAutoEscalationPolicy>() - 32usize];
["Alignment of EmpyreanAutoEscalationPolicy"]
[::std::mem::align_of::<EmpyreanAutoEscalationPolicy>() - 8usize];
["Offset of field: EmpyreanAutoEscalationPolicy::reduced_chi2"]
[::std::mem::offset_of!(EmpyreanAutoEscalationPolicy, reduced_chi2) - 0usize];
["Offset of field: EmpyreanAutoEscalationPolicy::at_ct_ratio"]
[::std::mem::offset_of!(EmpyreanAutoEscalationPolicy, at_ct_ratio) - 8usize];
["Offset of field: EmpyreanAutoEscalationPolicy::min_arc_days"]
[::std::mem::offset_of!(EmpyreanAutoEscalationPolicy, min_arc_days) - 16usize];
["Offset of field: EmpyreanAutoEscalationPolicy::min_n_obs"]
[::std::mem::offset_of!(EmpyreanAutoEscalationPolicy, min_n_obs) - 24usize];
};
#[doc = " Acceptability thresholds for the post-DC fit-quality checks\n (mirrors [`scott::od::AcceptabilityThresholds`]). Sentinel: `0.0` →\n upstream default."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanAcceptabilityThresholds {
pub reduced_chi2: f64,
pub rms_arcsec: f64,
pub at_ct_ratio: f64,
pub min_arc_days: f64,
pub fractional_sigma_a: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanAcceptabilityThresholds"]
[::std::mem::size_of::<EmpyreanAcceptabilityThresholds>() - 40usize];
["Alignment of EmpyreanAcceptabilityThresholds"]
[::std::mem::align_of::<EmpyreanAcceptabilityThresholds>() - 8usize];
["Offset of field: EmpyreanAcceptabilityThresholds::reduced_chi2"]
[::std::mem::offset_of!(EmpyreanAcceptabilityThresholds, reduced_chi2) - 0usize];
["Offset of field: EmpyreanAcceptabilityThresholds::rms_arcsec"]
[::std::mem::offset_of!(EmpyreanAcceptabilityThresholds, rms_arcsec) - 8usize];
["Offset of field: EmpyreanAcceptabilityThresholds::at_ct_ratio"]
[::std::mem::offset_of!(EmpyreanAcceptabilityThresholds, at_ct_ratio) - 16usize];
["Offset of field: EmpyreanAcceptabilityThresholds::min_arc_days"]
[::std::mem::offset_of!(EmpyreanAcceptabilityThresholds, min_arc_days) - 24usize];
["Offset of field: EmpyreanAcceptabilityThresholds::fractional_sigma_a"]
[::std::mem::offset_of!(EmpyreanAcceptabilityThresholds, fractional_sigma_a) - 32usize];
};
#[doc = " Per-station RA/Dec bias-fit configuration (mirrors\n [`scott::nuisance::BiasKind::StationRaDec`]).\n\n Activated by [`EmpyreanODConfig::fit_station_biases`]. Per-station\n sigma overrides and `BiasScope` filtering aren't carried across the\n C ABI yet — every active station uses `sigma_prior_arcsec` and the\n scope is always [`BiasScope::AllStations`]. Reach for the\n empyrean-core Rust API when you need finer control."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanStationRaDecConfig {
#[doc = " Default 1-sigma prior on the RA / Dec offset (arcsec). Default = 0.3."]
pub sigma_prior_arcsec: f64,
#[doc = " Minimum observations per station for a bias parameter to be\n allocated. Stations below this threshold contribute observations\n at face value. 0 → upstream default (5)."]
pub min_obs_per_station: usize,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanStationRaDecConfig"]
[::std::mem::size_of::<EmpyreanStationRaDecConfig>() - 16usize];
["Alignment of EmpyreanStationRaDecConfig"]
[::std::mem::align_of::<EmpyreanStationRaDecConfig>() - 8usize];
["Offset of field: EmpyreanStationRaDecConfig::sigma_prior_arcsec"]
[::std::mem::offset_of!(EmpyreanStationRaDecConfig, sigma_prior_arcsec) - 0usize];
["Offset of field: EmpyreanStationRaDecConfig::min_obs_per_station"]
[::std::mem::offset_of!(EmpyreanStationRaDecConfig, min_obs_per_station) - 8usize];
};
#[doc = " Outlier rejection configuration. Selects between two strategies via\n the [`kind`](Self::kind) discriminator:\n\n - `kind = EMPYREAN_REJECTION_KIND_ADAPTIVE` (default): mirrors\n [`scott::rejection::AdaptiveRejectionConfig`]. Reads\n `chi2_base` / `lambda` / `max_threshold`. Sentinels:\n `chi2_base = 0.0` → 9.21, `lambda < 0` → 1.0,\n `max_threshold = 0.0` → 100.0.\n - `kind = EMPYREAN_REJECTION_KIND_CMC2003`: mirrors\n [`scott::rejection::CMC2003Config`]. Reads `chi2_rej` / `chi2_rec`\n (the upper / lower hysteresis thresholds). Sentinels:\n `chi2_rej = 0.0` → 8.0, `chi2_rec = 0.0` → 7.0.\n\n `enabled = 0` runs OD without any rejection pass — the strategy\n fields are ignored. `enabled = 1` activates rejection."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanRejectionConfig {
#[doc = " 1 = run rejection (default), 0 = skip."]
pub enabled: u8,
#[doc = " Strategy selector — one of the `EMPYREAN_REJECTION_KIND_*`\n constants. Default `0` (Adaptive) keeps existing C callers\n working without code changes."]
pub kind: u8,
pub chi2_base: f64,
#[doc = " `-1.0` selects the upstream default (1.0); negative values are\n otherwise valid and disable adaptation when 0.0."]
pub lambda: f64,
pub max_threshold: f64,
#[doc = " CMC2003 upper threshold (reject when χ² > chi2_rej). 0.0 →\n upstream default (8.0). Ignored unless `kind ==\n EMPYREAN_REJECTION_KIND_CMC2003`."]
pub chi2_rej: f64,
#[doc = " CMC2003 lower threshold (recover when χ² < chi2_rec). 0.0 →\n upstream default (7.0). Must be strictly less than `chi2_rej`\n for hysteresis to break cycles. Ignored unless `kind ==\n EMPYREAN_REJECTION_KIND_CMC2003`."]
pub chi2_rec: f64,
#[doc = " Maximum rejection-refit passes. 0 → upstream default (3)."]
pub max_passes: u32,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanRejectionConfig"][::std::mem::size_of::<EmpyreanRejectionConfig>() - 56usize];
["Alignment of EmpyreanRejectionConfig"]
[::std::mem::align_of::<EmpyreanRejectionConfig>() - 8usize];
["Offset of field: EmpyreanRejectionConfig::enabled"]
[::std::mem::offset_of!(EmpyreanRejectionConfig, enabled) - 0usize];
["Offset of field: EmpyreanRejectionConfig::kind"]
[::std::mem::offset_of!(EmpyreanRejectionConfig, kind) - 1usize];
["Offset of field: EmpyreanRejectionConfig::chi2_base"]
[::std::mem::offset_of!(EmpyreanRejectionConfig, chi2_base) - 8usize];
["Offset of field: EmpyreanRejectionConfig::lambda"]
[::std::mem::offset_of!(EmpyreanRejectionConfig, lambda) - 16usize];
["Offset of field: EmpyreanRejectionConfig::max_threshold"]
[::std::mem::offset_of!(EmpyreanRejectionConfig, max_threshold) - 24usize];
["Offset of field: EmpyreanRejectionConfig::chi2_rej"]
[::std::mem::offset_of!(EmpyreanRejectionConfig, chi2_rej) - 32usize];
["Offset of field: EmpyreanRejectionConfig::chi2_rec"]
[::std::mem::offset_of!(EmpyreanRejectionConfig, chi2_rec) - 40usize];
["Offset of field: EmpyreanRejectionConfig::max_passes"]
[::std::mem::offset_of!(EmpyreanRejectionConfig, max_passes) - 48usize];
};
#[doc = " Orbit-determination configuration.\n\n Drives `empyrean_determine`, `empyrean_evaluate`, and `empyrean_refine`.\n Mirrors [`scott::od::ODConfig`](scott::od::ODConfig) **structurally** —\n where scott has a nested config (e.g. `auto_escalation`,\n `acceptability`), this surface keeps the same nesting via\n [`EmpyreanAutoEscalationPolicy`], [`EmpyreanAcceptabilityThresholds`],\n etc., so the C-side caller's mental model matches the upstream Rust\n type. Sentinel rule for primitive fields: `0` / `0.0` requests the\n upstream default; only the few fields documented inline (e.g.\n `opposition_gap_days < 0`, `lambda < 0`) carry their own special\n values.\n\n IOD strategy configs (Gauss / Herget / SystematicRanging /\n Refinement) are not exposed here — those are tens of internal\n tuning fields that don't translate cleanly. They always run with\n their upstream defaults; reach for the empyrean-core Rust API when\n you need to override them."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanODConfig {
#[doc = " Force-model tier: 0=Approximate, 1=Basic, 2=Standard."]
pub force_model: i32,
#[doc = " Integrator truncation-error tolerance (interpreted by the\n active integrator backend — for the default GR15 this is the\n relative b₆ truncation tolerance). 0.0 → upstream default\n (1e-9)."]
pub epsilon: f64,
#[doc = " Maximum light-time iterations. 0 → upstream default (3)."]
pub max_light_time_iterations: usize,
#[doc = " Threads for batch operations. 0 → all available cores."]
pub num_threads: usize,
#[doc = " Output reference frame: 0=ICRF, 1=EclipticJ2000."]
pub frame: i32,
#[doc = " Observation weighting pipeline configuration. Zero-init = the\n production default (VFC17 + nightly de-weighting at floor-σ\n policy). See [`EmpyreanWeightingConfig`]."]
pub weighting: EmpyreanWeightingConfig,
#[doc = " Catalog-bias-correction configuration. Zero-init = the\n production default (EFCC2020 standard resolution, loaded from\n the DataManager default path). See [`EmpyreanDebiasingConfig`]."]
pub debiasing: EmpyreanDebiasingConfig,
#[doc = " Number of `excluded_perturbers` in [`excluded_perturbers_naif`]; 0 = none."]
pub num_excluded_perturbers: usize,
#[doc = " Pointer to `num_excluded_perturbers` NAIF body IDs to exclude\n from the perturber set (for self-determination of SB441-N16\n bodies). Non-owning — caller must keep the array alive for the\n duration of the OD call."]
pub excluded_perturbers_naif: *const i32,
#[doc = " Origin-policy selector. Zero-init = `Auto` (heliocentric → geo-\n centric Earth cascade). See [`EmpyreanOriginPolicy`]."]
pub origin: EmpyreanOriginPolicy,
pub iod: EmpyreanIODConfig,
pub output_epoch: EmpyreanOutputEpoch,
#[doc = " Maximum DC iterations. 0 → upstream default (100)."]
pub max_iterations: u32,
#[doc = " DC convergence tolerance on Δx^T N Δx. 0.0 → upstream default (0.1)."]
pub convergence_tol: f64,
#[doc = " Use STM-cached ephemeris updates for iterations 2+. 1 = on (default)."]
pub use_stm_cache: u8,
#[doc = " Solve-for parameter set (`EMPYREAN_SOLVE_FOR_*`). Default = Auto."]
pub solve_for: i32,
pub auto_escalation: EmpyreanAutoEscalationPolicy,
pub acceptability: EmpyreanAcceptabilityThresholds,
#[doc = " Schur-eliminate per-station RA/Dec biases. 1 = enable, 0 = off (default)."]
pub fit_station_biases: u8,
#[doc = " Per-station RA/Dec bias config. Honored only when\n [`fit_station_biases`] is non-zero."]
pub station_radec: EmpyreanStationRaDecConfig,
#[doc = " Use span-grouped Jacobian reuse on cache iterations. 0 = off (default)."]
pub use_span_grouping: u8,
pub rejection: EmpyreanRejectionConfig,
#[doc = " Auto-select force-model tier from IOD elements. 0 = off (default)."]
pub auto_force_model: u8,
#[doc = " Output coordinate representation for the fitted orbit + covariance\n (`EMPYREAN_REPRESENTATION_*`). Default = Cartesian."]
pub output_representation: i32,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanODConfig"][::std::mem::size_of::<EmpyreanODConfig>() - 384usize];
["Alignment of EmpyreanODConfig"][::std::mem::align_of::<EmpyreanODConfig>() - 8usize];
["Offset of field: EmpyreanODConfig::force_model"]
[::std::mem::offset_of!(EmpyreanODConfig, force_model) - 0usize];
["Offset of field: EmpyreanODConfig::epsilon"]
[::std::mem::offset_of!(EmpyreanODConfig, epsilon) - 8usize];
["Offset of field: EmpyreanODConfig::max_light_time_iterations"]
[::std::mem::offset_of!(EmpyreanODConfig, max_light_time_iterations) - 16usize];
["Offset of field: EmpyreanODConfig::num_threads"]
[::std::mem::offset_of!(EmpyreanODConfig, num_threads) - 24usize];
["Offset of field: EmpyreanODConfig::frame"]
[::std::mem::offset_of!(EmpyreanODConfig, frame) - 32usize];
["Offset of field: EmpyreanODConfig::weighting"]
[::std::mem::offset_of!(EmpyreanODConfig, weighting) - 40usize];
["Offset of field: EmpyreanODConfig::debiasing"]
[::std::mem::offset_of!(EmpyreanODConfig, debiasing) - 80usize];
["Offset of field: EmpyreanODConfig::num_excluded_perturbers"]
[::std::mem::offset_of!(EmpyreanODConfig, num_excluded_perturbers) - 104usize];
["Offset of field: EmpyreanODConfig::excluded_perturbers_naif"]
[::std::mem::offset_of!(EmpyreanODConfig, excluded_perturbers_naif) - 112usize];
["Offset of field: EmpyreanODConfig::origin"]
[::std::mem::offset_of!(EmpyreanODConfig, origin) - 120usize];
["Offset of field: EmpyreanODConfig::iod"]
[::std::mem::offset_of!(EmpyreanODConfig, iod) - 128usize];
["Offset of field: EmpyreanODConfig::output_epoch"]
[::std::mem::offset_of!(EmpyreanODConfig, output_epoch) - 176usize];
["Offset of field: EmpyreanODConfig::max_iterations"]
[::std::mem::offset_of!(EmpyreanODConfig, max_iterations) - 192usize];
["Offset of field: EmpyreanODConfig::convergence_tol"]
[::std::mem::offset_of!(EmpyreanODConfig, convergence_tol) - 200usize];
["Offset of field: EmpyreanODConfig::use_stm_cache"]
[::std::mem::offset_of!(EmpyreanODConfig, use_stm_cache) - 208usize];
["Offset of field: EmpyreanODConfig::solve_for"]
[::std::mem::offset_of!(EmpyreanODConfig, solve_for) - 212usize];
["Offset of field: EmpyreanODConfig::auto_escalation"]
[::std::mem::offset_of!(EmpyreanODConfig, auto_escalation) - 216usize];
["Offset of field: EmpyreanODConfig::acceptability"]
[::std::mem::offset_of!(EmpyreanODConfig, acceptability) - 248usize];
["Offset of field: EmpyreanODConfig::fit_station_biases"]
[::std::mem::offset_of!(EmpyreanODConfig, fit_station_biases) - 288usize];
["Offset of field: EmpyreanODConfig::station_radec"]
[::std::mem::offset_of!(EmpyreanODConfig, station_radec) - 296usize];
["Offset of field: EmpyreanODConfig::use_span_grouping"]
[::std::mem::offset_of!(EmpyreanODConfig, use_span_grouping) - 312usize];
["Offset of field: EmpyreanODConfig::rejection"]
[::std::mem::offset_of!(EmpyreanODConfig, rejection) - 320usize];
["Offset of field: EmpyreanODConfig::auto_force_model"]
[::std::mem::offset_of!(EmpyreanODConfig, auto_force_model) - 376usize];
["Offset of field: EmpyreanODConfig::output_representation"]
[::std::mem::offset_of!(EmpyreanODConfig, output_representation) - 380usize];
};
impl Default for EmpyreanODConfig {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Aggregate residual statistics.\n\n All angular quantities in arcseconds. NaN entries indicate the stat\n could not be computed (e.g. AT/CT RMS when no sky-motion rates were\n available, or weighted RMS when no weighting layer was active)."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanResidualSummary {
pub num_obs: usize,
pub num_selected: usize,
pub num_rejected: usize,
#[doc = " Total χ² over selected observations."]
pub chi2: f64,
#[doc = " Effective degrees of freedom (after subtracting solve-for params)."]
pub dof: usize,
#[doc = " Reduced χ² = chi2 / dof. NaN when dof ≤ 0."]
pub reduced_chi2: f64,
pub rms_ra_arcsec: f64,
pub rms_dec_arcsec: f64,
#[doc = " Combined RA·cosδ + Dec residual RMS (arcsec). Matches the\n find_orb / OrbFit `rms` reporting convention — a single\n number directly comparable across tools."]
pub rms_combined_arcsec: f64,
#[doc = " RMS weighted by the per-observation σ (matches scott's `weighted_rms`)."]
pub weighted_rms_ra_arcsec: f64,
pub weighted_rms_dec_arcsec: f64,
#[doc = " Combined weighted RA·cosδ + Dec residual RMS (arcsec)."]
pub weighted_rms_combined_arcsec: f64,
pub mean_ra_arcsec: f64,
pub mean_dec_arcsec: f64,
pub std_ra_arcsec: f64,
pub std_dec_arcsec: f64,
#[doc = " RMS along-track residual (arcsec). NaN if no AT/CT data."]
pub rms_along_track_arcsec: f64,
#[doc = " RMS cross-track residual (arcsec). NaN if no AT/CT data."]
pub rms_cross_track_arcsec: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanResidualSummary"]
[::std::mem::size_of::<EmpyreanResidualSummary>() - 144usize];
["Alignment of EmpyreanResidualSummary"]
[::std::mem::align_of::<EmpyreanResidualSummary>() - 8usize];
["Offset of field: EmpyreanResidualSummary::num_obs"]
[::std::mem::offset_of!(EmpyreanResidualSummary, num_obs) - 0usize];
["Offset of field: EmpyreanResidualSummary::num_selected"]
[::std::mem::offset_of!(EmpyreanResidualSummary, num_selected) - 8usize];
["Offset of field: EmpyreanResidualSummary::num_rejected"]
[::std::mem::offset_of!(EmpyreanResidualSummary, num_rejected) - 16usize];
["Offset of field: EmpyreanResidualSummary::chi2"]
[::std::mem::offset_of!(EmpyreanResidualSummary, chi2) - 24usize];
["Offset of field: EmpyreanResidualSummary::dof"]
[::std::mem::offset_of!(EmpyreanResidualSummary, dof) - 32usize];
["Offset of field: EmpyreanResidualSummary::reduced_chi2"]
[::std::mem::offset_of!(EmpyreanResidualSummary, reduced_chi2) - 40usize];
["Offset of field: EmpyreanResidualSummary::rms_ra_arcsec"]
[::std::mem::offset_of!(EmpyreanResidualSummary, rms_ra_arcsec) - 48usize];
["Offset of field: EmpyreanResidualSummary::rms_dec_arcsec"]
[::std::mem::offset_of!(EmpyreanResidualSummary, rms_dec_arcsec) - 56usize];
["Offset of field: EmpyreanResidualSummary::rms_combined_arcsec"]
[::std::mem::offset_of!(EmpyreanResidualSummary, rms_combined_arcsec) - 64usize];
["Offset of field: EmpyreanResidualSummary::weighted_rms_ra_arcsec"]
[::std::mem::offset_of!(EmpyreanResidualSummary, weighted_rms_ra_arcsec) - 72usize];
["Offset of field: EmpyreanResidualSummary::weighted_rms_dec_arcsec"]
[::std::mem::offset_of!(EmpyreanResidualSummary, weighted_rms_dec_arcsec) - 80usize];
["Offset of field: EmpyreanResidualSummary::weighted_rms_combined_arcsec"]
[::std::mem::offset_of!(EmpyreanResidualSummary, weighted_rms_combined_arcsec) - 88usize];
["Offset of field: EmpyreanResidualSummary::mean_ra_arcsec"]
[::std::mem::offset_of!(EmpyreanResidualSummary, mean_ra_arcsec) - 96usize];
["Offset of field: EmpyreanResidualSummary::mean_dec_arcsec"]
[::std::mem::offset_of!(EmpyreanResidualSummary, mean_dec_arcsec) - 104usize];
["Offset of field: EmpyreanResidualSummary::std_ra_arcsec"]
[::std::mem::offset_of!(EmpyreanResidualSummary, std_ra_arcsec) - 112usize];
["Offset of field: EmpyreanResidualSummary::std_dec_arcsec"]
[::std::mem::offset_of!(EmpyreanResidualSummary, std_dec_arcsec) - 120usize];
["Offset of field: EmpyreanResidualSummary::rms_along_track_arcsec"]
[::std::mem::offset_of!(EmpyreanResidualSummary, rms_along_track_arcsec) - 128usize];
["Offset of field: EmpyreanResidualSummary::rms_cross_track_arcsec"]
[::std::mem::offset_of!(EmpyreanResidualSummary, rms_cross_track_arcsec) - 136usize];
};
#[doc = " A complete non-gravitational acceleration model, flattened for the C ABI.\n\n Mirrors the fields the input [`EmpyreanOrbit`] carries, so a fitted orbit's\n non-grav can be read back off [`EmpyreanODResult::non_grav`] and re-applied\n to an `EmpyreanOrbit` with no loss: the radial/transverse/normal\n coefficients (A1/A2/A3, AU/day²), the Marsden–Sekanina g(r) exponents\n (`ng_alpha`..`ng_k`; all-zero = inverse-square default), and the optional\n thermal-lag delay `non_grav_dt` (days, valid only when `has_dt = 1`)."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanNonGravParams {
pub a1: f64,
pub a2: f64,
pub a3: f64,
pub ng_alpha: f64,
pub ng_r0: f64,
pub ng_m: f64,
pub ng_n: f64,
pub ng_k: f64,
#[doc = " 1 when `non_grav_dt` carries a thermal-lag delay; 0 otherwise."]
pub has_dt: u8,
#[doc = " g(r) evaluation time delay (days); only meaningful when `has_dt = 1`."]
pub non_grav_dt: f64,
#[doc = " 1 when `covariance` carries the fitted non-grav covariance; 0 otherwise."]
pub has_covariance: u8,
#[doc = " Fitted non-grav 3×3 covariance for (A1, A2, A3), row-major. Only\n meaningful when `has_covariance = 1`. Re-feeding it onto an input\n orbit lets a fitted orbit flow into a StateAndNonGrav refine without\n losing its non-grav prior."]
pub covariance: [[f64; 3usize]; 3usize],
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanNonGravParams"][::std::mem::size_of::<EmpyreanNonGravParams>() - 160usize];
["Alignment of EmpyreanNonGravParams"]
[::std::mem::align_of::<EmpyreanNonGravParams>() - 8usize];
["Offset of field: EmpyreanNonGravParams::a1"]
[::std::mem::offset_of!(EmpyreanNonGravParams, a1) - 0usize];
["Offset of field: EmpyreanNonGravParams::a2"]
[::std::mem::offset_of!(EmpyreanNonGravParams, a2) - 8usize];
["Offset of field: EmpyreanNonGravParams::a3"]
[::std::mem::offset_of!(EmpyreanNonGravParams, a3) - 16usize];
["Offset of field: EmpyreanNonGravParams::ng_alpha"]
[::std::mem::offset_of!(EmpyreanNonGravParams, ng_alpha) - 24usize];
["Offset of field: EmpyreanNonGravParams::ng_r0"]
[::std::mem::offset_of!(EmpyreanNonGravParams, ng_r0) - 32usize];
["Offset of field: EmpyreanNonGravParams::ng_m"]
[::std::mem::offset_of!(EmpyreanNonGravParams, ng_m) - 40usize];
["Offset of field: EmpyreanNonGravParams::ng_n"]
[::std::mem::offset_of!(EmpyreanNonGravParams, ng_n) - 48usize];
["Offset of field: EmpyreanNonGravParams::ng_k"]
[::std::mem::offset_of!(EmpyreanNonGravParams, ng_k) - 56usize];
["Offset of field: EmpyreanNonGravParams::has_dt"]
[::std::mem::offset_of!(EmpyreanNonGravParams, has_dt) - 64usize];
["Offset of field: EmpyreanNonGravParams::non_grav_dt"]
[::std::mem::offset_of!(EmpyreanNonGravParams, non_grav_dt) - 72usize];
["Offset of field: EmpyreanNonGravParams::has_covariance"]
[::std::mem::offset_of!(EmpyreanNonGravParams, has_covariance) - 80usize];
["Offset of field: EmpyreanNonGravParams::covariance"]
[::std::mem::offset_of!(EmpyreanNonGravParams, covariance) - 88usize];
};
#[doc = " Acceptability sub-checks computed post-DC.\n\n Mirrors scott's [`AcceptabilityReport`](scott::od::AcceptabilityReport).\n Boolean fields are encoded as `u8` (0/1). When a value is unavailable\n (e.g. AT/CT ratio with no sky-motion rates), the `_value` is NaN and\n the corresponding `_ok` flag is 0. Always populated on\n [`EmpyreanODResult`]; on [`EmpyreanEvaluateResult`] the report is\n filled with NaN/0 because evaluate does not produce a fitted orbit."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanAcceptabilityReport {
pub fit_acceptable: u8,
pub extrapolation_acceptable: u8,
pub converged_ok: u8,
pub reduced_chi2_ok: u8,
pub reduced_chi2_value: f64,
pub reduced_chi2_threshold: f64,
pub rms_ok: u8,
pub rms_value_arcsec: f64,
pub rms_threshold_arcsec: f64,
pub residual_isotropy_ok: u8,
pub at_ct_ratio_value: f64,
pub at_ct_ratio_threshold: f64,
pub covariance_ok: u8,
pub arc_coverage_ok: u8,
pub arc_days_value: f64,
pub arc_days_threshold: f64,
pub fractional_sigma_a_ok: u8,
pub fractional_sigma_a_value: f64,
pub fractional_sigma_a_threshold: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanAcceptabilityReport"]
[::std::mem::size_of::<EmpyreanAcceptabilityReport>() - 120usize];
["Alignment of EmpyreanAcceptabilityReport"]
[::std::mem::align_of::<EmpyreanAcceptabilityReport>() - 8usize];
["Offset of field: EmpyreanAcceptabilityReport::fit_acceptable"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, fit_acceptable) - 0usize];
["Offset of field: EmpyreanAcceptabilityReport::extrapolation_acceptable"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, extrapolation_acceptable) - 1usize];
["Offset of field: EmpyreanAcceptabilityReport::converged_ok"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, converged_ok) - 2usize];
["Offset of field: EmpyreanAcceptabilityReport::reduced_chi2_ok"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, reduced_chi2_ok) - 3usize];
["Offset of field: EmpyreanAcceptabilityReport::reduced_chi2_value"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, reduced_chi2_value) - 8usize];
["Offset of field: EmpyreanAcceptabilityReport::reduced_chi2_threshold"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, reduced_chi2_threshold) - 16usize];
["Offset of field: EmpyreanAcceptabilityReport::rms_ok"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, rms_ok) - 24usize];
["Offset of field: EmpyreanAcceptabilityReport::rms_value_arcsec"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, rms_value_arcsec) - 32usize];
["Offset of field: EmpyreanAcceptabilityReport::rms_threshold_arcsec"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, rms_threshold_arcsec) - 40usize];
["Offset of field: EmpyreanAcceptabilityReport::residual_isotropy_ok"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, residual_isotropy_ok) - 48usize];
["Offset of field: EmpyreanAcceptabilityReport::at_ct_ratio_value"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, at_ct_ratio_value) - 56usize];
["Offset of field: EmpyreanAcceptabilityReport::at_ct_ratio_threshold"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, at_ct_ratio_threshold) - 64usize];
["Offset of field: EmpyreanAcceptabilityReport::covariance_ok"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, covariance_ok) - 72usize];
["Offset of field: EmpyreanAcceptabilityReport::arc_coverage_ok"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, arc_coverage_ok) - 73usize];
["Offset of field: EmpyreanAcceptabilityReport::arc_days_value"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, arc_days_value) - 80usize];
["Offset of field: EmpyreanAcceptabilityReport::arc_days_threshold"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, arc_days_threshold) - 88usize];
["Offset of field: EmpyreanAcceptabilityReport::fractional_sigma_a_ok"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, fractional_sigma_a_ok) - 96usize];
["Offset of field: EmpyreanAcceptabilityReport::fractional_sigma_a_value"]
[::std::mem::offset_of!(EmpyreanAcceptabilityReport, fractional_sigma_a_value) - 104usize];
["Offset of field: EmpyreanAcceptabilityReport::fractional_sigma_a_threshold"][::std::mem::offset_of!(
EmpyreanAcceptabilityReport,
fractional_sigma_a_threshold
) - 112usize];
};
#[doc = " One per-station bias estimate from a Schur-eliminated nuisance fit.\n\n Mirrors [`scott::results::StationBias`]. Populated rows in the\n returned array correspond to stations that met the\n `min_obs_per_station` threshold; under-observed stations are absent.\n Timing fields are populated only when a `BiasKind::StationTiming`\n nuisance was active (currently no surface to enable it from the C\n ABI; reserved for a planned follow-up).\n\n `obs_code` is heap-allocated and owned by the parent array — freed\n by [`empyrean_od_result_free`] when the result is freed. Don't free\n it manually."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanStationBias {
pub obs_code: *mut ::std::os::raw::c_char,
#[doc = " Pre-rejection observation count from this station."]
pub n_obs: usize,
pub bias_ra_arcsec: f64,
pub sigma_ra_arcsec: f64,
pub bias_dec_arcsec: f64,
pub sigma_dec_arcsec: f64,
#[doc = " 1 when the timing bias is populated; 0 otherwise. Reserved for\n the planned `BiasKind::StationTiming` follow-up."]
pub has_timing: u8,
pub bias_timing_sec: f64,
pub sigma_timing_sec: f64,
#[doc = " Scalar significance: max of |bᵢ|/σᵢ across populated components."]
pub significance: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanStationBias"][::std::mem::size_of::<EmpyreanStationBias>() - 80usize];
["Alignment of EmpyreanStationBias"][::std::mem::align_of::<EmpyreanStationBias>() - 8usize];
["Offset of field: EmpyreanStationBias::obs_code"]
[::std::mem::offset_of!(EmpyreanStationBias, obs_code) - 0usize];
["Offset of field: EmpyreanStationBias::n_obs"]
[::std::mem::offset_of!(EmpyreanStationBias, n_obs) - 8usize];
["Offset of field: EmpyreanStationBias::bias_ra_arcsec"]
[::std::mem::offset_of!(EmpyreanStationBias, bias_ra_arcsec) - 16usize];
["Offset of field: EmpyreanStationBias::sigma_ra_arcsec"]
[::std::mem::offset_of!(EmpyreanStationBias, sigma_ra_arcsec) - 24usize];
["Offset of field: EmpyreanStationBias::bias_dec_arcsec"]
[::std::mem::offset_of!(EmpyreanStationBias, bias_dec_arcsec) - 32usize];
["Offset of field: EmpyreanStationBias::sigma_dec_arcsec"]
[::std::mem::offset_of!(EmpyreanStationBias, sigma_dec_arcsec) - 40usize];
["Offset of field: EmpyreanStationBias::has_timing"]
[::std::mem::offset_of!(EmpyreanStationBias, has_timing) - 48usize];
["Offset of field: EmpyreanStationBias::bias_timing_sec"]
[::std::mem::offset_of!(EmpyreanStationBias, bias_timing_sec) - 56usize];
["Offset of field: EmpyreanStationBias::sigma_timing_sec"]
[::std::mem::offset_of!(EmpyreanStationBias, sigma_timing_sec) - 64usize];
["Offset of field: EmpyreanStationBias::significance"]
[::std::mem::offset_of!(EmpyreanStationBias, significance) - 72usize];
};
impl Default for EmpyreanStationBias {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Result of orbit determination (determine or refine).\n\n Mirrors scott's [`ODResult`](scott::od::ODResult). Carries the fitted\n orbit, the 6×6 (or 9×9 when non-grav was solved) formal covariance,\n the per-observation result array, the summary, the structured\n acceptability report, and the per-station nuisance-bias array\n when `fit_station_biases` was active.\n\n The fitted **absolute** non-gravitational model (when one was solved\n or carried) is exposed via [`has_non_grav`](EmpyreanODResult::has_non_grav)\n / [`non_grav`](EmpyreanODResult::non_grav) so the orbit can be re-fed into\n propagation / evaluate / refine without losing the force model. This is\n distinct from [`non_grav_delta`](EmpyreanODResult::non_grav_delta), which\n is the *cumulative correction* the fit applied and is kept for inspection."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanODResult {
pub orbit: EmpyreanPropagatedState,
pub observations: *mut EmpyreanObservationResult,
pub num_observations: usize,
pub summary: EmpyreanResidualSummary,
pub iterations: u32,
#[doc = " Convergence metric at the final DC iteration (Δx^T N Δx)."]
pub update_norm: f64,
#[doc = " Solver reached its stopping criterion (1 = yes).\n Equivalent to `acceptability.converged_ok`; kept for backwards\n compatibility with the v0.7.0 surface that pre-dated the\n structured acceptability report."]
pub converged: u8,
#[doc = " Fitted 6×6 state covariance in [`covariance_representation`]."]
pub covariance: [[f64; 6usize]; 6usize],
#[doc = " Coordinate basis the 6×6 / 9×9 covariance is reported in\n (`EMPYREAN_REPRESENTATION_*`)."]
pub covariance_representation: i32,
#[doc = " 1 when [`covariance_9x9`] is populated (non-grav was solved)."]
pub has_covariance_9x9: u8,
#[doc = " Full 9×9 covariance over (state, A1, A2, A3) when solving for non-grav."]
pub covariance_9x9: [[f64; 9usize]; 9usize],
#[doc = " 1 when [`non_grav_delta`] is populated."]
pub has_non_grav_delta: u8,
#[doc = " Cumulative non-grav parameter corrections (ΔA1, ΔA2, ΔA3) when solving for non-grav."]
pub non_grav_delta: [f64; 3usize],
#[doc = " 1 when [`non_grav`] carries a fitted/absolute non-gravitational model."]
pub has_non_grav: u8,
#[doc = " The fitted orbit's **absolute** non-gravitational model (A1/A2/A3 +\n g(r) exponents + optional thermal-lag `dt`). Re-feed this onto the\n orbit for propagation / evaluate / refine. Zeroed when the orbit is\n gravity-only (`has_non_grav = 0`)."]
pub non_grav: EmpyreanNonGravParams,
#[doc = " Number of rejection/refit passes performed."]
pub rejection_passes: u32,
#[doc = " Number of oppositions successfully fit."]
pub num_oppositions_fit: u32,
#[doc = " Force model tier actually used (0=Approximate, 1=Basic, 2=Standard)."]
pub force_model_used: i32,
#[doc = " Solve-for parameter set requested on the driving config\n (`EMPYREAN_SOLVE_FOR_*`). Together with `has_covariance_9x9`\n disambiguates Auto outcomes."]
pub solve_for_used: i32,
#[doc = " Structured fit-quality verdict. The `acceptable` flags can be\n checked directly; per-check values + thresholds are exposed for\n reporting and downstream sub-classification."]
pub acceptability: EmpyreanAcceptabilityReport,
#[doc = " Per-station fitted nuisance biases when [`EmpyreanODConfig::fit_station_biases`]\n was set. Owned heap allocation; freed by [`empyrean_od_result_free`].\n Null + `num_station_biases = 0` when no bias fit was configured."]
pub station_biases: *mut EmpyreanStationBias,
pub num_station_biases: usize,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanODResult"][::std::mem::size_of::<EmpyreanODResult>() - 3872usize];
["Alignment of EmpyreanODResult"][::std::mem::align_of::<EmpyreanODResult>() - 8usize];
["Offset of field: EmpyreanODResult::orbit"]
[::std::mem::offset_of!(EmpyreanODResult, orbit) - 0usize];
["Offset of field: EmpyreanODResult::observations"]
[::std::mem::offset_of!(EmpyreanODResult, observations) - 2392usize];
["Offset of field: EmpyreanODResult::num_observations"]
[::std::mem::offset_of!(EmpyreanODResult, num_observations) - 2400usize];
["Offset of field: EmpyreanODResult::summary"]
[::std::mem::offset_of!(EmpyreanODResult, summary) - 2408usize];
["Offset of field: EmpyreanODResult::iterations"]
[::std::mem::offset_of!(EmpyreanODResult, iterations) - 2552usize];
["Offset of field: EmpyreanODResult::update_norm"]
[::std::mem::offset_of!(EmpyreanODResult, update_norm) - 2560usize];
["Offset of field: EmpyreanODResult::converged"]
[::std::mem::offset_of!(EmpyreanODResult, converged) - 2568usize];
["Offset of field: EmpyreanODResult::covariance"]
[::std::mem::offset_of!(EmpyreanODResult, covariance) - 2576usize];
["Offset of field: EmpyreanODResult::covariance_representation"]
[::std::mem::offset_of!(EmpyreanODResult, covariance_representation) - 2864usize];
["Offset of field: EmpyreanODResult::has_covariance_9x9"]
[::std::mem::offset_of!(EmpyreanODResult, has_covariance_9x9) - 2868usize];
["Offset of field: EmpyreanODResult::covariance_9x9"]
[::std::mem::offset_of!(EmpyreanODResult, covariance_9x9) - 2872usize];
["Offset of field: EmpyreanODResult::has_non_grav_delta"]
[::std::mem::offset_of!(EmpyreanODResult, has_non_grav_delta) - 3520usize];
["Offset of field: EmpyreanODResult::non_grav_delta"]
[::std::mem::offset_of!(EmpyreanODResult, non_grav_delta) - 3528usize];
["Offset of field: EmpyreanODResult::has_non_grav"]
[::std::mem::offset_of!(EmpyreanODResult, has_non_grav) - 3552usize];
["Offset of field: EmpyreanODResult::non_grav"]
[::std::mem::offset_of!(EmpyreanODResult, non_grav) - 3560usize];
["Offset of field: EmpyreanODResult::rejection_passes"]
[::std::mem::offset_of!(EmpyreanODResult, rejection_passes) - 3720usize];
["Offset of field: EmpyreanODResult::num_oppositions_fit"]
[::std::mem::offset_of!(EmpyreanODResult, num_oppositions_fit) - 3724usize];
["Offset of field: EmpyreanODResult::force_model_used"]
[::std::mem::offset_of!(EmpyreanODResult, force_model_used) - 3728usize];
["Offset of field: EmpyreanODResult::solve_for_used"]
[::std::mem::offset_of!(EmpyreanODResult, solve_for_used) - 3732usize];
["Offset of field: EmpyreanODResult::acceptability"]
[::std::mem::offset_of!(EmpyreanODResult, acceptability) - 3736usize];
["Offset of field: EmpyreanODResult::station_biases"]
[::std::mem::offset_of!(EmpyreanODResult, station_biases) - 3856usize];
["Offset of field: EmpyreanODResult::num_station_biases"]
[::std::mem::offset_of!(EmpyreanODResult, num_station_biases) - 3864usize];
};
impl Default for EmpyreanODResult {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Result of orbit evaluation (residuals without fitting).\n\n Same per-observation surface as [`EmpyreanODResult`] (rejection +\n influence fields are NaN / `NOT_EVALUATED` because evaluate does\n not run rejection or influence passes), but no fitted orbit or\n acceptability report."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanEvaluateResult {
pub observations: *mut EmpyreanObservationResult,
pub num_observations: usize,
pub summary: EmpyreanResidualSummary,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanEvaluateResult"][::std::mem::size_of::<EmpyreanEvaluateResult>() - 160usize];
["Alignment of EmpyreanEvaluateResult"]
[::std::mem::align_of::<EmpyreanEvaluateResult>() - 8usize];
["Offset of field: EmpyreanEvaluateResult::observations"]
[::std::mem::offset_of!(EmpyreanEvaluateResult, observations) - 0usize];
["Offset of field: EmpyreanEvaluateResult::num_observations"]
[::std::mem::offset_of!(EmpyreanEvaluateResult, num_observations) - 8usize];
["Offset of field: EmpyreanEvaluateResult::summary"]
[::std::mem::offset_of!(EmpyreanEvaluateResult, summary) - 16usize];
};
impl Default for EmpyreanEvaluateResult {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " A single planned (candidate) observation: an epoch plus either an optical or\n a radar measurement spec. Optical fields are read when `kind == 0`, radar\n fields when `kind == 1`; absent optional radar target properties use NaN\n (the link budget refuses, rather than silently defaults, a missing value)."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanPlannedObservation {
#[doc = " Planned (receive, for radar) epoch — MJD, TDB."]
pub epoch_mjd_tdb: f64,
#[doc = " 0 = optical, 1 = radar."]
pub kind: u8,
#[doc = " Optical: registered MPC station code (null-terminated UTF-8)."]
pub optical_code: *const ::std::os::raw::c_char,
#[doc = " Optical 1σ (RA·cosδ) uncertainty (arcsec)."]
pub optical_sigma_ra_arcsec: f64,
#[doc = " Optical 1σ Dec uncertainty (arcsec)."]
pub optical_sigma_dec_arcsec: f64,
#[doc = " Radar transmit dish preset: 0 = Goldstone DSS-14, 1 = Green Bank\n (receive-only), 2 = Arecibo (defunct — rejected loudly, never scheduled)."]
pub radar_transmit_station: u8,
#[doc = " Radar receive dish preset (same encoding; equal to transmit = monostatic)."]
pub radar_receive_station: u8,
#[doc = " Radar mode: 0 = Delay, 1 = Doppler, 2 = Both."]
pub radar_mode: u8,
#[doc = " Waveform bandwidth (Hz) — sets the delay (range) σ."]
pub radar_bandwidth_hz: f64,
#[doc = " Doppler frequency resolution (Hz) — sets the Doppler (range-rate) σ."]
pub radar_freq_resolution_hz: f64,
#[doc = " Supplied effective SNR (linear, not dB). NaN → compute from the link\n budget using the target properties + integration time below."]
pub radar_snr: f64,
#[doc = " Link-budget target absolute magnitude H (mag). NaN = absent."]
pub radar_target_h_mag: f64,
#[doc = " Link-budget target visual geometric albedo. NaN = absent."]
pub radar_target_visual_albedo: f64,
#[doc = " Link-budget target radar (OC) albedo. NaN = absent."]
pub radar_target_radar_albedo: f64,
#[doc = " Link-budget target effective diameter (km). NaN = absent."]
pub radar_target_diameter_km: f64,
#[doc = " Link-budget target rotation period (hours), caps coherent integration.\n NaN = absent."]
pub radar_target_spin_period_hours: f64,
#[doc = " Coherent integration time (s) for the link-budget SNR."]
pub radar_integration_s: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanPlannedObservation"]
[::std::mem::size_of::<EmpyreanPlannedObservation>() - 120usize];
["Alignment of EmpyreanPlannedObservation"]
[::std::mem::align_of::<EmpyreanPlannedObservation>() - 8usize];
["Offset of field: EmpyreanPlannedObservation::epoch_mjd_tdb"]
[::std::mem::offset_of!(EmpyreanPlannedObservation, epoch_mjd_tdb) - 0usize];
["Offset of field: EmpyreanPlannedObservation::kind"]
[::std::mem::offset_of!(EmpyreanPlannedObservation, kind) - 8usize];
["Offset of field: EmpyreanPlannedObservation::optical_code"]
[::std::mem::offset_of!(EmpyreanPlannedObservation, optical_code) - 16usize];
["Offset of field: EmpyreanPlannedObservation::optical_sigma_ra_arcsec"]
[::std::mem::offset_of!(EmpyreanPlannedObservation, optical_sigma_ra_arcsec) - 24usize];
["Offset of field: EmpyreanPlannedObservation::optical_sigma_dec_arcsec"]
[::std::mem::offset_of!(EmpyreanPlannedObservation, optical_sigma_dec_arcsec) - 32usize];
["Offset of field: EmpyreanPlannedObservation::radar_transmit_station"]
[::std::mem::offset_of!(EmpyreanPlannedObservation, radar_transmit_station) - 40usize];
["Offset of field: EmpyreanPlannedObservation::radar_receive_station"]
[::std::mem::offset_of!(EmpyreanPlannedObservation, radar_receive_station) - 41usize];
["Offset of field: EmpyreanPlannedObservation::radar_mode"]
[::std::mem::offset_of!(EmpyreanPlannedObservation, radar_mode) - 42usize];
["Offset of field: EmpyreanPlannedObservation::radar_bandwidth_hz"]
[::std::mem::offset_of!(EmpyreanPlannedObservation, radar_bandwidth_hz) - 48usize];
["Offset of field: EmpyreanPlannedObservation::radar_freq_resolution_hz"]
[::std::mem::offset_of!(EmpyreanPlannedObservation, radar_freq_resolution_hz) - 56usize];
["Offset of field: EmpyreanPlannedObservation::radar_snr"]
[::std::mem::offset_of!(EmpyreanPlannedObservation, radar_snr) - 64usize];
["Offset of field: EmpyreanPlannedObservation::radar_target_h_mag"]
[::std::mem::offset_of!(EmpyreanPlannedObservation, radar_target_h_mag) - 72usize];
["Offset of field: EmpyreanPlannedObservation::radar_target_visual_albedo"]
[::std::mem::offset_of!(EmpyreanPlannedObservation, radar_target_visual_albedo) - 80usize];
["Offset of field: EmpyreanPlannedObservation::radar_target_radar_albedo"]
[::std::mem::offset_of!(EmpyreanPlannedObservation, radar_target_radar_albedo) - 88usize];
["Offset of field: EmpyreanPlannedObservation::radar_target_diameter_km"]
[::std::mem::offset_of!(EmpyreanPlannedObservation, radar_target_diameter_km) - 96usize];
["Offset of field: EmpyreanPlannedObservation::radar_target_spin_period_hours"][::std::mem::offset_of!(
EmpyreanPlannedObservation,
radar_target_spin_period_hours
) - 104usize];
["Offset of field: EmpyreanPlannedObservation::radar_integration_s"]
[::std::mem::offset_of!(EmpyreanPlannedObservation, radar_integration_s) - 112usize];
};
impl Default for EmpyreanPlannedObservation {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Per-observatory assumptions: astrometric σ + observability filters."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanObservatoryConfig {
#[doc = " MPC observatory code (null-terminated UTF-8)."]
pub obs_code: *const ::std::os::raw::c_char,
#[doc = " 1σ (RA·cosδ) astrometric uncertainty (arcsec)."]
pub sigma_ra_arcsec: f64,
#[doc = " 1σ Dec astrometric uncertainty (arcsec)."]
pub sigma_dec_arcsec: f64,
#[doc = " Limiting apparent magnitude."]
pub max_apparent_mag: f64,
#[doc = " Minimum solar elongation (degrees)."]
pub min_elongation_deg: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanObservatoryConfig"]
[::std::mem::size_of::<EmpyreanObservatoryConfig>() - 40usize];
["Alignment of EmpyreanObservatoryConfig"]
[::std::mem::align_of::<EmpyreanObservatoryConfig>() - 8usize];
["Offset of field: EmpyreanObservatoryConfig::obs_code"]
[::std::mem::offset_of!(EmpyreanObservatoryConfig, obs_code) - 0usize];
["Offset of field: EmpyreanObservatoryConfig::sigma_ra_arcsec"]
[::std::mem::offset_of!(EmpyreanObservatoryConfig, sigma_ra_arcsec) - 8usize];
["Offset of field: EmpyreanObservatoryConfig::sigma_dec_arcsec"]
[::std::mem::offset_of!(EmpyreanObservatoryConfig, sigma_dec_arcsec) - 16usize];
["Offset of field: EmpyreanObservatoryConfig::max_apparent_mag"]
[::std::mem::offset_of!(EmpyreanObservatoryConfig, max_apparent_mag) - 24usize];
["Offset of field: EmpyreanObservatoryConfig::min_elongation_deg"]
[::std::mem::offset_of!(EmpyreanObservatoryConfig, min_elongation_deg) - 32usize];
};
impl Default for EmpyreanObservatoryConfig {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Planning configuration: force model, integration tolerance, the\n per-observatory astrometric assumptions, and threading."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanPlanningConfig {
#[doc = " Force-model tier: 0 = Approximate, 1 = Basic, 2 = Standard."]
pub force_model: i32,
#[doc = " GR15 / IAS15 integration tolerance."]
pub epsilon: f64,
#[doc = " Per-observatory config array."]
pub observatories: *const EmpyreanObservatoryConfig,
#[doc = " Number of entries in `observatories`."]
pub num_observatories: usize,
#[doc = " Threads for batch operations; -1 = all CPUs."]
pub num_threads: i32,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanPlanningConfig"][::std::mem::size_of::<EmpyreanPlanningConfig>() - 40usize];
["Alignment of EmpyreanPlanningConfig"]
[::std::mem::align_of::<EmpyreanPlanningConfig>() - 8usize];
["Offset of field: EmpyreanPlanningConfig::force_model"]
[::std::mem::offset_of!(EmpyreanPlanningConfig, force_model) - 0usize];
["Offset of field: EmpyreanPlanningConfig::epsilon"]
[::std::mem::offset_of!(EmpyreanPlanningConfig, epsilon) - 8usize];
["Offset of field: EmpyreanPlanningConfig::observatories"]
[::std::mem::offset_of!(EmpyreanPlanningConfig, observatories) - 16usize];
["Offset of field: EmpyreanPlanningConfig::num_observatories"]
[::std::mem::offset_of!(EmpyreanPlanningConfig, num_observatories) - 24usize];
["Offset of field: EmpyreanPlanningConfig::num_threads"]
[::std::mem::offset_of!(EmpyreanPlanningConfig, num_threads) - 32usize];
};
impl Default for EmpyreanPlanningConfig {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Covariance summary metrics (prior, posterior, or per-candidate cumulative)."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanCovarianceMetrics {
#[doc = " RSS position 1σ (km)."]
pub position_sigma_km: f64,
#[doc = " RSS velocity 1σ (m/s) — the rendezvous-Δv-knowledge term."]
pub velocity_sigma_m_s: f64,
#[doc = " Semi-major axis of the 1σ position ellipsoid (km)."]
pub semi_major_km: f64,
#[doc = " Semi-minor axis of the 1σ position ellipsoid (km)."]
pub semi_minor_km: f64,
#[doc = " ln(det(Σ)) — D-optimality criterion."]
pub log_det: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanCovarianceMetrics"]
[::std::mem::size_of::<EmpyreanCovarianceMetrics>() - 40usize];
["Alignment of EmpyreanCovarianceMetrics"]
[::std::mem::align_of::<EmpyreanCovarianceMetrics>() - 8usize];
["Offset of field: EmpyreanCovarianceMetrics::position_sigma_km"]
[::std::mem::offset_of!(EmpyreanCovarianceMetrics, position_sigma_km) - 0usize];
["Offset of field: EmpyreanCovarianceMetrics::velocity_sigma_m_s"]
[::std::mem::offset_of!(EmpyreanCovarianceMetrics, velocity_sigma_m_s) - 8usize];
["Offset of field: EmpyreanCovarianceMetrics::semi_major_km"]
[::std::mem::offset_of!(EmpyreanCovarianceMetrics, semi_major_km) - 16usize];
["Offset of field: EmpyreanCovarianceMetrics::semi_minor_km"]
[::std::mem::offset_of!(EmpyreanCovarianceMetrics, semi_minor_km) - 24usize];
["Offset of field: EmpyreanCovarianceMetrics::log_det"]
[::std::mem::offset_of!(EmpyreanCovarianceMetrics, log_det) - 32usize];
};
#[doc = " Per-candidate information-gain analysis."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanPlanCandidate {
#[doc = " Index into the planned-observation list."]
pub index: usize,
#[doc = " Observatory / receive-station code (owned; freed by\n `empyrean_plan_result_free`)."]
pub obs_code: *mut ::std::os::raw::c_char,
#[doc = " 0 = optical, 1 = radar."]
pub kind: u8,
#[doc = " 1 if observable at this epoch (passes the filters / has positive SNR)."]
pub observable: u8,
#[doc = " Sky-plane along-track 1σ (arcsec) — optical geometry (NaN for radar)."]
pub along_track_sigma_arcsec: f64,
#[doc = " Sky-plane cross-track 1σ (arcsec)."]
pub cross_track_sigma_arcsec: f64,
#[doc = " Predicted RA·cosδ 1σ (arcsec)."]
pub ra_sigma_arcsec: f64,
#[doc = " Predicted Dec 1σ (arcsec)."]
pub dec_sigma_arcsec: f64,
#[doc = " Position angle of the sky-plane uncertainty ellipse (degrees)."]
pub position_angle_deg: f64,
#[doc = " Marginal covariance-volume reduction factor from this observation (≤ 1)."]
pub marginal_volume_reduction: f64,
#[doc = " Fractional position-σ improvement from this observation (∈ [0, 1])."]
pub marginal_position_improvement: f64,
#[doc = " Post-observation along-track 1σ (arcsec)."]
pub post_along_track_sigma_arcsec: f64,
#[doc = " Post-observation cross-track 1σ (arcsec)."]
pub post_cross_track_sigma_arcsec: f64,
#[doc = " Covariance metrics after folding this observation and all prior ones."]
pub cumulative: EmpyreanCovarianceMetrics,
#[doc = " Active solve-for width (6 = state-only)."]
pub active_width: usize,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanPlanCandidate"][::std::mem::size_of::<EmpyreanPlanCandidate>() - 144usize];
["Alignment of EmpyreanPlanCandidate"]
[::std::mem::align_of::<EmpyreanPlanCandidate>() - 8usize];
["Offset of field: EmpyreanPlanCandidate::index"]
[::std::mem::offset_of!(EmpyreanPlanCandidate, index) - 0usize];
["Offset of field: EmpyreanPlanCandidate::obs_code"]
[::std::mem::offset_of!(EmpyreanPlanCandidate, obs_code) - 8usize];
["Offset of field: EmpyreanPlanCandidate::kind"]
[::std::mem::offset_of!(EmpyreanPlanCandidate, kind) - 16usize];
["Offset of field: EmpyreanPlanCandidate::observable"]
[::std::mem::offset_of!(EmpyreanPlanCandidate, observable) - 17usize];
["Offset of field: EmpyreanPlanCandidate::along_track_sigma_arcsec"]
[::std::mem::offset_of!(EmpyreanPlanCandidate, along_track_sigma_arcsec) - 24usize];
["Offset of field: EmpyreanPlanCandidate::cross_track_sigma_arcsec"]
[::std::mem::offset_of!(EmpyreanPlanCandidate, cross_track_sigma_arcsec) - 32usize];
["Offset of field: EmpyreanPlanCandidate::ra_sigma_arcsec"]
[::std::mem::offset_of!(EmpyreanPlanCandidate, ra_sigma_arcsec) - 40usize];
["Offset of field: EmpyreanPlanCandidate::dec_sigma_arcsec"]
[::std::mem::offset_of!(EmpyreanPlanCandidate, dec_sigma_arcsec) - 48usize];
["Offset of field: EmpyreanPlanCandidate::position_angle_deg"]
[::std::mem::offset_of!(EmpyreanPlanCandidate, position_angle_deg) - 56usize];
["Offset of field: EmpyreanPlanCandidate::marginal_volume_reduction"]
[::std::mem::offset_of!(EmpyreanPlanCandidate, marginal_volume_reduction) - 64usize];
["Offset of field: EmpyreanPlanCandidate::marginal_position_improvement"]
[::std::mem::offset_of!(EmpyreanPlanCandidate, marginal_position_improvement) - 72usize];
["Offset of field: EmpyreanPlanCandidate::post_along_track_sigma_arcsec"]
[::std::mem::offset_of!(EmpyreanPlanCandidate, post_along_track_sigma_arcsec) - 80usize];
["Offset of field: EmpyreanPlanCandidate::post_cross_track_sigma_arcsec"]
[::std::mem::offset_of!(EmpyreanPlanCandidate, post_cross_track_sigma_arcsec) - 88usize];
["Offset of field: EmpyreanPlanCandidate::cumulative"]
[::std::mem::offset_of!(EmpyreanPlanCandidate, cumulative) - 96usize];
["Offset of field: EmpyreanPlanCandidate::active_width"]
[::std::mem::offset_of!(EmpyreanPlanCandidate, active_width) - 136usize];
};
impl Default for EmpyreanPlanCandidate {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Result of a plan evaluation. The caller allocates the struct; the\n `orbit_id` string and the `candidates` array (with their `obs_code`\n strings) are heap-allocated here and must be released with\n [`empyrean_plan_result_free`]."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanPlanResult {
#[doc = " Orbit identifier (owned)."]
pub orbit_id: *mut ::std::os::raw::c_char,
#[doc = " Prior (pre-observation) covariance metrics."]
pub prior: EmpyreanCovarianceMetrics,
#[doc = " Posterior (all candidates folded) covariance metrics."]
pub posterior: EmpyreanCovarianceMetrics,
#[doc = " Per-candidate analysis array (owned)."]
pub candidates: *mut EmpyreanPlanCandidate,
#[doc = " Number of entries in `candidates`."]
pub num_candidates: usize,
#[doc = " Active solve-for width (6 = state-only)."]
pub active_width: usize,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanPlanResult"][::std::mem::size_of::<EmpyreanPlanResult>() - 112usize];
["Alignment of EmpyreanPlanResult"][::std::mem::align_of::<EmpyreanPlanResult>() - 8usize];
["Offset of field: EmpyreanPlanResult::orbit_id"]
[::std::mem::offset_of!(EmpyreanPlanResult, orbit_id) - 0usize];
["Offset of field: EmpyreanPlanResult::prior"]
[::std::mem::offset_of!(EmpyreanPlanResult, prior) - 8usize];
["Offset of field: EmpyreanPlanResult::posterior"]
[::std::mem::offset_of!(EmpyreanPlanResult, posterior) - 48usize];
["Offset of field: EmpyreanPlanResult::candidates"]
[::std::mem::offset_of!(EmpyreanPlanResult, candidates) - 88usize];
["Offset of field: EmpyreanPlanResult::num_candidates"]
[::std::mem::offset_of!(EmpyreanPlanResult, num_candidates) - 96usize];
["Offset of field: EmpyreanPlanResult::active_width"]
[::std::mem::offset_of!(EmpyreanPlanResult, active_width) - 104usize];
};
impl Default for EmpyreanPlanResult {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Flattened, owned form of `empyrean_core::propagation::TaggedCovariance`\n (villeneuve's provenance-tagged covariance). Self-describing: the 6×6\n matrix together with the co-located nominal state, how the covariance\n was derived, its definiteness, its basis, the solved-for parameters,\n and the functional it describes — so a consumer can never read a\n second-order CA ellipsoid as a linear one.\n\n NOTE on the `_cartesian` accessor's reachable range: that accessor\n classifies but never repairs (`quality` ∈ {POSITIVE_DEFINITE,\n INDEFINITE}), is always state-only (`solved_width == 6`,\n `target_functional == CARTESIAN_STATE`, `has_mean_shift_input == 0`),\n and resolves Monte-Carlo epochs to an error rather than a row. The\n constant fields are carried for the future element-space / off-grid /\n CA-window accessors that *do* vary them."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanTaggedCovariance {
#[doc = " Epoch of this covariance (TDB)."]
pub epoch_mjd_tdb: f64,
#[doc = " Propagated nominal state [x, y, z, vx, vy, vz] (AU, AU/day),\n co-located engine-side. The CORRECTED mean is\n `state + (has_mean_shift_prop ? mean_shift_prop : 0)\n + (has_mean_shift_input ? mean_shift_input : 0)`."]
pub state: [f64; 6usize],
#[doc = " The 6×6 covariance (AU², AU²/day, AU²/day² blocks)."]
pub matrix: [[f64; 6usize]; 6usize],
#[doc = " `EMPYREAN_COVARIANCE_KIND_*`."]
pub kind: u8,
#[doc = " RNG seed — valid iff `has_mc_seed == 1` (kind == MONTE_CARLO)."]
pub mc_seed: u64,
#[doc = " Disambiguates a real `mc_seed == 0` from \"no seed\". 0 on the\n `_cartesian` accessor (MC resolves to an error there)."]
pub has_mc_seed: u8,
#[doc = " Second-order propagation mean shift δμ_prop (zero at t₀).\n Zero-filled when `has_mean_shift_prop == 0`."]
pub mean_shift_prop: [f64; 6usize],
pub has_mean_shift_prop: u8,
#[doc = " OD-estimator mean shift δμ₀ (nonzero at t₀). Zero-filled when\n `has_mean_shift_input == 0` (always 0 on the `_cartesian` accessor)."]
pub mean_shift_input: [f64; 6usize],
pub has_mean_shift_input: u8,
#[doc = " `EMPYREAN_COVARIANCE_QUALITY_*`."]
pub quality: u8,
#[doc = " `min_eig` for INDEFINITE / REPAIRED; `f64::NAN` for\n POSITIVE_DEFINITE. **Read-only provenance** — `isnan`-guard before\n any arithmetic; never feed to a clamp."]
pub quality_min_eig: f64,
#[doc = " `EMPYREAN_REPRESENTATION_*` (always CARTESIAN=0 on this accessor)."]
pub representation: i32,
#[doc = " Frame, same encoding as `EmpyreanPropagatedState.frame`."]
pub frame: i32,
#[doc = " Origin NAIF id, same encoding as `EmpyreanPropagatedState.origin`."]
pub origin: i32,
#[doc = " [A1, A2, A3] non-grav solved flags (0/1). The returned 6×6 is the\n MARGINALIZED state block of a possibly-wider fit."]
pub non_grav: [u8; 3usize],
#[doc = " Thrust Δv segments solved for."]
pub thrust_segments: u32,
#[doc = " `TaggedCovariance::solved_width()` (6 / 9 / 12 / …) — the scalar\n IP consumers key on (6 on this accessor)."]
pub solved_width: u32,
#[doc = " `EMPYREAN_TARGET_FUNCTIONAL_*` (always CARTESIAN_STATE on this accessor)."]
pub target_functional: u8,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanTaggedCovariance"]
[::std::mem::size_of::<EmpyreanTaggedCovariance>() - 520usize];
["Alignment of EmpyreanTaggedCovariance"]
[::std::mem::align_of::<EmpyreanTaggedCovariance>() - 8usize];
["Offset of field: EmpyreanTaggedCovariance::epoch_mjd_tdb"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, epoch_mjd_tdb) - 0usize];
["Offset of field: EmpyreanTaggedCovariance::state"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, state) - 8usize];
["Offset of field: EmpyreanTaggedCovariance::matrix"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, matrix) - 56usize];
["Offset of field: EmpyreanTaggedCovariance::kind"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, kind) - 344usize];
["Offset of field: EmpyreanTaggedCovariance::mc_seed"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, mc_seed) - 352usize];
["Offset of field: EmpyreanTaggedCovariance::has_mc_seed"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, has_mc_seed) - 360usize];
["Offset of field: EmpyreanTaggedCovariance::mean_shift_prop"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, mean_shift_prop) - 368usize];
["Offset of field: EmpyreanTaggedCovariance::has_mean_shift_prop"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, has_mean_shift_prop) - 416usize];
["Offset of field: EmpyreanTaggedCovariance::mean_shift_input"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, mean_shift_input) - 424usize];
["Offset of field: EmpyreanTaggedCovariance::has_mean_shift_input"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, has_mean_shift_input) - 472usize];
["Offset of field: EmpyreanTaggedCovariance::quality"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, quality) - 473usize];
["Offset of field: EmpyreanTaggedCovariance::quality_min_eig"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, quality_min_eig) - 480usize];
["Offset of field: EmpyreanTaggedCovariance::representation"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, representation) - 488usize];
["Offset of field: EmpyreanTaggedCovariance::frame"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, frame) - 492usize];
["Offset of field: EmpyreanTaggedCovariance::origin"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, origin) - 496usize];
["Offset of field: EmpyreanTaggedCovariance::non_grav"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, non_grav) - 500usize];
["Offset of field: EmpyreanTaggedCovariance::thrust_segments"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, thrust_segments) - 504usize];
["Offset of field: EmpyreanTaggedCovariance::solved_width"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, solved_width) - 508usize];
["Offset of field: EmpyreanTaggedCovariance::target_functional"]
[::std::mem::offset_of!(EmpyreanTaggedCovariance, target_functional) - 512usize];
};
#[doc = " Owned series of [`EmpyreanTaggedCovariance`], one entry per output\n epoch. Free with [`empyrean_tagged_covariance_series_free`]."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanTaggedCovarianceSeries {
pub entries: *mut EmpyreanTaggedCovariance,
pub num_entries: usize,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanTaggedCovarianceSeries"]
[::std::mem::size_of::<EmpyreanTaggedCovarianceSeries>() - 16usize];
["Alignment of EmpyreanTaggedCovarianceSeries"]
[::std::mem::align_of::<EmpyreanTaggedCovarianceSeries>() - 8usize];
["Offset of field: EmpyreanTaggedCovarianceSeries::entries"]
[::std::mem::offset_of!(EmpyreanTaggedCovarianceSeries, entries) - 0usize];
["Offset of field: EmpyreanTaggedCovarianceSeries::num_entries"]
[::std::mem::offset_of!(EmpyreanTaggedCovarianceSeries, num_entries) - 8usize];
};
impl Default for EmpyreanTaggedCovarianceSeries {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[doc = " Opaque handle to an `empyrean_core::determination::Session`.\n\n Owns observations, the mask state, and the fit history. Construct\n with [`empyrean_session_new`]; release with\n [`empyrean_session_free`]. The handle is **not** thread-safe — do\n not share between threads without external synchronization."]
pub type EmpyreanSession = Session;
#[doc = " Pairwise diagnostic returned by [`empyrean_session_diff`]."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanSessionDiff {
#[doc = " Δ reduced χ² (positive ⇒ current fit is worse than prior)."]
pub reduced_chi2_delta: f64,
#[doc = " Δ iteration count."]
pub iterations_delta: i64,
#[doc = " Δ number of observations used (negative ⇒ observations were\n masked between prior and current)."]
pub n_observations_delta: i64,
#[doc = " Final update-norm convergence metric on the current fit."]
pub update_norm_current: f64,
#[doc = " Final update-norm convergence metric on the prior fit."]
pub update_norm_prior: f64,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanSessionDiff"][::std::mem::size_of::<EmpyreanSessionDiff>() - 40usize];
["Alignment of EmpyreanSessionDiff"][::std::mem::align_of::<EmpyreanSessionDiff>() - 8usize];
["Offset of field: EmpyreanSessionDiff::reduced_chi2_delta"]
[::std::mem::offset_of!(EmpyreanSessionDiff, reduced_chi2_delta) - 0usize];
["Offset of field: EmpyreanSessionDiff::iterations_delta"]
[::std::mem::offset_of!(EmpyreanSessionDiff, iterations_delta) - 8usize];
["Offset of field: EmpyreanSessionDiff::n_observations_delta"]
[::std::mem::offset_of!(EmpyreanSessionDiff, n_observations_delta) - 16usize];
["Offset of field: EmpyreanSessionDiff::update_norm_current"]
[::std::mem::offset_of!(EmpyreanSessionDiff, update_norm_current) - 24usize];
["Offset of field: EmpyreanSessionDiff::update_norm_prior"]
[::std::mem::offset_of!(EmpyreanSessionDiff, update_norm_prior) - 32usize];
};
#[doc = " A single body state for the C API."]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct EmpyreanState {
#[doc = " Epoch as MJD TDB."]
pub epoch_mjd_tdb: f64,
#[doc = " Position (AU)."]
pub x: f64,
pub y: f64,
pub z: f64,
#[doc = " Velocity (AU/day)."]
pub vx: f64,
pub vy: f64,
pub vz: f64,
#[doc = " Reference frame (EMPYREAN_FRAME_*)."]
pub frame: i32,
#[doc = " Center body NAIF ID."]
pub origin: i32,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanState"][::std::mem::size_of::<EmpyreanState>() - 64usize];
["Alignment of EmpyreanState"][::std::mem::align_of::<EmpyreanState>() - 8usize];
["Offset of field: EmpyreanState::epoch_mjd_tdb"]
[::std::mem::offset_of!(EmpyreanState, epoch_mjd_tdb) - 0usize];
["Offset of field: EmpyreanState::x"][::std::mem::offset_of!(EmpyreanState, x) - 8usize];
["Offset of field: EmpyreanState::y"][::std::mem::offset_of!(EmpyreanState, y) - 16usize];
["Offset of field: EmpyreanState::z"][::std::mem::offset_of!(EmpyreanState, z) - 24usize];
["Offset of field: EmpyreanState::vx"][::std::mem::offset_of!(EmpyreanState, vx) - 32usize];
["Offset of field: EmpyreanState::vy"][::std::mem::offset_of!(EmpyreanState, vy) - 40usize];
["Offset of field: EmpyreanState::vz"][::std::mem::offset_of!(EmpyreanState, vz) - 48usize];
["Offset of field: EmpyreanState::frame"]
[::std::mem::offset_of!(EmpyreanState, frame) - 56usize];
["Offset of field: EmpyreanState::origin"]
[::std::mem::offset_of!(EmpyreanState, origin) - 60usize];
};
#[doc = " Result containing an array of body states."]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EmpyreanStateResult {
pub states: *mut EmpyreanState,
pub num_states: usize,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of EmpyreanStateResult"][::std::mem::size_of::<EmpyreanStateResult>() - 16usize];
["Alignment of EmpyreanStateResult"][::std::mem::align_of::<EmpyreanStateResult>() - 8usize];
["Offset of field: EmpyreanStateResult::states"]
[::std::mem::offset_of!(EmpyreanStateResult, states) - 0usize];
["Offset of field: EmpyreanStateResult::num_states"]
[::std::mem::offset_of!(EmpyreanStateResult, num_states) - 8usize];
};
impl Default for EmpyreanStateResult {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
pub struct EmpyreanLib {
__library: ::libloading::Library,
pub empyrean_last_error: unsafe extern "C" fn() -> *const ::std::os::raw::c_char,
pub empyrean_context_new_minimal: unsafe extern "C" fn(
de440_path: *const ::std::os::raw::c_char,
gm_path: *const ::std::os::raw::c_char,
) -> *mut EmpyreanContext,
pub empyrean_context_with_spk: unsafe extern "C" fn(
ctx: *mut EmpyreanContext,
spk_path: *const ::std::os::raw::c_char,
) -> i32,
pub empyrean_context_from_data_dir:
unsafe extern "C" fn(data_dir: *const ::std::os::raw::c_char) -> *mut EmpyreanContext,
pub empyrean_context_free: unsafe extern "C" fn(ctx: *mut EmpyreanContext),
pub empyrean_default_data_dir: unsafe extern "C" fn() -> *mut ::std::os::raw::c_char,
pub empyrean_string_free: unsafe extern "C" fn(s: *mut ::std::os::raw::c_char),
pub empyrean_version_string: unsafe extern "C" fn() -> *mut ::std::os::raw::c_char,
pub empyrean_versions: unsafe extern "C" fn(out: *mut EmpyreanVersions) -> i32,
pub empyrean_versions_free: unsafe extern "C" fn(versions: *mut EmpyreanVersions),
pub empyrean_builtsystem_new: unsafe extern "C" fn(
ctx: *const EmpyreanContext,
force_model: i32,
frame: i32,
encounter_timescale_divisor: f64,
out: *mut *mut EmpyreanBuiltSystem,
) -> i32,
pub empyrean_builtsystem_free: unsafe extern "C" fn(handle: *mut EmpyreanBuiltSystem),
pub empyrean_builtsystem_propagate: unsafe extern "C" fn(
handle: *const EmpyreanBuiltSystem,
ctx: *const EmpyreanContext,
orbits_ptr: *const EmpyreanOrbit,
num_orbits: usize,
times_ptr: *const f64,
num_times: usize,
config: *const EmpyreanPropagationConfig,
result_out: *mut EmpyreanPropagationResult,
) -> i32,
pub empyrean_builtsystem_generate_ephemeris: unsafe extern "C" fn(
handle: *const EmpyreanBuiltSystem,
ctx: *const EmpyreanContext,
orbits_ptr: *const EmpyreanOrbit,
num_orbits: usize,
observers_ptr: *const EmpyreanObserver,
num_observers: usize,
config: *const EmpyreanEphemerisConfig,
result_out: *mut EmpyreanEphemerisResult,
) -> i32,
pub empyrean_builtsystem_describe: unsafe extern "C" fn(
handle: *const EmpyreanBuiltSystem,
out: *mut EmpyreanSystemDescription,
) -> i32,
pub empyrean_builtsystem_description_free:
unsafe extern "C" fn(desc: *mut EmpyreanSystemDescription),
pub empyrean_generate_ephemeris: unsafe extern "C" fn(
ctx: *const EmpyreanContext,
orbits_ptr: *const EmpyreanOrbit,
num_orbits: usize,
observers_ptr: *const EmpyreanObserver,
num_observers: usize,
config: *const EmpyreanEphemerisConfig,
result_out: *mut EmpyreanEphemerisResult,
) -> i32,
pub empyrean_ephemeris_result_free: unsafe extern "C" fn(result: *mut EmpyreanEphemerisResult),
pub empyrean_compute_impact_probabilities: unsafe extern "C" fn(
ctx: *const EmpyreanContext,
orbits_ptr: *const EmpyreanOrbit,
num_orbits: usize,
end_mjd_tdb: f64,
methods_ptr: *const EmpyreanUncertaintyMethod,
num_methods: usize,
body_filter_naif: *const i32,
num_body_filter: usize,
result_out: *mut EmpyreanImpactProbabilitiesResult,
) -> i32,
pub empyrean_compute_impact_probabilities_result_free:
unsafe extern "C" fn(result: *mut EmpyreanImpactProbabilitiesResult),
pub empyrean_compute_b_planes: unsafe extern "C" fn(
ctx: *const EmpyreanContext,
orbits_ptr: *const EmpyreanOrbit,
num_orbits: usize,
end_mjd_tdb: f64,
methods_ptr: *const EmpyreanUncertaintyMethod,
num_methods: usize,
body_filter_naif: *const i32,
num_body_filter: usize,
result_out: *mut EmpyreanBPlanesResult,
) -> i32,
pub empyrean_compute_b_planes_result_free:
unsafe extern "C" fn(result: *mut EmpyreanBPlanesResult),
pub empyrean_orbits_batch_free: unsafe extern "C" fn(batch: *mut EmpyreanOrbitBatch),
pub empyrean_orbits_read_parquet: unsafe extern "C" fn(
path: *const ::std::os::raw::c_char,
out: *mut EmpyreanOrbitBatch,
) -> i32,
pub empyrean_orbits_write_parquet: unsafe extern "C" fn(
path: *const ::std::os::raw::c_char,
batch: *const EmpyreanOrbitBatch,
) -> i32,
pub empyrean_orbits_read_json: unsafe extern "C" fn(
path: *const ::std::os::raw::c_char,
out: *mut EmpyreanOrbitBatch,
) -> i32,
pub empyrean_orbits_write_json: unsafe extern "C" fn(
path: *const ::std::os::raw::c_char,
batch: *const EmpyreanOrbitBatch,
) -> i32,
pub empyrean_orbits_read_csv: unsafe extern "C" fn(
path: *const ::std::os::raw::c_char,
out: *mut EmpyreanOrbitBatch,
) -> i32,
pub empyrean_orbits_write_csv: unsafe extern "C" fn(
path: *const ::std::os::raw::c_char,
batch: *const EmpyreanOrbitBatch,
) -> i32,
pub empyrean_ephemeris_write_parquet: unsafe extern "C" fn(
path: *const ::std::os::raw::c_char,
entries_ptr: *const EmpyreanEphemerisEntry,
num_entries: usize,
) -> i32,
pub empyrean_ephemeris_write_json: unsafe extern "C" fn(
path: *const ::std::os::raw::c_char,
entries_ptr: *const EmpyreanEphemerisEntry,
num_entries: usize,
) -> i32,
pub empyrean_ephemeris_write_csv: unsafe extern "C" fn(
path: *const ::std::os::raw::c_char,
entries_ptr: *const EmpyreanEphemerisEntry,
num_entries: usize,
) -> i32,
pub empyrean_events_write_parquet: unsafe extern "C" fn(
path: *const ::std::os::raw::c_char,
events_ptr: *const EmpyreanEvent,
num_events: usize,
) -> i32,
pub empyrean_events_write_json: unsafe extern "C" fn(
path: *const ::std::os::raw::c_char,
events_ptr: *const EmpyreanEvent,
num_events: usize,
) -> i32,
pub empyrean_events_write_csv: unsafe extern "C" fn(
path: *const ::std::os::raw::c_char,
events_ptr: *const EmpyreanEvent,
num_events: usize,
) -> i32,
pub empyrean_residuals_write_parquet: unsafe extern "C" fn(
path: *const ::std::os::raw::c_char,
obs_ptr: *const EmpyreanObservationResult,
num_obs: usize,
) -> i32,
pub empyrean_residuals_write_json: unsafe extern "C" fn(
path: *const ::std::os::raw::c_char,
obs_ptr: *const EmpyreanObservationResult,
num_obs: usize,
) -> i32,
pub empyrean_residuals_write_csv: unsafe extern "C" fn(
path: *const ::std::os::raw::c_char,
obs_ptr: *const EmpyreanObservationResult,
num_obs: usize,
) -> i32,
pub empyrean_eigenvector_max_6x6: unsafe extern "C" fn(
matrix: *const [[f64; 6usize]; 6usize],
eigenvalue_out: *mut f64,
eigenvector_out: *mut [f64; 6usize],
) -> i32,
pub empyrean_split_gaussian: unsafe extern "C" fn(
mean: *const [f64; 6usize],
covariance: *const [[f64; 6usize]; 6usize],
k: usize,
weights_out: *mut f64,
means_out: *mut [f64; 6usize],
covariances_out: *mut [[f64; 6usize]; 6usize],
) -> i32,
pub empyrean_get_observers: unsafe extern "C" fn(
ctx: *const EmpyreanContext,
obs_codes: *const *const ::std::os::raw::c_char,
num_codes: usize,
epochs_mjd_tdb: *const f64,
num_epochs: usize,
result_out: *mut EmpyreanObserverResult,
) -> i32,
pub empyrean_observer_result_free: unsafe extern "C" fn(result: *mut EmpyreanObserverResult),
pub empyrean_read_ades: unsafe extern "C" fn(
content: *const ::std::os::raw::c_char,
observations_out: *mut *mut EmpyreanObservation,
num_observations_out: *mut usize,
radar_out: *mut *mut EmpyreanRadarObservation,
num_radar_out: *mut usize,
) -> i32,
pub empyrean_observations_from_array: unsafe extern "C" fn(
input: *const EmpyreanObservation,
num: usize,
out_ptr: *mut *mut EmpyreanObservation,
out_num: *mut usize,
) -> i32,
pub empyrean_observations_free:
unsafe extern "C" fn(observations: *mut EmpyreanObservation, num: usize),
pub empyrean_radar_observations_from_array: unsafe extern "C" fn(
input: *const EmpyreanRadarObservation,
num: usize,
out_ptr: *mut *mut EmpyreanRadarObservation,
out_num: *mut usize,
) -> i32,
pub empyrean_radar_observations_free:
unsafe extern "C" fn(observations: *mut EmpyreanRadarObservation, num: usize),
pub empyrean_determine: unsafe extern "C" fn(
ctx: *const EmpyreanContext,
observations: *const EmpyreanObservation,
num_observations: usize,
radar: *const EmpyreanRadarObservation,
num_radar: usize,
initial_orbits: *const EmpyreanOrbit,
num_initial_orbits: usize,
config: *const EmpyreanODConfig,
result_out: *mut EmpyreanODResult,
) -> i32,
pub empyrean_od_result_free: unsafe extern "C" fn(result: *mut EmpyreanODResult),
pub empyrean_evaluate: unsafe extern "C" fn(
ctx: *const EmpyreanContext,
orbit: *const EmpyreanOrbit,
observations: *const EmpyreanObservation,
num_observations: usize,
config: *const EmpyreanODConfig,
result_out: *mut EmpyreanEvaluateResult,
) -> i32,
pub empyrean_evaluate_result_free: unsafe extern "C" fn(result: *mut EmpyreanEvaluateResult),
pub empyrean_refine: unsafe extern "C" fn(
ctx: *const EmpyreanContext,
orbit: *const EmpyreanOrbit,
observations: *const EmpyreanObservation,
num_observations: usize,
config: *const EmpyreanODConfig,
result_out: *mut EmpyreanODResult,
) -> i32,
pub empyrean_evaluate_plan: unsafe extern "C" fn(
ctx: *const EmpyreanContext,
orbit: *const EmpyreanOrbit,
orbit_id: *const ::std::os::raw::c_char,
planned: *const EmpyreanPlannedObservation,
num_planned: usize,
config: *const EmpyreanPlanningConfig,
result_out: *mut EmpyreanPlanResult,
) -> i32,
pub empyrean_plan_result_free: unsafe extern "C" fn(result: *mut EmpyreanPlanResult),
pub empyrean_propagate: unsafe extern "C" fn(
ctx: *const EmpyreanContext,
orbits_ptr: *const EmpyreanOrbit,
num_orbits: usize,
times_ptr: *const f64,
num_times: usize,
config: *const EmpyreanPropagationConfig,
result_out: *mut EmpyreanPropagationResult,
) -> i32,
pub empyrean_propagation_result_free:
unsafe extern "C" fn(result: *mut EmpyreanPropagationResult),
pub empyrean_propagation_covariance_series_cartesian: unsafe extern "C" fn(
result: *const EmpyreanPropagationResult,
orbit_index: usize,
out_series: *mut *mut EmpyreanTaggedCovarianceSeries,
) -> i32,
pub empyrean_propagation_covariance_at_cartesian: unsafe extern "C" fn(
result: *const EmpyreanPropagationResult,
orbit_index: usize,
epoch_index: usize,
out: *mut EmpyreanTaggedCovariance,
) -> i32,
pub empyrean_tagged_covariance_series_free:
unsafe extern "C" fn(series: *mut EmpyreanTaggedCovarianceSeries),
pub empyrean_query_sbdb: unsafe extern "C" fn(
object_ids: *const *const ::std::os::raw::c_char,
num_object_ids: usize,
cache_dir: *const ::std::os::raw::c_char,
out: *mut EmpyreanOrbitBatch,
) -> i32,
pub empyrean_query_horizons: unsafe extern "C" fn(
object_ids: *const *const ::std::os::raw::c_char,
num_object_ids: usize,
obs_code: *const ::std::os::raw::c_char,
times_mjd_tdb: *const f64,
num_times: usize,
cache_dir: *const ::std::os::raw::c_char,
out: *mut EmpyreanEphemerisResult,
) -> i32,
pub empyrean_query_horizons_vectors: unsafe extern "C" fn(
command: *const ::std::os::raw::c_char,
epoch_mjd_tdb: f64,
cache_dir: *const ::std::os::raw::c_char,
out_pos: *mut f64,
out_vel: *mut f64,
) -> i32,
pub empyrean_query_observations: unsafe extern "C" fn(
designations: *const *const ::std::os::raw::c_char,
num_designations: usize,
cache_dir: *const ::std::os::raw::c_char,
out_ptr: *mut *mut EmpyreanObservation,
out_num: *mut usize,
) -> i32,
pub empyrean_query_radar: unsafe extern "C" fn(
designations: *const *const ::std::os::raw::c_char,
num_designations: usize,
cache_dir: *const ::std::os::raw::c_char,
out_ptr: *mut *mut EmpyreanRadarObservation,
out_num: *mut usize,
) -> i32,
pub empyrean_session_new: unsafe extern "C" fn(
observations: *const EmpyreanObservation,
num_observations: usize,
config: *const EmpyreanODConfig,
) -> *mut EmpyreanSession,
pub empyrean_session_free: unsafe extern "C" fn(session: *mut EmpyreanSession),
pub empyrean_session_n_observations:
unsafe extern "C" fn(session: *const EmpyreanSession) -> usize,
pub empyrean_session_n_masked: unsafe extern "C" fn(session: *const EmpyreanSession) -> usize,
pub empyrean_session_n_active: unsafe extern "C" fn(session: *const EmpyreanSession) -> usize,
pub empyrean_session_mask:
unsafe extern "C" fn(session: *mut EmpyreanSession, idx: usize) -> i32,
pub empyrean_session_unmask:
unsafe extern "C" fn(session: *mut EmpyreanSession, idx: usize) -> i32,
pub empyrean_session_unmask_all: unsafe extern "C" fn(session: *mut EmpyreanSession) -> i32,
pub empyrean_session_is_masked:
unsafe extern "C" fn(session: *const EmpyreanSession, idx: usize) -> u8,
pub empyrean_session_refine: unsafe extern "C" fn(
session: *mut EmpyreanSession,
ctx: *const EmpyreanContext,
result_out: *mut EmpyreanODResult,
) -> i32,
pub empyrean_session_history_len:
unsafe extern "C" fn(session: *const EmpyreanSession) -> usize,
pub empyrean_session_get_history: unsafe extern "C" fn(
session: *const EmpyreanSession,
idx: usize,
result_out: *mut EmpyreanODResult,
) -> i32,
pub empyrean_session_diff: unsafe extern "C" fn(
session: *const EmpyreanSession,
prior_idx: usize,
diff_out: *mut EmpyreanSessionDiff,
) -> i32,
pub empyrean_get_states: unsafe extern "C" fn(
ctx: *const EmpyreanContext,
target_naif_id: i32,
center_naif_id: i32,
epochs_mjd_tdb: *const f64,
num_epochs: usize,
frame: i32,
result_out: *mut EmpyreanStateResult,
) -> i32,
pub empyrean_state_result_free: unsafe extern "C" fn(result: *mut EmpyreanStateResult),
pub empyrean_iso_to_mjd: unsafe extern "C" fn(
iso: *const ::std::os::raw::c_char,
scale: i32,
out_mjd: *mut f64,
) -> i32,
pub empyrean_mjd_to_iso: unsafe extern "C" fn(
mjd: f64,
scale: i32,
out_buf: *mut ::std::os::raw::c_char,
buf_len: usize,
) -> i32,
pub empyrean_transform_coordinates: unsafe extern "C" fn(
ctx: *const EmpyreanContext,
input: *const CoordinateState,
target_representation: i32,
target_frame: i32,
target_origin: i32,
output: *mut CoordinateState,
) -> i32,
}
impl EmpyreanLib {
pub unsafe fn new<P>(path: P) -> Result<Self, ::libloading::Error>
where
P: AsRef<::std::ffi::OsStr>,
{
let library = ::libloading::Library::new(path)?;
Self::from_library(library)
}
pub unsafe fn from_library<L>(library: L) -> Result<Self, ::libloading::Error>
where
L: Into<::libloading::Library>,
{
let __library = library.into();
let empyrean_last_error = __library.get(b"empyrean_last_error\0").map(|sym| *sym)?;
let empyrean_context_new_minimal = __library
.get(b"empyrean_context_new_minimal\0")
.map(|sym| *sym)?;
let empyrean_context_with_spk = __library
.get(b"empyrean_context_with_spk\0")
.map(|sym| *sym)?;
let empyrean_context_from_data_dir = __library
.get(b"empyrean_context_from_data_dir\0")
.map(|sym| *sym)?;
let empyrean_context_free = __library.get(b"empyrean_context_free\0").map(|sym| *sym)?;
let empyrean_default_data_dir = __library
.get(b"empyrean_default_data_dir\0")
.map(|sym| *sym)?;
let empyrean_string_free = __library.get(b"empyrean_string_free\0").map(|sym| *sym)?;
let empyrean_version_string = __library
.get(b"empyrean_version_string\0")
.map(|sym| *sym)?;
let empyrean_versions = __library.get(b"empyrean_versions\0").map(|sym| *sym)?;
let empyrean_versions_free = __library.get(b"empyrean_versions_free\0").map(|sym| *sym)?;
let empyrean_builtsystem_new = __library
.get(b"empyrean_builtsystem_new\0")
.map(|sym| *sym)?;
let empyrean_builtsystem_free = __library
.get(b"empyrean_builtsystem_free\0")
.map(|sym| *sym)?;
let empyrean_builtsystem_propagate = __library
.get(b"empyrean_builtsystem_propagate\0")
.map(|sym| *sym)?;
let empyrean_builtsystem_generate_ephemeris = __library
.get(b"empyrean_builtsystem_generate_ephemeris\0")
.map(|sym| *sym)?;
let empyrean_builtsystem_describe = __library
.get(b"empyrean_builtsystem_describe\0")
.map(|sym| *sym)?;
let empyrean_builtsystem_description_free = __library
.get(b"empyrean_builtsystem_description_free\0")
.map(|sym| *sym)?;
let empyrean_generate_ephemeris = __library
.get(b"empyrean_generate_ephemeris\0")
.map(|sym| *sym)?;
let empyrean_ephemeris_result_free = __library
.get(b"empyrean_ephemeris_result_free\0")
.map(|sym| *sym)?;
let empyrean_compute_impact_probabilities = __library
.get(b"empyrean_compute_impact_probabilities\0")
.map(|sym| *sym)?;
let empyrean_compute_impact_probabilities_result_free = __library
.get(b"empyrean_compute_impact_probabilities_result_free\0")
.map(|sym| *sym)?;
let empyrean_compute_b_planes = __library
.get(b"empyrean_compute_b_planes\0")
.map(|sym| *sym)?;
let empyrean_compute_b_planes_result_free = __library
.get(b"empyrean_compute_b_planes_result_free\0")
.map(|sym| *sym)?;
let empyrean_orbits_batch_free = __library
.get(b"empyrean_orbits_batch_free\0")
.map(|sym| *sym)?;
let empyrean_orbits_read_parquet = __library
.get(b"empyrean_orbits_read_parquet\0")
.map(|sym| *sym)?;
let empyrean_orbits_write_parquet = __library
.get(b"empyrean_orbits_write_parquet\0")
.map(|sym| *sym)?;
let empyrean_orbits_read_json = __library
.get(b"empyrean_orbits_read_json\0")
.map(|sym| *sym)?;
let empyrean_orbits_write_json = __library
.get(b"empyrean_orbits_write_json\0")
.map(|sym| *sym)?;
let empyrean_orbits_read_csv = __library
.get(b"empyrean_orbits_read_csv\0")
.map(|sym| *sym)?;
let empyrean_orbits_write_csv = __library
.get(b"empyrean_orbits_write_csv\0")
.map(|sym| *sym)?;
let empyrean_ephemeris_write_parquet = __library
.get(b"empyrean_ephemeris_write_parquet\0")
.map(|sym| *sym)?;
let empyrean_ephemeris_write_json = __library
.get(b"empyrean_ephemeris_write_json\0")
.map(|sym| *sym)?;
let empyrean_ephemeris_write_csv = __library
.get(b"empyrean_ephemeris_write_csv\0")
.map(|sym| *sym)?;
let empyrean_events_write_parquet = __library
.get(b"empyrean_events_write_parquet\0")
.map(|sym| *sym)?;
let empyrean_events_write_json = __library
.get(b"empyrean_events_write_json\0")
.map(|sym| *sym)?;
let empyrean_events_write_csv = __library
.get(b"empyrean_events_write_csv\0")
.map(|sym| *sym)?;
let empyrean_residuals_write_parquet = __library
.get(b"empyrean_residuals_write_parquet\0")
.map(|sym| *sym)?;
let empyrean_residuals_write_json = __library
.get(b"empyrean_residuals_write_json\0")
.map(|sym| *sym)?;
let empyrean_residuals_write_csv = __library
.get(b"empyrean_residuals_write_csv\0")
.map(|sym| *sym)?;
let empyrean_eigenvector_max_6x6 = __library
.get(b"empyrean_eigenvector_max_6x6\0")
.map(|sym| *sym)?;
let empyrean_split_gaussian = __library
.get(b"empyrean_split_gaussian\0")
.map(|sym| *sym)?;
let empyrean_get_observers = __library.get(b"empyrean_get_observers\0").map(|sym| *sym)?;
let empyrean_observer_result_free = __library
.get(b"empyrean_observer_result_free\0")
.map(|sym| *sym)?;
let empyrean_read_ades = __library.get(b"empyrean_read_ades\0").map(|sym| *sym)?;
let empyrean_observations_from_array = __library
.get(b"empyrean_observations_from_array\0")
.map(|sym| *sym)?;
let empyrean_observations_free = __library
.get(b"empyrean_observations_free\0")
.map(|sym| *sym)?;
let empyrean_radar_observations_from_array = __library
.get(b"empyrean_radar_observations_from_array\0")
.map(|sym| *sym)?;
let empyrean_radar_observations_free = __library
.get(b"empyrean_radar_observations_free\0")
.map(|sym| *sym)?;
let empyrean_determine = __library.get(b"empyrean_determine\0").map(|sym| *sym)?;
let empyrean_od_result_free = __library
.get(b"empyrean_od_result_free\0")
.map(|sym| *sym)?;
let empyrean_evaluate = __library.get(b"empyrean_evaluate\0").map(|sym| *sym)?;
let empyrean_evaluate_result_free = __library
.get(b"empyrean_evaluate_result_free\0")
.map(|sym| *sym)?;
let empyrean_refine = __library.get(b"empyrean_refine\0").map(|sym| *sym)?;
let empyrean_evaluate_plan = __library.get(b"empyrean_evaluate_plan\0").map(|sym| *sym)?;
let empyrean_plan_result_free = __library
.get(b"empyrean_plan_result_free\0")
.map(|sym| *sym)?;
let empyrean_propagate = __library.get(b"empyrean_propagate\0").map(|sym| *sym)?;
let empyrean_propagation_result_free = __library
.get(b"empyrean_propagation_result_free\0")
.map(|sym| *sym)?;
let empyrean_propagation_covariance_series_cartesian = __library
.get(b"empyrean_propagation_covariance_series_cartesian\0")
.map(|sym| *sym)?;
let empyrean_propagation_covariance_at_cartesian = __library
.get(b"empyrean_propagation_covariance_at_cartesian\0")
.map(|sym| *sym)?;
let empyrean_tagged_covariance_series_free = __library
.get(b"empyrean_tagged_covariance_series_free\0")
.map(|sym| *sym)?;
let empyrean_query_sbdb = __library.get(b"empyrean_query_sbdb\0").map(|sym| *sym)?;
let empyrean_query_horizons = __library
.get(b"empyrean_query_horizons\0")
.map(|sym| *sym)?;
let empyrean_query_horizons_vectors = __library
.get(b"empyrean_query_horizons_vectors\0")
.map(|sym| *sym)?;
let empyrean_query_observations = __library
.get(b"empyrean_query_observations\0")
.map(|sym| *sym)?;
let empyrean_query_radar = __library.get(b"empyrean_query_radar\0").map(|sym| *sym)?;
let empyrean_session_new = __library.get(b"empyrean_session_new\0").map(|sym| *sym)?;
let empyrean_session_free = __library.get(b"empyrean_session_free\0").map(|sym| *sym)?;
let empyrean_session_n_observations = __library
.get(b"empyrean_session_n_observations\0")
.map(|sym| *sym)?;
let empyrean_session_n_masked = __library
.get(b"empyrean_session_n_masked\0")
.map(|sym| *sym)?;
let empyrean_session_n_active = __library
.get(b"empyrean_session_n_active\0")
.map(|sym| *sym)?;
let empyrean_session_mask = __library.get(b"empyrean_session_mask\0").map(|sym| *sym)?;
let empyrean_session_unmask = __library
.get(b"empyrean_session_unmask\0")
.map(|sym| *sym)?;
let empyrean_session_unmask_all = __library
.get(b"empyrean_session_unmask_all\0")
.map(|sym| *sym)?;
let empyrean_session_is_masked = __library
.get(b"empyrean_session_is_masked\0")
.map(|sym| *sym)?;
let empyrean_session_refine = __library
.get(b"empyrean_session_refine\0")
.map(|sym| *sym)?;
let empyrean_session_history_len = __library
.get(b"empyrean_session_history_len\0")
.map(|sym| *sym)?;
let empyrean_session_get_history = __library
.get(b"empyrean_session_get_history\0")
.map(|sym| *sym)?;
let empyrean_session_diff = __library.get(b"empyrean_session_diff\0").map(|sym| *sym)?;
let empyrean_get_states = __library.get(b"empyrean_get_states\0").map(|sym| *sym)?;
let empyrean_state_result_free = __library
.get(b"empyrean_state_result_free\0")
.map(|sym| *sym)?;
let empyrean_iso_to_mjd = __library.get(b"empyrean_iso_to_mjd\0").map(|sym| *sym)?;
let empyrean_mjd_to_iso = __library.get(b"empyrean_mjd_to_iso\0").map(|sym| *sym)?;
let empyrean_transform_coordinates = __library
.get(b"empyrean_transform_coordinates\0")
.map(|sym| *sym)?;
Ok(EmpyreanLib {
__library,
empyrean_last_error,
empyrean_context_new_minimal,
empyrean_context_with_spk,
empyrean_context_from_data_dir,
empyrean_context_free,
empyrean_default_data_dir,
empyrean_string_free,
empyrean_version_string,
empyrean_versions,
empyrean_versions_free,
empyrean_builtsystem_new,
empyrean_builtsystem_free,
empyrean_builtsystem_propagate,
empyrean_builtsystem_generate_ephemeris,
empyrean_builtsystem_describe,
empyrean_builtsystem_description_free,
empyrean_generate_ephemeris,
empyrean_ephemeris_result_free,
empyrean_compute_impact_probabilities,
empyrean_compute_impact_probabilities_result_free,
empyrean_compute_b_planes,
empyrean_compute_b_planes_result_free,
empyrean_orbits_batch_free,
empyrean_orbits_read_parquet,
empyrean_orbits_write_parquet,
empyrean_orbits_read_json,
empyrean_orbits_write_json,
empyrean_orbits_read_csv,
empyrean_orbits_write_csv,
empyrean_ephemeris_write_parquet,
empyrean_ephemeris_write_json,
empyrean_ephemeris_write_csv,
empyrean_events_write_parquet,
empyrean_events_write_json,
empyrean_events_write_csv,
empyrean_residuals_write_parquet,
empyrean_residuals_write_json,
empyrean_residuals_write_csv,
empyrean_eigenvector_max_6x6,
empyrean_split_gaussian,
empyrean_get_observers,
empyrean_observer_result_free,
empyrean_read_ades,
empyrean_observations_from_array,
empyrean_observations_free,
empyrean_radar_observations_from_array,
empyrean_radar_observations_free,
empyrean_determine,
empyrean_od_result_free,
empyrean_evaluate,
empyrean_evaluate_result_free,
empyrean_refine,
empyrean_evaluate_plan,
empyrean_plan_result_free,
empyrean_propagate,
empyrean_propagation_result_free,
empyrean_propagation_covariance_series_cartesian,
empyrean_propagation_covariance_at_cartesian,
empyrean_tagged_covariance_series_free,
empyrean_query_sbdb,
empyrean_query_horizons,
empyrean_query_horizons_vectors,
empyrean_query_observations,
empyrean_query_radar,
empyrean_session_new,
empyrean_session_free,
empyrean_session_n_observations,
empyrean_session_n_masked,
empyrean_session_n_active,
empyrean_session_mask,
empyrean_session_unmask,
empyrean_session_unmask_all,
empyrean_session_is_masked,
empyrean_session_refine,
empyrean_session_history_len,
empyrean_session_get_history,
empyrean_session_diff,
empyrean_get_states,
empyrean_state_result_free,
empyrean_iso_to_mjd,
empyrean_mjd_to_iso,
empyrean_transform_coordinates,
})
}
#[doc = " Return a pointer to the last error message (thread-local, null-terminated).\n\n The pointer is valid until the next call that sets an error on the same\n thread."]
pub unsafe fn empyrean_last_error(&self) -> *const ::std::os::raw::c_char {
(self.empyrean_last_error)()
}
#[doc = " Create a **minimal** `EmpyreanContext` from a DE440 SPK file and a\n GM TPC file.\n\n Loads ONLY the planetary ephemeris and gravitational parameters —\n no Earth/Moon BPC kernels, no SB441-N16 asteroid perturbers, no\n MPC observatory codes, no Earth gravity field. This is sufficient\n for coordinate transforms and basic propagation under the\n `Approximate` force model, but is **not** enough for production\n orbit propagation, orbit determination, or topocentric ephemeris\n generation. Most callers should use\n [`empyrean_context_from_data_dir`] instead, which loads the full\n Standard-tier kernel set (downloading any missing files).\n\n Use [`empyrean_context_with_spk`] to chain additional SPK kernels\n (e.g. SB441-N16) onto a context built by this function.\n\n Returns a heap-allocated pointer on success, or null on error.\n Call `empyrean_last_error()` to retrieve the error message when null is\n returned. The caller owns the returned pointer and must free it with\n `empyrean_context_free()`."]
pub unsafe fn empyrean_context_new_minimal(
&self,
de440_path: *const ::std::os::raw::c_char,
gm_path: *const ::std::os::raw::c_char,
) -> *mut EmpyreanContext {
(self.empyrean_context_new_minimal)(de440_path, gm_path)
}
#[doc = " Load an additional SPK kernel into an existing context, in place.\n\n Useful for layering SB441-N16 asteroid perturbers or spacecraft\n SPK kernels (JWST, Gaia, custom probes) on top of a context built\n by [`empyrean_context_new_minimal`] or [`empyrean_context_from_data_dir`].\n The merged context picks up the new kernel's body coverage on top\n of what was already loaded.\n\n Returns 0 on success; negative error code on failure. The context\n pointer remains valid and unchanged when this function returns\n non-zero — failure does not invalidate `ctx`."]
pub unsafe fn empyrean_context_with_spk(
&self,
ctx: *mut EmpyreanContext,
spk_path: *const ::std::os::raw::c_char,
) -> i32 {
(self.empyrean_context_with_spk)(ctx, spk_path)
}
#[doc = " Create a new `EmpyreanContext` from a data directory.\n\n Loads the full Standard-tier kernel set (DE440, SB441-N16, Earth/Moon\n BPCs, GM, MPC observatory codes) from `data_dir`, downloading any\n missing files. Pass null for `data_dir` to use the platform XDG\n data directory (`~/.empyrean/data` on Linux/macOS).\n\n Returns a heap-allocated pointer on success, or null on error.\n Call `empyrean_last_error()` to retrieve the error message when null is\n returned. The caller owns the returned pointer and must free it with\n `empyrean_context_free()`."]
pub unsafe fn empyrean_context_from_data_dir(
&self,
data_dir: *const ::std::os::raw::c_char,
) -> *mut EmpyreanContext {
(self.empyrean_context_from_data_dir)(data_dir)
}
#[doc = " Free an `EmpyreanContext` previously returned by `empyrean_context_new()`.\n\n Passing null is a no-op."]
pub unsafe fn empyrean_context_free(&self, ctx: *mut EmpyreanContext) {
(self.empyrean_context_free)(ctx)
}
#[doc = " Return the platform XDG-compliant default data directory as a\n heap-allocated, NUL-terminated UTF-8 string.\n\n Mirrors villeneuve's [`DataManager::new`] resolution: honors\n `EMPYREAN_DATA_DIR` first, then falls back to `dirs::data_dir()` —\n `~/.local/share/empyrean/data/` on Linux, `~/Library/Application\n Support/empyrean/data/` on macOS, `%APPDATA%\\empyrean\\data\\` on\n Windows. Cheap (no filesystem I/O).\n\n Returns null on failure (non-UTF-8 path, NUL byte in path, panic).\n Call `empyrean_last_error()` for details.\n\n **The caller owns the returned pointer and must release it with\n [`empyrean_string_free`].**"]
pub unsafe fn empyrean_default_data_dir(&self) -> *mut ::std::os::raw::c_char {
(self.empyrean_default_data_dir)()
}
#[doc = " Free a string returned by an empyrean C API function (e.g.,\n [`empyrean_default_data_dir`], [`empyrean_version_string`]).\n\n Passing null is a no-op. Passing any pointer not obtained from an\n empyrean string-returning function is undefined behavior."]
pub unsafe fn empyrean_string_free(&self, s: *mut ::std::os::raw::c_char) {
(self.empyrean_string_free)(s)
}
#[doc = " Multi-line version report — `empyrean-core <ver>\\nvilleneuve <ver>\\n…`.\n\n Mirrors [`empyrean_core::version_string`]. Useful for `--version`-style\n output and for verifying the build provenance of a deployed cdylib.\n Returns null on allocation failure (extremely unlikely — the strings\n are short and `&'static` underneath); call `empyrean_last_error()` if\n it does.\n\n **The caller owns the returned pointer and must release it with\n [`empyrean_string_free`].**"]
pub unsafe fn empyrean_version_string(&self) -> *mut ::std::os::raw::c_char {
(self.empyrean_version_string)()
}
#[doc = " Populate `out` with the per-crate versions of the empyrean stack.\n\n Returns 0 on success, non-zero on failure (`empyrean_last_error()`\n has the details). On failure `out` is left zero-initialized — no\n allocation needs freeing.\n\n **The caller owns the strings inside `out` and must release the\n whole struct with [`empyrean_versions_free`] when done.**"]
pub unsafe fn empyrean_versions(&self, out: *mut EmpyreanVersions) -> i32 {
(self.empyrean_versions)(out)
}
#[doc = " Free the version strings inside `versions` (each was heap-allocated\n by a previous successful [`empyrean_versions`] call). After this\n returns, `versions` itself is zero-initialized — safe to drop on\n the caller's stack.\n\n Passing null is a no-op. Calling this twice on the same struct, or\n passing a struct that wasn't populated by [`empyrean_versions`], is\n undefined behavior."]
pub unsafe fn empyrean_versions_free(&self, versions: *mut EmpyreanVersions) {
(self.empyrean_versions_free)(versions)
}
#[doc = " Assemble a reusable force-model handle for `(force_model, frame)` from\n `ctx`, freezing `encounter_timescale_divisor` into its key.\n\n - `force_model`: tier code (0=Approximate, 1=Basic, 2=Standard).\n - `frame`: output/integration frame code (0=ICRF, 1=EclipticJ2000, 2=ITRF93).\n - `encounter_timescale_divisor`: pass `0.0` to freeze the engine default;\n any positive value freezes that divisor into the key *before* it is\n used to validate calls.\n - `out`: receives the heap-allocated handle on success.\n\n The handle snapshots `ctx`'s kernel manifest at construction so\n [`empyrean_builtsystem_describe`] is self-contained. After you load any\n additional kernel into `ctx`, rebuild the handle — a stale handle is\n rejected loudly by every forward-model call, never silently reused.\n\n Returns [`EMPYREAN_BUILTSYSTEM_OK`] on success; on error, `out` is left\n untouched and `empyrean_last_error()` carries the message. The caller\n owns the returned handle and must free it with\n [`empyrean_builtsystem_free`]."]
pub unsafe fn empyrean_builtsystem_new(
&self,
ctx: *const EmpyreanContext,
force_model: i32,
frame: i32,
encounter_timescale_divisor: f64,
out: *mut *mut EmpyreanBuiltSystem,
) -> i32 {
(self.empyrean_builtsystem_new)(ctx, force_model, frame, encounter_timescale_divisor, out)
}
#[doc = " Free a handle previously returned by [`empyrean_builtsystem_new`].\n Passing null is a no-op."]
pub unsafe fn empyrean_builtsystem_free(&self, handle: *mut EmpyreanBuiltSystem) {
(self.empyrean_builtsystem_free)(handle)
}
#[doc = " Propagate `orbits` to `times` through the pre-built handle.\n\n Signature parallels the one-shot\n [`empyrean_propagate`](crate::propagate::empyrean_propagate) but takes\n `(handle, ctx, ...)`. Before dispatch the identity guard runs: the handle\n must have been built from `ctx`'s ephemeris data\n ([`EMPYREAN_BUILTSYSTEM_DATA_MISMATCH`]); the config must match the frozen\n key ([`EMPYREAN_BUILTSYSTEM_KEY_MISMATCH_FRAME`] /\n `_FORCE_MODEL` / `_DIVISOR`); and the data must be unmutated since build\n ([`EMPYREAN_BUILTSYSTEM_STALE`]). On pass, the result is bit-identical to\n the one-shot with the same config.\n\n On success populates `result_out`; free it with\n [`empyrean_propagation_result_free`](crate::propagate::empyrean_propagation_result_free)."]
pub unsafe fn empyrean_builtsystem_propagate(
&self,
handle: *const EmpyreanBuiltSystem,
ctx: *const EmpyreanContext,
orbits_ptr: *const EmpyreanOrbit,
num_orbits: usize,
times_ptr: *const f64,
num_times: usize,
config: *const EmpyreanPropagationConfig,
result_out: *mut EmpyreanPropagationResult,
) -> i32 {
(self.empyrean_builtsystem_propagate)(
handle, ctx, orbits_ptr, num_orbits, times_ptr, num_times, config, result_out,
)
}
#[doc = " Generate predicted ephemeris for `orbits` and `observers` through the\n pre-built handle.\n\n Signature parallels the one-shot\n [`empyrean_generate_ephemeris`](crate::ephemeris::empyrean_generate_ephemeris)\n but takes `(handle, ctx, ...)`. Runs the same identity guard as\n [`empyrean_builtsystem_propagate`] before dispatch; on pass the result is\n bit-identical to the one-shot. Note the C-ABI ephemeris config carries no\n divisor knob, so a handle frozen at a non-default divisor is rejected here\n with [`EMPYREAN_BUILTSYSTEM_KEY_MISMATCH_DIVISOR`] rather than served under\n the wrong dynamics — build the handle with the default divisor for\n ephemeris reuse.\n\n On success populates `result_out`; free it with\n [`empyrean_ephemeris_result_free`](crate::ephemeris::empyrean_ephemeris_result_free)."]
pub unsafe fn empyrean_builtsystem_generate_ephemeris(
&self,
handle: *const EmpyreanBuiltSystem,
ctx: *const EmpyreanContext,
orbits_ptr: *const EmpyreanOrbit,
num_orbits: usize,
observers_ptr: *const EmpyreanObserver,
num_observers: usize,
config: *const EmpyreanEphemerisConfig,
result_out: *mut EmpyreanEphemerisResult,
) -> i32 {
(self.empyrean_builtsystem_generate_ephemeris)(
handle,
ctx,
orbits_ptr,
num_orbits,
observers_ptr,
num_observers,
config,
result_out,
)
}
#[doc = " Populate `out` with a full reproducibility summary of the handle's frozen\n force model and its captured kernel manifest.\n\n Every field is populated from the system description and the manifest\n snapshot — no field is left defaulted. Returns\n [`EMPYREAN_BUILTSYSTEM_OK`] on success. The caller owns the heap arrays\n inside `out` and must release them with\n [`empyrean_builtsystem_description_free`]."]
pub unsafe fn empyrean_builtsystem_describe(
&self,
handle: *const EmpyreanBuiltSystem,
out: *mut EmpyreanSystemDescription,
) -> i32 {
(self.empyrean_builtsystem_describe)(handle, out)
}
#[doc = " Free the heap arrays inside a description populated by\n [`empyrean_builtsystem_describe`] (the perturber-id array and the kernel\n records with their C strings). After this returns `desc` is\n zero-initialized — safe to drop on the caller's stack. Passing null is a\n no-op."]
pub unsafe fn empyrean_builtsystem_description_free(
&self,
desc: *mut EmpyreanSystemDescription,
) {
(self.empyrean_builtsystem_description_free)(desc)
}
#[doc = " Generate predicted ephemeris for orbits and observers.\n\n Returns 0 on success, negative error code on failure.\n On success, `result_out` is populated with ephemeris entries.\n The caller must free the result with `empyrean_ephemeris_result_free()`."]
pub unsafe fn empyrean_generate_ephemeris(
&self,
ctx: *const EmpyreanContext,
orbits_ptr: *const EmpyreanOrbit,
num_orbits: usize,
observers_ptr: *const EmpyreanObserver,
num_observers: usize,
config: *const EmpyreanEphemerisConfig,
result_out: *mut EmpyreanEphemerisResult,
) -> i32 {
(self.empyrean_generate_ephemeris)(
ctx,
orbits_ptr,
num_orbits,
observers_ptr,
num_observers,
config,
result_out,
)
}
#[doc = " Free an ephemeris result previously returned by `empyrean_generate_ephemeris()`."]
pub unsafe fn empyrean_ephemeris_result_free(&self, result: *mut EmpyreanEphemerisResult) {
(self.empyrean_ephemeris_result_free)(result)
}
#[doc = " Run [`empyrean_core::impact::compute_impact_probabilities`] over a\n caller-supplied set of [`UncertaintyMethod`] variants and return\n the flattened IP records tagged by method.\n\n Caller is responsible for freeing the result via\n [`empyrean_compute_impact_probabilities_result_free`].\n\n # Returns\n `0` on success, negative on failure (see [`crate::set_last_error`]).\n\n # Safety\n All non-null pointer arguments must point to valid arrays of the\n indicated length for the duration of the call. The output struct\n is allocated by the caller; pointer fields inside it are allocated\n here and owned by the result."]
pub unsafe fn empyrean_compute_impact_probabilities(
&self,
ctx: *const EmpyreanContext,
orbits_ptr: *const EmpyreanOrbit,
num_orbits: usize,
end_mjd_tdb: f64,
methods_ptr: *const EmpyreanUncertaintyMethod,
num_methods: usize,
body_filter_naif: *const i32,
num_body_filter: usize,
result_out: *mut EmpyreanImpactProbabilitiesResult,
) -> i32 {
(self.empyrean_compute_impact_probabilities)(
ctx,
orbits_ptr,
num_orbits,
end_mjd_tdb,
methods_ptr,
num_methods,
body_filter_naif,
num_body_filter,
result_out,
)
}
#[doc = " Free the records array allocated by\n [`empyrean_compute_impact_probabilities`]. After calling, the\n struct's `records` is reset to null and `num_records` to 0."]
pub unsafe fn empyrean_compute_impact_probabilities_result_free(
&self,
result: *mut EmpyreanImpactProbabilitiesResult,
) {
(self.empyrean_compute_impact_probabilities_result_free)(result)
}
#[doc = " Run [`empyrean_core::impact::compute_b_planes`] over a caller-\n supplied set of [`UncertaintyMethod`] variants and return the\n flattened B-plane records tagged by method.\n\n Caller is responsible for freeing the result via\n [`empyrean_compute_b_planes_result_free`].\n\n # Safety\n Same contract as\n [`empyrean_compute_impact_probabilities`]."]
pub unsafe fn empyrean_compute_b_planes(
&self,
ctx: *const EmpyreanContext,
orbits_ptr: *const EmpyreanOrbit,
num_orbits: usize,
end_mjd_tdb: f64,
methods_ptr: *const EmpyreanUncertaintyMethod,
num_methods: usize,
body_filter_naif: *const i32,
num_body_filter: usize,
result_out: *mut EmpyreanBPlanesResult,
) -> i32 {
(self.empyrean_compute_b_planes)(
ctx,
orbits_ptr,
num_orbits,
end_mjd_tdb,
methods_ptr,
num_methods,
body_filter_naif,
num_body_filter,
result_out,
)
}
#[doc = " Free the records array allocated by [`empyrean_compute_b_planes`]."]
pub unsafe fn empyrean_compute_b_planes_result_free(&self, result: *mut EmpyreanBPlanesResult) {
(self.empyrean_compute_b_planes_result_free)(result)
}
#[doc = " Free a batch previously returned by an `empyrean_orbits_read_*`\n function. Passing null is a no-op."]
pub unsafe fn empyrean_orbits_batch_free(&self, batch: *mut EmpyreanOrbitBatch) {
(self.empyrean_orbits_batch_free)(batch)
}
#[doc = " Read an orbits parquet file. Caller frees the result with\n [`empyrean_orbits_batch_free`]."]
pub unsafe fn empyrean_orbits_read_parquet(
&self,
path: *const ::std::os::raw::c_char,
out: *mut EmpyreanOrbitBatch,
) -> i32 {
(self.empyrean_orbits_read_parquet)(path, out)
}
#[doc = " Write an orbit batch to a parquet file."]
pub unsafe fn empyrean_orbits_write_parquet(
&self,
path: *const ::std::os::raw::c_char,
batch: *const EmpyreanOrbitBatch,
) -> i32 {
(self.empyrean_orbits_write_parquet)(path, batch)
}
#[doc = " Read an orbits JSON file (array of orbit-row objects). Caller frees\n with [`empyrean_orbits_batch_free`]."]
pub unsafe fn empyrean_orbits_read_json(
&self,
path: *const ::std::os::raw::c_char,
out: *mut EmpyreanOrbitBatch,
) -> i32 {
(self.empyrean_orbits_read_json)(path, out)
}
#[doc = " Write an orbit batch to JSON."]
pub unsafe fn empyrean_orbits_write_json(
&self,
path: *const ::std::os::raw::c_char,
batch: *const EmpyreanOrbitBatch,
) -> i32 {
(self.empyrean_orbits_write_json)(path, batch)
}
#[doc = " Read an orbits CSV file.\n\n CSV does not carry covariance (use parquet for covariance round-trip)."]
pub unsafe fn empyrean_orbits_read_csv(
&self,
path: *const ::std::os::raw::c_char,
out: *mut EmpyreanOrbitBatch,
) -> i32 {
(self.empyrean_orbits_read_csv)(path, out)
}
#[doc = " Write an orbit batch to CSV."]
pub unsafe fn empyrean_orbits_write_csv(
&self,
path: *const ::std::os::raw::c_char,
batch: *const EmpyreanOrbitBatch,
) -> i32 {
(self.empyrean_orbits_write_csv)(path, batch)
}
#[doc = " Write ephemeris entries to parquet using the villeneuve schema."]
pub unsafe fn empyrean_ephemeris_write_parquet(
&self,
path: *const ::std::os::raw::c_char,
entries_ptr: *const EmpyreanEphemerisEntry,
num_entries: usize,
) -> i32 {
(self.empyrean_ephemeris_write_parquet)(path, entries_ptr, num_entries)
}
#[doc = " Write ephemeris entries to JSON."]
pub unsafe fn empyrean_ephemeris_write_json(
&self,
path: *const ::std::os::raw::c_char,
entries_ptr: *const EmpyreanEphemerisEntry,
num_entries: usize,
) -> i32 {
(self.empyrean_ephemeris_write_json)(path, entries_ptr, num_entries)
}
#[doc = " Write ephemeris entries to CSV."]
pub unsafe fn empyrean_ephemeris_write_csv(
&self,
path: *const ::std::os::raw::c_char,
entries_ptr: *const EmpyreanEphemerisEntry,
num_entries: usize,
) -> i32 {
(self.empyrean_ephemeris_write_csv)(path, entries_ptr, num_entries)
}
#[doc = " Write events to parquet."]
pub unsafe fn empyrean_events_write_parquet(
&self,
path: *const ::std::os::raw::c_char,
events_ptr: *const EmpyreanEvent,
num_events: usize,
) -> i32 {
(self.empyrean_events_write_parquet)(path, events_ptr, num_events)
}
#[doc = " Write events to JSON."]
pub unsafe fn empyrean_events_write_json(
&self,
path: *const ::std::os::raw::c_char,
events_ptr: *const EmpyreanEvent,
num_events: usize,
) -> i32 {
(self.empyrean_events_write_json)(path, events_ptr, num_events)
}
#[doc = " Write events to CSV."]
pub unsafe fn empyrean_events_write_csv(
&self,
path: *const ::std::os::raw::c_char,
events_ptr: *const EmpyreanEvent,
num_events: usize,
) -> i32 {
(self.empyrean_events_write_csv)(path, events_ptr, num_events)
}
#[doc = " Write OD residuals to parquet."]
pub unsafe fn empyrean_residuals_write_parquet(
&self,
path: *const ::std::os::raw::c_char,
obs_ptr: *const EmpyreanObservationResult,
num_obs: usize,
) -> i32 {
(self.empyrean_residuals_write_parquet)(path, obs_ptr, num_obs)
}
#[doc = " Write OD residuals to JSON."]
pub unsafe fn empyrean_residuals_write_json(
&self,
path: *const ::std::os::raw::c_char,
obs_ptr: *const EmpyreanObservationResult,
num_obs: usize,
) -> i32 {
(self.empyrean_residuals_write_json)(path, obs_ptr, num_obs)
}
#[doc = " Write OD residuals to CSV."]
pub unsafe fn empyrean_residuals_write_csv(
&self,
path: *const ::std::os::raw::c_char,
obs_ptr: *const EmpyreanObservationResult,
num_obs: usize,
) -> i32 {
(self.empyrean_residuals_write_csv)(path, obs_ptr, num_obs)
}
#[doc = " Find the dominant eigenvalue and eigenvector of a 6x6 symmetric matrix.\n\n Returns 0 on success. `eigenvalue_out` receives the eigenvalue,\n `eigenvector_out` receives the 6-element eigenvector."]
pub unsafe fn empyrean_eigenvector_max_6x6(
&self,
matrix: *const [[f64; 6usize]; 6usize],
eigenvalue_out: *mut f64,
eigenvector_out: *mut [f64; 6usize],
) -> i32 {
(self.empyrean_eigenvector_max_6x6)(matrix, eigenvalue_out, eigenvector_out)
}
#[doc = " Split a 6D Gaussian into K weighted components along the dominant\n eigenvector of the covariance.\n\n `weights_out`, `means_out`, `covariances_out` must point to arrays\n of size K, K×6, and K×6×6 respectively. Returns 0 on success."]
pub unsafe fn empyrean_split_gaussian(
&self,
mean: *const [f64; 6usize],
covariance: *const [[f64; 6usize]; 6usize],
k: usize,
weights_out: *mut f64,
means_out: *mut [f64; 6usize],
covariances_out: *mut [[f64; 6usize]; 6usize],
) -> i32 {
(self.empyrean_split_gaussian)(mean, covariance, k, weights_out, means_out, covariances_out)
}
#[doc = " Compute observer states for given observatory codes and epochs.\n\n Returns 0 on success, negative error code on failure.\n On success, `result_out` is populated with observer states.\n The caller must free the result with `empyrean_observer_result_free()`."]
pub unsafe fn empyrean_get_observers(
&self,
ctx: *const EmpyreanContext,
obs_codes: *const *const ::std::os::raw::c_char,
num_codes: usize,
epochs_mjd_tdb: *const f64,
num_epochs: usize,
result_out: *mut EmpyreanObserverResult,
) -> i32 {
(self.empyrean_get_observers)(
ctx,
obs_codes,
num_codes,
epochs_mjd_tdb,
num_epochs,
result_out,
)
}
#[doc = " Free an observer result previously returned by `empyrean_get_observers()`.\n\n Passing a zeroed/null result is a no-op."]
pub unsafe fn empyrean_observer_result_free(&self, result: *mut EmpyreanObserverResult) {
(self.empyrean_observer_result_free)(result)
}
#[doc = " Read ADES PSV / MPC80 data from a string and pack into the C array.\n\n `path_or_content` is a null-terminated UTF-8 string with the ADES\n content directly (not a file path)."]
pub unsafe fn empyrean_read_ades(
&self,
content: *const ::std::os::raw::c_char,
observations_out: *mut *mut EmpyreanObservation,
num_observations_out: *mut usize,
radar_out: *mut *mut EmpyreanRadarObservation,
num_radar_out: *mut usize,
) -> i32 {
(self.empyrean_read_ades)(
content,
observations_out,
num_observations_out,
radar_out,
num_radar_out,
)
}
#[doc = " Free an observation array previously returned by `empyrean_read_ades()`.\n Copy a caller-owned array of [`EmpyreanObservation`] into a fresh\n allocation that matches the layout produced by\n [`empyrean_read_ades`].\n\n The strings on the input observations (`perm_id` / `prov_id` /\n `obs_time`) are duplicated into freshly-allocated `CString`s so the\n returned array owns its own memory independent of the input.\n\n On success populates `*out_ptr` with the new array and `*out_num`\n with its length, both freeable with [`empyrean_observations_free`].\n\n Returns 0 on success; negative error code on failure."]
pub unsafe fn empyrean_observations_from_array(
&self,
input: *const EmpyreanObservation,
num: usize,
out_ptr: *mut *mut EmpyreanObservation,
out_num: *mut usize,
) -> i32 {
(self.empyrean_observations_from_array)(input, num, out_ptr, out_num)
}
pub unsafe fn empyrean_observations_free(
&self,
observations: *mut EmpyreanObservation,
num: usize,
) {
(self.empyrean_observations_free)(observations, num)
}
#[doc = " Copy a caller-owned array of [`EmpyreanRadarObservation`] into a fresh\n allocation matching the layout produced by [`empyrean_read_ades`].\n\n The nullable `*mut c_char` fields (`perm_id` / `prov_id` / `trk_sub` /\n `obs_time` / `remarks`) are duplicated into freshly-allocated\n `CString`s so the returned array owns its own memory independent of the\n input. All scalar fields (including the ADES-native delay/Doppler\n values) are copied verbatim — no unit conversion, nothing zeroed.\n\n On success populates `*out_ptr` with the new array and `*out_num` with\n its length, both freeable with [`empyrean_radar_observations_free`].\n\n Returns 0 on success; negative error code on failure."]
pub unsafe fn empyrean_radar_observations_from_array(
&self,
input: *const EmpyreanRadarObservation,
num: usize,
out_ptr: *mut *mut EmpyreanRadarObservation,
out_num: *mut usize,
) -> i32 {
(self.empyrean_radar_observations_from_array)(input, num, out_ptr, out_num)
}
#[doc = " Free a radar observation array previously returned by\n [`empyrean_read_ades`] or [`empyrean_radar_observations_from_array`]."]
pub unsafe fn empyrean_radar_observations_free(
&self,
observations: *mut EmpyreanRadarObservation,
num: usize,
) {
(self.empyrean_radar_observations_free)(observations, num)
}
#[doc = " Run the full orbit determination pipeline.\n\n When `num_initial_orbits > 0`, the supplied orbits are used as DC\n seeds (one per ADES object_id encountered in `observations`,\n matched by orbit index). Pass `null, 0` to let the IOD pipeline\n produce its own seeds."]
pub unsafe fn empyrean_determine(
&self,
ctx: *const EmpyreanContext,
observations: *const EmpyreanObservation,
num_observations: usize,
radar: *const EmpyreanRadarObservation,
num_radar: usize,
initial_orbits: *const EmpyreanOrbit,
num_initial_orbits: usize,
config: *const EmpyreanODConfig,
result_out: *mut EmpyreanODResult,
) -> i32 {
(self.empyrean_determine)(
ctx,
observations,
num_observations,
radar,
num_radar,
initial_orbits,
num_initial_orbits,
config,
result_out,
)
}
#[doc = " Free an OD result previously returned by `empyrean_determine()` or `empyrean_refine()`."]
pub unsafe fn empyrean_od_result_free(&self, result: *mut EmpyreanODResult) {
(self.empyrean_od_result_free)(result)
}
#[doc = " Evaluate residuals for a single orbit against observations."]
pub unsafe fn empyrean_evaluate(
&self,
ctx: *const EmpyreanContext,
orbit: *const EmpyreanOrbit,
observations: *const EmpyreanObservation,
num_observations: usize,
config: *const EmpyreanODConfig,
result_out: *mut EmpyreanEvaluateResult,
) -> i32 {
(self.empyrean_evaluate)(
ctx,
orbit,
observations,
num_observations,
config,
result_out,
)
}
#[doc = " Free an evaluate result previously returned by `empyrean_evaluate()`."]
pub unsafe fn empyrean_evaluate_result_free(&self, result: *mut EmpyreanEvaluateResult) {
(self.empyrean_evaluate_result_free)(result)
}
#[doc = " Refine a single orbit estimate with new observations using a\n Bayesian prior."]
pub unsafe fn empyrean_refine(
&self,
ctx: *const EmpyreanContext,
orbit: *const EmpyreanOrbit,
observations: *const EmpyreanObservation,
num_observations: usize,
config: *const EmpyreanODConfig,
result_out: *mut EmpyreanODResult,
) -> i32 {
(self.empyrean_refine)(
ctx,
orbit,
observations,
num_observations,
config,
result_out,
)
}
#[doc = " Evaluate an observation plan: how much each candidate observation would\n tighten the prior orbit covariance.\n\n `orbit` must carry a 6×6 Cartesian covariance (e.g. a `determine` result).\n `planned` is an array of `num_planned` candidate observations. `orbit_id`\n may be null (defaults to `\"orbit_0\"`). On success populates `*result_out`\n (caller-allocated); free with [`empyrean_plan_result_free`].\n\n Returns 0 on success, -1 for a null/invalid argument, -3 if planning fails\n (missing/singular prior covariance, an infeasible or invalid candidate, an\n ephemeris-generation error), -99 on an internal panic. The error message is\n retrievable via `empyrean_last_error()`."]
pub unsafe fn empyrean_evaluate_plan(
&self,
ctx: *const EmpyreanContext,
orbit: *const EmpyreanOrbit,
orbit_id: *const ::std::os::raw::c_char,
planned: *const EmpyreanPlannedObservation,
num_planned: usize,
config: *const EmpyreanPlanningConfig,
result_out: *mut EmpyreanPlanResult,
) -> i32 {
(self.empyrean_evaluate_plan)(
ctx,
orbit,
orbit_id,
planned,
num_planned,
config,
result_out,
)
}
#[doc = " Free the heap allocations inside a plan result populated by\n [`empyrean_evaluate_plan`]. Does not free the caller-allocated struct."]
pub unsafe fn empyrean_plan_result_free(&self, result: *mut EmpyreanPlanResult) {
(self.empyrean_plan_result_free)(result)
}
#[doc = " Propagate orbits to the requested target times.\n\n Returns 0 on success, negative error code on failure.\n On success, `result_out` is populated with the propagated states.\n The caller must free the result with `empyrean_propagation_result_free()`."]
pub unsafe fn empyrean_propagate(
&self,
ctx: *const EmpyreanContext,
orbits_ptr: *const EmpyreanOrbit,
num_orbits: usize,
times_ptr: *const f64,
num_times: usize,
config: *const EmpyreanPropagationConfig,
result_out: *mut EmpyreanPropagationResult,
) -> i32 {
(self.empyrean_propagate)(
ctx, orbits_ptr, num_orbits, times_ptr, num_times, config, result_out,
)
}
#[doc = " Free a propagation result previously returned by `empyrean_propagate()`."]
pub unsafe fn empyrean_propagation_result_free(&self, result: *mut EmpyreanPropagationResult) {
(self.empyrean_propagation_result_free)(result)
}
#[doc = " Resolved-kind tagged covariance at every output epoch for one orbit,\n Cartesian basis. On success `out_series` owns the array; free with\n [`empyrean_tagged_covariance_series_free`]. On error `out_series` is\n left null and the detail is on `empyrean_last_error()`.\n\n # Safety\n `result` must be a valid pointer returned by `empyrean_propagate`;\n `out_series` must be a valid pointer to write the result into."]
pub unsafe fn empyrean_propagation_covariance_series_cartesian(
&self,
result: *const EmpyreanPropagationResult,
orbit_index: usize,
out_series: *mut *mut EmpyreanTaggedCovarianceSeries,
) -> i32 {
(self.empyrean_propagation_covariance_series_cartesian)(result, orbit_index, out_series)
}
#[doc = " Resolved-kind tagged covariance at a single `(orbit_index,\n epoch_index)`, Cartesian basis (the gm-free point query). `out` is\n written on success.\n\n # Safety\n `result` and `out` must be valid pointers; `result` from `empyrean_propagate`."]
pub unsafe fn empyrean_propagation_covariance_at_cartesian(
&self,
result: *const EmpyreanPropagationResult,
orbit_index: usize,
epoch_index: usize,
out: *mut EmpyreanTaggedCovariance,
) -> i32 {
(self.empyrean_propagation_covariance_at_cartesian)(result, orbit_index, epoch_index, out)
}
#[doc = " Free a series returned by\n [`empyrean_propagation_covariance_series_cartesian`].\n\n # Safety\n `series` must be null or a pointer returned by that accessor, freed once."]
pub unsafe fn empyrean_tagged_covariance_series_free(
&self,
series: *mut EmpyreanTaggedCovarianceSeries,
) {
(self.empyrean_tagged_covariance_series_free)(series)
}
#[doc = " Query the JPL Small-Body Database for one or more orbits.\n\n `object_ids` is an array of `num_object_ids` null-terminated UTF-8\n designations / names / SPK IDs (e.g. `\"apophis\"`, `\"99942\"`,\n `\"2024 YR4\"`, `\"67P\"`). `cache_dir` may be null to skip caching, or\n a directory path where SBDB JSON responses are cached on disk.\n\n On success the populated [`EmpyreanOrbitBatch`] must be released with\n [`empyrean_orbits_batch_free`](crate::io::empyrean_orbits_batch_free)."]
pub unsafe fn empyrean_query_sbdb(
&self,
object_ids: *const *const ::std::os::raw::c_char,
num_object_ids: usize,
cache_dir: *const ::std::os::raw::c_char,
out: *mut EmpyreanOrbitBatch,
) -> i32 {
(self.empyrean_query_sbdb)(object_ids, num_object_ids, cache_dir, out)
}
#[doc = " Query JPL Horizons for predicted ephemeris records.\n\n `object_ids` is an array of `num_object_ids` null-terminated UTF-8\n designations / names / SPK IDs. `obs_code` is the MPC observatory\n code as a null-terminated string. `times_mjd_tdb` carries\n `num_times` epochs in MJD TDB.\n\n On success populates an [`EmpyreanEphemerisResult`] with one entry\n per `(object_id × epoch)`. Free with\n [`empyrean_ephemeris_result_free`](crate::ephemeris::empyrean_ephemeris_result_free).\n\n All angular values are converted to **degrees** at the FFI boundary\n (Horizons natively returns radians)."]
pub unsafe fn empyrean_query_horizons(
&self,
object_ids: *const *const ::std::os::raw::c_char,
num_object_ids: usize,
obs_code: *const ::std::os::raw::c_char,
times_mjd_tdb: *const f64,
num_times: usize,
cache_dir: *const ::std::os::raw::c_char,
out: *mut EmpyreanEphemerisResult,
) -> i32 {
(self.empyrean_query_horizons)(
object_ids,
num_object_ids,
obs_code,
times_mjd_tdb,
num_times,
cache_dir,
out,
)
}
#[doc = " Query JPL Horizons for a Cartesian state vector at a single epoch.\n\n `command` is the Horizons COMMAND string as a null-terminated UTF-8\n string (e.g. `\"99942;\"`, `\"DES=C/2019 Q4;\"`). `epoch_mjd_tdb` is\n the epoch in MJD TDB. `cache_dir` may be null to skip caching, or\n a directory path where Horizons JSON responses are cached on disk.\n\n On success writes the position (AU) to `out_pos` (length 3) and the\n velocity (AU/day) to `out_vel` (length 3) — both solar-system\n barycenter (SSB) centered, ICRF."]
pub unsafe fn empyrean_query_horizons_vectors(
&self,
command: *const ::std::os::raw::c_char,
epoch_mjd_tdb: f64,
cache_dir: *const ::std::os::raw::c_char,
out_pos: *mut f64,
out_vel: *mut f64,
) -> i32 {
(self.empyrean_query_horizons_vectors)(command, epoch_mjd_tdb, cache_dir, out_pos, out_vel)
}
#[doc = " Query the MPC observations API for ADES records of one or more\n designations.\n\n `designations` is an array of `num_designations` null-terminated\n UTF-8 designations (e.g. `\"99942\"`, `\"2024 YR4\"`, `\"67P\"`). The\n MPC API returns ADES_DF JSON; this function parses each row into\n the C-ABI [`EmpyreanObservation`] struct, filling the full ADES\n schema (perm_id / prov_id / trk_sub / mode / sys / ctr / pos1-3 /\n rms_corr / mag / rms_mag / band / ast_cat / phot_cat / phot_ap /\n log_snr / seeing / exp / rms_fit / n_stars / notes / remarks) when\n present in the JSON.\n\n On success `*out_ptr` carries a heap-allocated array of length\n `*out_num`. Free with\n [`empyrean_observations_free`](crate::od::empyrean_observations_free)."]
pub unsafe fn empyrean_query_observations(
&self,
designations: *const *const ::std::os::raw::c_char,
num_designations: usize,
cache_dir: *const ::std::os::raw::c_char,
out_ptr: *mut *mut EmpyreanObservation,
out_num: *mut usize,
) -> i32 {
(self.empyrean_query_observations)(
designations,
num_designations,
cache_dir,
out_ptr,
out_num,
)
}
#[doc = " Query the JPL `sb_radar` API for delay/Doppler radar astrometry of one\n or more designations.\n\n `designations` is an array of `num_designations` null-terminated UTF-8\n designations (e.g. `\"99942\"`, `\"2024 YR4\"`). Asteroid radar astrometry\n is a JPL SSD product — it is **not** served by the MPC observations API\n (`empyrean_query_observations` returns only optical / occultation\n records), so radar ships as its own live-query entry point. JPL\n `sb_radar` JSON records are converted to ADES-native scott\n `RadarObservation`s and packed into the C-ABI\n [`EmpyreanRadarObservation`] struct (the same layout\n [`empyrean_read_ades`](crate::od::empyrean_read_ades) emits): the delay\n value is in seconds, its σ in microseconds, Doppler in Hz, frequency in\n MHz, and the `com` flag is a tri-state i8. `cache_dir` may be null to\n skip caching, or a directory path where `sb_radar` JSON responses are\n cached on disk.\n\n An object with no radar astrometry contributes no records (it is not an\n error). A JPL record that fails to parse (missing required field, or an\n unrecognised DSN station code) is rejected loudly rather than silently\n dropped — the whole call fails so no radar quietly goes missing.\n\n On success `*out_ptr` carries a heap-allocated array of length\n `*out_num`. Free with\n [`empyrean_radar_observations_free`](crate::od::empyrean_radar_observations_free)."]
pub unsafe fn empyrean_query_radar(
&self,
designations: *const *const ::std::os::raw::c_char,
num_designations: usize,
cache_dir: *const ::std::os::raw::c_char,
out_ptr: *mut *mut EmpyreanRadarObservation,
out_num: *mut usize,
) -> i32 {
(self.empyrean_query_radar)(designations, num_designations, cache_dir, out_ptr, out_num)
}
#[doc = " Construct a new orbit-determination session over a fixed\n observation set.\n\n Returns a heap-allocated handle on success, or null on error.\n The caller owns the returned pointer and must free it with\n [`empyrean_session_free`]."]
pub unsafe fn empyrean_session_new(
&self,
observations: *const EmpyreanObservation,
num_observations: usize,
config: *const EmpyreanODConfig,
) -> *mut EmpyreanSession {
(self.empyrean_session_new)(observations, num_observations, config)
}
#[doc = " Free a session previously returned by [`empyrean_session_new`].\n Passing null is a no-op."]
pub unsafe fn empyrean_session_free(&self, session: *mut EmpyreanSession) {
(self.empyrean_session_free)(session)
}
#[doc = " Total number of observations in the session (masked or not).\n Returns 0 if `session` is null."]
pub unsafe fn empyrean_session_n_observations(&self, session: *const EmpyreanSession) -> usize {
(self.empyrean_session_n_observations)(session)
}
#[doc = " Number of observations currently masked."]
pub unsafe fn empyrean_session_n_masked(&self, session: *const EmpyreanSession) -> usize {
(self.empyrean_session_n_masked)(session)
}
#[doc = " Number of observations active (not masked) in the next refine."]
pub unsafe fn empyrean_session_n_active(&self, session: *const EmpyreanSession) -> usize {
(self.empyrean_session_n_active)(session)
}
#[doc = " Mask the observation at `idx`. Returns 0 on success, -1 on null\n or out-of-bounds."]
pub unsafe fn empyrean_session_mask(&self, session: *mut EmpyreanSession, idx: usize) -> i32 {
(self.empyrean_session_mask)(session, idx)
}
#[doc = " Unmask the observation at `idx`. Returns 0 on success, -1 on null\n or out-of-bounds."]
pub unsafe fn empyrean_session_unmask(&self, session: *mut EmpyreanSession, idx: usize) -> i32 {
(self.empyrean_session_unmask)(session, idx)
}
#[doc = " Clear all masks. Returns 0 on success, -1 on null."]
pub unsafe fn empyrean_session_unmask_all(&self, session: *mut EmpyreanSession) -> i32 {
(self.empyrean_session_unmask_all)(session)
}
#[doc = " Whether the observation at `idx` is masked. Returns 1 = masked,\n 0 = active, 255 (-1 cast) on null/out-of-bounds."]
pub unsafe fn empyrean_session_is_masked(
&self,
session: *const EmpyreanSession,
idx: usize,
) -> u8 {
(self.empyrean_session_is_masked)(session, idx)
}
#[doc = " Run an OD refine using the current mask state.\n\n On the first call, runs the full IOD → DC pipeline. On subsequent\n calls, uses the previously-fit orbit as the IOD seed (skipping the\n IOD step). Pushes the new fit onto the session's history.\n\n On success populates `result_out` with the latest fit. The caller\n must free `result_out` with [`empyrean_od_result_free`](crate::od::empyrean_od_result_free)."]
pub unsafe fn empyrean_session_refine(
&self,
session: *mut EmpyreanSession,
ctx: *const EmpyreanContext,
result_out: *mut EmpyreanODResult,
) -> i32 {
(self.empyrean_session_refine)(session, ctx, result_out)
}
#[doc = " Number of fits in the session history."]
pub unsafe fn empyrean_session_history_len(&self, session: *const EmpyreanSession) -> usize {
(self.empyrean_session_history_len)(session)
}
#[doc = " Copy the i-th history entry into `result_out`. Returns 0 on\n success, -1 on null/out-of-bounds. Caller frees `result_out` with\n [`empyrean_od_result_free`](crate::od::empyrean_od_result_free)."]
pub unsafe fn empyrean_session_get_history(
&self,
session: *const EmpyreanSession,
idx: usize,
result_out: *mut EmpyreanODResult,
) -> i32 {
(self.empyrean_session_get_history)(session, idx, result_out)
}
#[doc = " Diff the current fit against an earlier history entry. Returns 0\n on success, -1 if there is no current fit or `prior_idx` is out\n of bounds."]
pub unsafe fn empyrean_session_diff(
&self,
session: *const EmpyreanSession,
prior_idx: usize,
diff_out: *mut EmpyreanSessionDiff,
) -> i32 {
(self.empyrean_session_diff)(session, prior_idx, diff_out)
}
#[doc = " Query body states relative to a center body at given epochs.\n\n Returns 0 on success, negative error code on failure.\n On success, `result_out` is populated with body states.\n The caller must free the result with `empyrean_state_result_free()`."]
pub unsafe fn empyrean_get_states(
&self,
ctx: *const EmpyreanContext,
target_naif_id: i32,
center_naif_id: i32,
epochs_mjd_tdb: *const f64,
num_epochs: usize,
frame: i32,
result_out: *mut EmpyreanStateResult,
) -> i32 {
(self.empyrean_get_states)(
ctx,
target_naif_id,
center_naif_id,
epochs_mjd_tdb,
num_epochs,
frame,
result_out,
)
}
#[doc = " Free a state result previously returned by `empyrean_get_states()`.\n\n Passing a zeroed/null result is a no-op."]
pub unsafe fn empyrean_state_result_free(&self, result: *mut EmpyreanStateResult) {
(self.empyrean_state_result_free)(result)
}
#[doc = " Parse an ISO 8601 UTC string (e.g. ``\"2024-08-01T00:00:00.000Z\"``)\n to MJD in the requested target scale.\n\n `scale` is `0` for UTC, `1` for TDB.\n\n On success writes the MJD value to `*out_mjd` and returns 0.\n On failure returns a negative code; consult\n [`empyrean_last_error`](crate::empyrean_last_error)."]
pub unsafe fn empyrean_iso_to_mjd(
&self,
iso: *const ::std::os::raw::c_char,
scale: i32,
out_mjd: *mut f64,
) -> i32 {
(self.empyrean_iso_to_mjd)(iso, scale, out_mjd)
}
#[doc = " Format an MJD value (in the given scale) as an ISO 8601 UTC string.\n\n `scale` is `0` for UTC, `1` for TDB. Writes a null-terminated\n string of length ≤ `buf_len-1` into `out_buf`. A 32-byte buffer is\n always sufficient (typical output is 24 bytes:\n ``\"2024-08-01T00:00:00.000Z\"``).\n\n Returns 0 on success; negative on failure."]
pub unsafe fn empyrean_mjd_to_iso(
&self,
mjd: f64,
scale: i32,
out_buf: *mut ::std::os::raw::c_char,
buf_len: usize,
) -> i32 {
(self.empyrean_mjd_to_iso)(mjd, scale, out_buf, buf_len)
}
#[doc = " Transform a coordinate state to a new representation, frame, and/or origin.\n\n Returns 0 on success or a negative error code on failure.\n Call `empyrean_last_error()` to retrieve the error message on failure."]
pub unsafe fn empyrean_transform_coordinates(
&self,
ctx: *const EmpyreanContext,
input: *const CoordinateState,
target_representation: i32,
target_frame: i32,
target_origin: i32,
output: *mut CoordinateState,
) -> i32 {
(self.empyrean_transform_coordinates)(
ctx,
input,
target_representation,
target_frame,
target_origin,
output,
)
}
}