ballistics_engine/lib.rs
1//! # Ballistics Engine
2//!
3//! High-performance ballistics trajectory calculation engine with comprehensive physics modeling.
4//!
5//! ## Interactive Web Demo
6//!
7//! Try the ballistics engine directly in your browser at [https://ballistics.rs/](https://ballistics.rs/)
8//!
9//! ## Features
10//!
11//! - Professional-grade trajectory calculations with multiple drag models
12//! - Advanced physics including spin drift, Coriolis effect, and Magnus force
13//! - Monte Carlo simulations for uncertainty analysis
14//! - WebAssembly support for browser-based applications
15//! - FFI bindings for iOS and Android development
16
17// Re-export the main types and functions
18pub use atmosphere::{
19 resolve_station_conditions_with_presence, AtmoSegment, AtmoSock, StationAtmospherePresence,
20 StationReading,
21};
22pub use cli_api::{
23 calculate_zero_angle, calculate_zero_angle_with_conditions,
24 calculate_zero_angle_with_resolved_conditions, calculate_zero_angle_with_station_presence,
25 calculate_zero_range_from_angle_with_conditions,
26 calculate_zero_range_from_angle_with_resolved_conditions,
27 calculate_zero_range_from_angle_with_station_presence, estimate_bc_fit,
28 estimate_bc_fit_with_station_presence, estimate_bc_from_trajectory,
29 interpolate_powder_temp_curve, resolve_powder_adjusted_velocity, run_monte_carlo,
30 run_monte_carlo_adaptive_seeded, run_monte_carlo_adaptive_seeded_with_station_presence,
31 run_monte_carlo_with_direction_std_dev, run_monte_carlo_with_station_presence,
32 run_monte_carlo_with_wind, run_monte_carlo_with_wind_and_direction_std_dev,
33 run_monte_carlo_with_wind_and_direction_std_dev_seeded, AdaptiveMcReportV1,
34 AtmosphericConditions, BallisticInputs, BallisticsError, BcEstimate, BcFitMode,
35 BcReferenceStandard, DropsReference, McConvergence, McStopReason, MonteCarloParams,
36 MonteCarloResults, TrajectoryPoint, TrajectoryResult, TrajectorySolver, WindConditions,
37 ZeroCrossings, DEFAULT_HIT_RADIUS_M, MAX_TRAJECTORY_POINTS, MC_ADAPTIVE_ASSUMPTIONS_V1,
38 MC_ADAPTIVE_METHOD_V1, MC_ADAPTIVE_SCHEMA_VERSION_V1, TARGET_NOT_REACHED_SENTINEL_M,
39 ZERO_RANGE_FROM_ANGLE_MAX_RANGE_M,
40};
41pub use drag_model::DragModel;
42pub use mc_stats::{wilson_interval, ConfidenceLevel};
43pub use moving_target::{
44 calculate_lead, calculate_lead_with_station_presence, lead_from_tof, mover_ring,
45 LeadComponents, LeadError, LeadSolution,
46};
47pub use solve_json::{
48 decode_solve_request_v1, ResolvedSolveRequestV1, SolveErrorCodeV1, SolveErrorEnvelopeV1,
49 SolveRequestV1, SolveSuccessV1, MAX_SOLVE_JSON_SAMPLES_V1, SOLVE_JSON_SCHEMA_VERSION_V1,
50};
51pub use solve_v1::solve_v1;
52pub use trajectory_observation::{
53 TrajectoryObservation, TrajectoryObservationError, TrajectoryObservationFlag,
54 TrajectoryTermination,
55};
56pub use trajectory_sampling::MAX_TRAJECTORY_SAMPLES;
57
58// Module declarations
59pub mod cli_api;
60// MBA-1375: deterministic reference-family BC conversion and banded least-squares family
61// recommendation, shared by native and WASM front ends. Pure table math; no filesystem I/O.
62pub mod bc_conversion;
63mod drag_model;
64mod gravity;
65pub mod moving_target;
66// The C ABI. Gated behind the default-on `ffi` feature so a binary that links two versions of
67// this crate can disable it on one edge and avoid duplicate #[no_mangle] symbols.
68#[cfg(feature = "ffi")]
69pub mod ffi;
70pub mod solve_json;
71pub mod solve_v1;
72// 0.33.0 decision-support Task 2: reverse conversion from a resolved request back into a
73// solvable one (`impl From<&ResolvedSolveRequestV1> for SolveRequestV1`), the direction the
74// perturbation kernel needs to take a resolved request, change one input, and re-solve. No
75// public items of its own -- the trait impl is usable wherever solve_json's public types are.
76mod request_roundtrip;
77pub mod terminal_plot;
78// MBA-1343: multi-observation velocity/BC truing core, shared by the CLI and the WASM terminal.
79pub mod truing;
80// MBA-1346: observation-range experiment design for identifiable MV/BC truing.
81pub mod truing_plan;
82// MBA-1353: opt-in uncertainty-aware joint MV/BC truing.
83pub mod truing_uncertainty;
84// MBA-1357: Mach-keyed DSF (drop-scale-factor) truing table — a drop-only post-processing
85// correction applied to a solved TrajectoryResult. No feature gate: must compile for wasm32;
86// fs-free (profile persistence lives in main.rs).
87pub mod truing_dsf;
88// MBA-1392: back-solve the effective crosswind from an observed horizontal miss (wind-call
89// truing). Carries its own shared table/JSON/CSV formatter so the native CLI and the WASM
90// terminal render identical bytes. No feature gate: must compile for wasm32.
91pub mod truing_wind;
92// Task 6 (truing JSON bridge): the tall-target correction-factor arithmetic, extracted out
93// of the CLI's `Commands::TallTarget` arm so the CLI and a future bridge command share one
94// implementation. No feature gate: must compile for wasm32; fs-free (the CLI keeps its
95// println! formatting, only the arithmetic and validation moved here).
96pub mod truing_service;
97// MBA-1349: robust hold corridors across named segmented-wind scenarios. No feature gate:
98// must compile for wasm32 (the CLI surface is native-only this train, but the core and its
99// shared formatter are ready for the WASM follow-up); fs-free — file reading stays in
100// main.rs, this module parses TEXT.
101pub mod wind_scenarios;
102// MBA-1361: reticle schema, parametric generators, and the hold-point-in-reticle API,
103// shared by the CLI, the WASM terminal and the FFI. No feature gate: must compile for
104// wasm32; pure math + serde, no I/O (file reading stays in main.rs/wasm.rs).
105pub mod reticle;
106// MBA-1440: import Bero's "Ventum" reticle spec into `reticle::ReticleDescription` so a
107// reticle drawn in that tool can be hold-solved by `reticle::hold_point_in_reticle`. Pure
108// transform + serde, no I/O; must compile for wasm32. Deliberately NOT wired into the
109// CLI / solve-json / WASM / FFI surfaces yet (that exposure is held for review).
110pub mod reticle_import;
111// MBA-1545: named reticles by id — the per-vendor catalog `reticle`'s header defers
112// to, kept in its own module so that module's "no vendor reticle catalog" statement
113// stays true of the module it was made about. Provenance per entry is mandatory.
114pub mod reticle_catalog;
115// Cleanroom import of the third-party `.reticle` XML drawing format into
116// `reticle::ReticleDescription`, the sibling of `reticle_import` for a format that is a
117// picture rather than a mark list: its `<bdc>` entries are the holds, its `<elements>`
118// drawing is dropped (and counted, so the rule is visible). Pure transform, no I/O; must
119// compile for wasm32. Deliberately NOT wired into the CLI / solve-json / WASM / FFI
120// surfaces (that exposure is a separate decision).
121pub mod reticle_document_import;
122// MBA-1343 Phase B: WEZ (`monte-carlo --wez`) sweep core, shared by the CLI and the WASM terminal.
123pub mod wez;
124// MBA-1355: turret adjustment-unit conversions (SMOA/IPHY/clicks) and click-value parsing,
125// shared by the CLI and the WASM terminal. No feature gate: must compile for wasm32.
126pub mod adjustment;
127// MBA-1409: cleanroom `.drg` (Doppler drag-curve text file) parser, shared by the CLI and
128// the WASM terminal. No feature gate: must compile for wasm32; parses TEXT only (no
129// std::fs — file I/O stays in main.rs/wasm.rs).
130pub mod drag_file;
131// MBA-1372: SAAMI free-recoil momentum-balance calculator, shared by the CLI and the
132// WASM terminal. No feature gate: must compile for wasm32; pure math, no I/O.
133pub mod recoil;
134// MBA-1372: power-factor arithmetic and per-organization (USPSA/IDPA/SASS) rulebook
135// pass/fail thresholds, shared by the CLI and the WASM terminal. No feature gate: must
136// compile for wasm32; pure math + a data table, no I/O.
137pub mod power_factor;
138pub mod trajectory_observation;
139#[cfg(target_arch = "wasm32")]
140pub mod wasm;
141#[cfg(test)]
142mod wasm_tests;
143// MBA-154: Make constants public for ballistics_rust wrapping
144pub mod atmosphere;
145// `atmosphere.density_altitude`: describe an atmosphere the way a solve resolves it.
146// Unconditional -- pure arithmetic over the solve-json schema, so it exists on every
147// target the bridge does, including wasm32, which has no PDF card.
148pub mod atmosphere_service;
149pub mod constants;
150pub mod drag;
151pub mod wind;
152// MBA-153: Make wind_shear public for ballistics_rust wrapping
153pub mod wind_shear;
154// MBA-154: Make derivatives public for ballistics_rust wrapping
155pub mod derivatives;
156pub mod trajectory_sampling;
157// MBA-154: Make fast_trajectory public for ballistics_rust wrapping
158pub mod fast_trajectory;
159// MBA-155: Add advanced integration methods (RK4, RK45)
160pub mod trajectory_integration;
161// MBA-149 Phase 5 Priority 2: Export enhanced spin_drift
162pub mod pitch_damping;
163pub mod spin_decay;
164pub mod spin_drift;
165pub mod spin_drift_advanced;
166// MBA-149 Phase 5 Priority 2: Export enhanced precession_nutation
167pub mod precession_nutation;
168// MBA-153: Make aerodynamic_jump public for ballistics_rust wrapping
169pub mod aerodynamic_jump;
170// MBA-149 Phase 5 Priority 2: Export enhanced angle_calculations
171pub mod angle_calculations;
172pub mod transonic_drag;
173// MBA-153: Make reynolds public for ballistics_rust wrapping
174pub mod reynolds;
175// MBA-149 Phase 5 Priority 2: Export enhanced form_factor
176pub mod form_factor;
177// MBA-153: Make monte_carlo public for ballistics_rust wrapping
178pub mod bc_estimation;
179pub mod cluster_bc;
180// MBA-1352 Task 2: Monte Carlo hit-statistics foundation -- Welford streaming moments and
181// fixed-n Wilson score intervals. The anytime-valid confidence sequence (Task 3) extends this
182// module. No feature gate: must compile for wasm32; pure std math, no randomness.
183pub mod mc_stats;
184pub mod monte_carlo;
185pub mod stability;
186pub mod stability_advanced;
187// 0.33.0 decision-support Phase 1: shared input taxonomy for perturbation kernel and
188// uncertainty propagation. No feature gate: must compile for wasm32 (pure data + serde).
189pub mod perturbation;
190// MBA-1345: explain why two fully resolved solve results differ, by symmetric counterfactual
191// swap of each input group (built on `perturbation`'s Tasks 5-8 kernel). No feature gate: must
192// compile for wasm32 (depends only on perturbation/solve_json/solve_v1, all unconditional).
193pub mod explain;
194// MBA-1347: erf/erfc/normal_cdf for hit-probability integration (mass of a bivariate
195// normal over a target). In-crate rather than a dependency: the crate ships to thirteen
196// platforms including big-endian MIPS and wasm32 and already hand-rolls its statistical
197// constants. No feature gate: must compile for wasm32; pure std float math, no I/O.
198pub mod special;
199// 0.33.0 decision-support Task 10, MBA-1347: propagate declared per-input uncertainty to
200// impact covariance via the perturbation kernel's central differences, and rank sources by
201// variance share into a measurement-priority report. Built on `perturbation` (Tasks 5-8) and
202// reuses `truing_uncertainty::Symmetric2` for the 2x2 covariance/eigenvalue arithmetic. No
203// feature gate: must compile for wasm32 (depends only on perturbation/solve_json/
204// truing_uncertainty, all unconditional).
205pub mod error_budget;
206// 0.33.0 decision-support Task 12, MBA-1350: one-variable tolerance envelopes -- how far a
207// single input may drift from its own current value before the impact leaves an explicit
208// target, by monotone bisection outward from the nominal (`perturbation::bisect_axis`, Task 7).
209// Reuses `error_budget::TargetGeometryV1` and its unavailable-axis classification verbatim. No
210// feature gate: must compile for wasm32 (depends only on perturbation/error_budget/solve_json,
211// all unconditional).
212pub mod tolerance;
213// 0.33.0 decision-support Task 3, MBA-1348: turret + reticle geometry model (click
214// detents/revolutions, zero stop, travel limits, current turret state, reticle hold
215// bounds) that a later dial/hold/hybrid engagement planner will read. Pure data +
216// validation; no feature gate: must compile for wasm32 (depends only on `adjustment`,
217// itself unconditional).
218pub mod optic;
219// 0.33.0 decision-support Task 8: `HoldCurve`, the drop-vs-range interpolation core shared
220// by `mark-to-range`, `bdc-match`, `optimal-zero` and `reticle hold --range`, promoted out of
221// the CLI binary (together with the sampled-trajectory helpers it solves through) so the
222// range-card work its own doc comment already nominates can reuse it as a library dependency.
223// No feature gate: must compile for wasm32 (pure math over already-resolved inputs; no fs, no
224// clap -- CLI argument resolution stays in `main.rs`).
225pub mod card_service;
226pub mod hold_curve;
227// 0.33.0 decision-support Task 9: `CardRow`, the shared display-ready row type behind the
228// come-ups/range-table/wind-card/compare CLI surfaces, replacing four function-local row
229// structs that each said the same thing a different way. Pure data; no feature gate: must
230// compile for wasm32 (no fs, no clap, no pdf -- those stay in main.rs). Task 10 rewrites the
231// PDF dope card on `&[CardRow]`; Task 11 grows an adaptive-card engine here.
232pub mod card;
233// 0.33.0 decision-support Task 10: the PDF dope card, promoted out of the `ballistics`
234// binary (it was `mod pdf_dope_card;`, private to `main.rs`) so it can consume
235// `card::CardRow` directly instead of its own `DopeCardRow { range_yd: u32, .. }` -- that
236// u32-yards field couldn't express the non-integer ranges Task 11's adaptive card engine
237// produces. Feature-gated (unlike `card`): pulls in `printpdf` (PDF generation) and `dirs`
238// (font-file lookup), neither wasm32-safe nor free -- `pdf` is on by default but the
239// wasm32 build always passes `--no-default-features`.
240#[cfg(feature = "pdf")]
241pub mod pdf_dope_card;
242
243// Online mode: HTTP client for Flask API (feature-gated)
244#[cfg(feature = "online")]
245pub mod api_client;
246
247#[cfg(feature = "online")]
248pub mod credentials;
249
250// BC5D table auto-download (feature-gated)
251#[cfg(feature = "online")]
252pub mod bc_table_download;
253
254// BC correction table for offline mode
255pub mod bc_table;
256
257// 5D BC correction tables (caliber-specific, ML-derived)
258pub mod bc_table_5d;
259
260// Saved-profile data model (ProfileData & friends), moved from main.rs so the bridge's
261// profile.validate/profile.normalize/profile.import_a7p commands and the CLI share one
262// serde wire shape. No feature gate: must compile for wasm32; fs-free (profile
263// persistence and unit conversion of loaded profiles stay in main.rs).
264pub mod profile;
265
266// Import of third-party ballistic profile files (.a7p), feature-gated
267#[cfg(feature = "profile-import")]
268pub mod profile_import;
269
270// MBA-1556: the outbound direction — ProfileData -> .a7p — with the list of every
271// ProfileData field the format cannot carry. Its own feature because writing a
272// third-party format is a separate capability from reading one; it implies
273// `profile-import`, whose MD5 envelope helper (`wrap_payload`) it shares so both
274// directions agree on the envelope by construction rather than by review.
275#[cfg(feature = "profile-export")]
276pub mod profile_export;
277
278// Versioned JSON command bridge for embedded (mobile/FFI) consumers
279#[cfg(feature = "bridge")]
280pub mod bridge;
281
282// Internal type alias for compatibility
283pub(crate) type InternalBallisticInputs = BallisticInputs;
284
285// BC segment data for velocity-dependent BC
286#[derive(Debug, Clone)]
287pub struct BCSegmentData {
288 pub velocity_min: f64,
289 pub velocity_max: f64,
290 pub bc_value: f64,
291}