Skip to main content

BallisticInputs

Struct BallisticInputs 

Source
pub struct BallisticInputs {
Show 66 fields pub bc_value: f64, pub bc_type: DragModel, pub bc_reference_standard: BcReferenceStandard, pub bullet_mass: f64, pub muzzle_velocity: f64, pub bullet_diameter: f64, pub bullet_length: f64, pub muzzle_angle: f64, pub target_distance: f64, pub azimuth_angle: f64, pub shot_azimuth: f64, pub shooting_angle: f64, pub cant_angle: f64, pub sight_height: f64, pub sight_offset_lateral_m: f64, pub muzzle_height: f64, pub target_height: f64, pub zero_poi_vertical_m: f64, pub zero_poi_horizontal_m: f64, pub ground_threshold: f64, pub altitude: f64, pub temperature: f64, pub pressure: f64, pub humidity: f64, pub latitude: Option<f64>, pub wind_speed: f64, pub wind_angle: f64, pub twist_rate: f64, pub is_twist_right: bool, pub caliber_inches: f64, pub weight_grains: f64, pub manufacturer: Option<String>, pub bullet_model: Option<String>, pub bullet_id: Option<String>, pub bullet_cluster: Option<usize>, pub use_rk4: bool, pub use_adaptive_rk45: bool, pub enable_advanced_effects: bool, pub enable_magnus: bool, pub enable_coriolis: bool, pub use_powder_sensitivity: bool, pub powder_temp_sensitivity: f64, pub powder_temp: f64, pub powder_temp_curve: Option<Vec<(f64, f64)>>, pub powder_curve_temp_c: Option<f64>, pub tipoff_yaw: f64, pub tipoff_decay_distance: f64, pub cd_delta2: f64, pub use_bc_segments: bool, pub bc_segments: Option<Vec<(f64, f64)>>, pub bc_segments_data: Option<Vec<BCSegmentData>>, pub use_enhanced_spin_drift: bool, pub use_form_factor: bool, pub enable_wind_shear: bool, pub wind_shear_model: String, pub enable_trajectory_sampling: bool, pub sample_interval: f64, pub drops_reference: DropsReference, pub enable_pitch_damping: bool, pub enable_precession_nutation: bool, pub enable_aerodynamic_jump: bool, pub use_cluster_bc: bool, pub custom_drag_table: Option<DragTable>, pub cd_scale: f64, pub custom_drag_reference: bool, pub bc_type_str: Option<String>,
}

Fields§

§bc_value: f64§bc_type: DragModel§bc_reference_standard: BcReferenceStandard

Which standard atmosphere bc_value/bc_segments/bc_segments_data are referenced to (MBA-1365). Icao (the default) is a no-op; ArmyStandardMetro is converted to the ICAO reference exactly once, in TrajectorySolver::new, before any retardation math runs. See BcReferenceStandard.

§bullet_mass: f64§muzzle_velocity: f64§bullet_diameter: f64§bullet_length: f64§muzzle_angle: f64§target_distance: f64§azimuth_angle: f64§shot_azimuth: f64

Compass bearing the shot is fired ALONG, radians, 0 = North, π/2 = East. Used only by the Coriolis model (Earth-rotation depends on which way downrange points relative to true North). Distinct from azimuth_angle, which is the small horizontal aiming offset and rotates the launch velocity.

§shooting_angle: f64§cant_angle: f64

Rifle cant angle in radians about the line of sight — positive = clockwise from the shooter’s view (top of the scope tips right). Rotates the sight-frame aim offsets (muzzle_angle, azimuth_angle) about the LOS and swings the bore’s sight-height offset laterally, producing the classic canted-rifle POI error (right-and-low for clockwise cant with an upward zero). Zeroing always solves un-canted (“zero level, fire canted”). NOTE: treats muzzle_angle as a sight-frame offset — the standard zero-then-fire usage; a raw gravity-frame launch angle would not rotate physically. 0.0 = level rifle (bit-identical to pre-cant behavior). (MBA-1286)

§sight_height: f64§sight_offset_lateral_m: f64

Lateral offset between the sight axis and the bore axis, meters (MBA-1396; offset-mounted optics): positive = the sight sits RIGHT of the bore, so the bore starts LEFT of the line of sight (initial lateral position z -= offset). When a zero is solved, a windage-zero convergence term of offset / zero_distance is added to azimuth_angle (see BallisticInputs::windage_zero_bias_rad) so the trajectory crosses the LOS laterally at the zero range — matching AB/JBM/Shooter, not a constant parallel offset. Without a zero solve (an explicit muzzle angle), only the physical displacement applies. Distinct from zero_poi_horizontal_m, which is an angular ZERO-STATE bias, not mount geometry. 0.0 (the default) is byte-identical to pre-MBA-1396 behavior.

§muzzle_height: f64§target_height: f64§zero_poi_vertical_m: f64

Deliberate vertical point-of-impact offset AT THE ZERO RANGE, meters (MBA-1359; Kestrel “zero height” semantics): positive = the rifle is deliberately zeroed to impact HIGH by this much at the zero distance. Applied POST-solve by calculate_and_set_zero_angle as a constant angular bias of zero_poi_vertical_m / zero_distance on the solved elevation — the zero trials themselves always solve perfect convergence, and the small-angle addition is identical in both zero target frames. 0.0 (the default) is byte-identical to pre-MBA-1359 behavior.

§zero_poi_horizontal_m: f64

Deliberate horizontal point-of-impact offset AT THE ZERO RANGE, meters (MBA-1359; Kestrel “zero offset” semantics): positive = impacts RIGHT by this much at the zero distance. Applied POST-solve as an azimuth bias of zero_poi_horizontal_m / zero_distance when a zero is solved — see BallisticInputs::windage_zero_bias_rad. 0.0 (the default) is neutral.

§ground_threshold: f64§altitude: f64§temperature: f64§pressure: f64§humidity: f64

Relative humidity as a FRACTION in [0, 1] (e.g. 0.5 = 50%). NOTE the scale differs from AtmosphericConditions::humidity, which is a PERCENT in [0, 100]. The atmosphere helpers (calculate_air_density_*) expect percent, so convert via BallisticInputs::humidity_percent before passing this value to them (MBA-722).

§latitude: Option<f64>§wind_speed: f64§wind_angle: f64§twist_rate: f64§is_twist_right: bool§caliber_inches: f64§weight_grains: f64§manufacturer: Option<String>§bullet_model: Option<String>§bullet_id: Option<String>§bullet_cluster: Option<usize>§use_rk4: bool§use_adaptive_rk45: bool§enable_advanced_effects: bool§enable_magnus: bool§enable_coriolis: bool§use_powder_sensitivity: bool§powder_temp_sensitivity: f64§powder_temp: f64§powder_temp_curve: Option<Vec<(f64, f64)>>

Optional measured powder-temperature -> muzzle-velocity curve, as (temperature_celsius, muzzle_velocity_m_s) points sorted ascending by temperature. When present it supersedes the linear powder_temp_sensitivity model: the muzzle velocity is interpolated from this table at the ambient temperature (clamped to the endpoints — no extrapolation beyond measured data). This is the data-driven, non-linear alternative to the constant slope.

§powder_curve_temp_c: Option<f64>

Temperature (Celsius) at which to interpolate powder_temp_curve — the POWDER temperature, which may differ from the ambient temperature (air). None uses temperature. Decouples the velocity lookup from the air-density temperature.

§tipoff_yaw: f64§tipoff_decay_distance: f64§cd_delta2: f64

Quadratic yaw-drag coefficient CD_delta2 (per rad^2, actual-Cd space) applied additively to the tip-off yaw: CD = CD0 + CD_delta2 * delta^2 (McCoy, Modern Exterior Ballistics). Literature values for spitzer rifle bullets run ~4-20 per rad^2 (7.62 M80 ~= 9.6); the default 7.5 is a documented mid-range constant. Only active when tipoff_yaw is nonzero (MBA-1227).

§use_bc_segments: bool

Enables velocity-keyed bc_segments_data. Explicit Mach-keyed bc_segments retain their legacy behavior and remain active when this flag is false.

An empty bc_segments_data is the same as None. With the flag on and no velocity ladder, every solver flies a non-empty Mach bc_segments table. Without one, TrajectorySolver and fast_trajectory::fast_integrate fly the scalar BC, while the RK45 kernel behind fast_integrate_with_segments / trajectory_integration::integrate_trajectory / derivatives::compute_derivatives auto-estimates a ladder when bc_segments is None (MBA-955, legacy opt-in).

§bc_segments: Option<Vec<(f64, f64)>>§bc_segments_data: Option<Vec<BCSegmentData>>§use_enhanced_spin_drift: bool§use_form_factor: bool

Legacy compatibility flag. Name-derived “form factors” are intentionally not multiplied into reference Cd when bc_value is already the retardation denominator (MBA-1184).

§enable_wind_shear: bool§wind_shear_model: String§enable_trajectory_sampling: bool§sample_interval: f64§drops_reference: DropsReference

Which plane sampled drop values are referenced to (MBA-1403). The default DropsReference::Los keeps the historical behavior (drop perpendicular to the line of sight) byte-identical; DropsReference::Target reports drop as vertical in the target plane — the LOS-perpendicular drop scaled by 1 / cos(shooting_angle) (JBM’s “target plane” checkbox) — and, when a non-zero target_height is supplied, slopes the sampler’s LOS datum toward it. This is an OUTPUT-mode toggle: the solved trajectory itself is unchanged, and zero-solve target_height semantics are untouched.

§enable_pitch_damping: bool§enable_precession_nutation: bool§enable_aerodynamic_jump: bool§use_cluster_bc: bool§custom_drag_table: Option<DragTable>

A caller-supplied Cd-vs-Mach curve that replaces the bc_type G-model curve at every drag site (MBA-940). It is used as-is: no transonic correction and no form factor is applied to it, and outside its Mach range the nearest end value is held. What the curve describes, and so what it is divided by, is decided by Self::custom_drag_reference:

  • false (the default): the projectile’s OWN drag coefficient, divided by its sectional density. bc_value and any BC segments are unused for drag. This is the only reading the CLI’s --drag-table, the WASM terminal, the array FFI and saved profiles have, and solve-json v1’s kind: "projectile".
  • true: a REFERENCE curve, such as an airgun pellet law, that the BCs were measured against, divided by the resolved BC exactly as a built-in model’s curve is.

See Self::custom_drag_denominator.

§cd_scale: f64

Whole-curve multiplier applied to the custom deck’s interpolated Cd (MBA-1356): Cd_used = table.interpolate(mach) * cd_scale. Meaningful only alongside custom_drag_table — it is read at the three custom-deck interpolation sites in cli_api.rs/derivatives.rs/fast_trajectory.rs and left untouched on the standard G-model/BC path (those users true their drag via --bc-adjustment instead; scaling a G-model’s reference table too would double-count). It multiplies the curve before the division, under either reading of Self::custom_drag_reference. solve-json v1’s kind: "reference" table without a BC ladder is installed as the own-curve path with cd_scale = SD / BC, which flies Cd_ref / BC; with a ladder it is installed with custom_drag_reference set and cd_scale = 1.0 instead, since one whole-curve scale cannot carry a BC that changes from band to band. Default 1.0 is neutral (byte-identical to the pre-MBA-1356 behavior). Validated finite and > 0 by validate_for_solve.

§custom_drag_reference: bool

Whether custom_drag_table is a REFERENCE curve that the BCs were measured against (true), rather than the projectile’s own Cd (false, the default). Inert without a table.

When set, the drag sites in cli_api.rs, derivatives.rs and fast_trajectory.rs divide the table’s Cd (times cd_scale) by the BC each of them has already resolved for the current speed, exactly as they divide a built-in model’s Cd: a velocity ladder’s band BC (bc_segments_data under use_bc_segments, selected and smoothstep-blended by velocity_segment_bc), a Mach-keyed bc_segments BC, or the scalar bc_value in an interior gap or without a ladder. The BC matters again on this path, so validate_for_solve requires a finite positive bc_value, and an ArmyStandardMetro bc_reference_standard is converted exactly as it is for a built-in model.

solve-json v1 sets it for a kind: "reference" projectile.drag_table sent with a projectile.bc_segments ladder; no other front end sets it. Every path that copies a table between input structs must carry it alongside cd_scale (TrajectoryParams::custom_drag_reference): dropped beside cd_scale = 1.0, it would fly the reference curve as the projectile’s own Cd over sectional density, wrong by the projectile’s whole form factor (the MBA-1356 dropped-field class).

§bc_type_str: Option<String>

Implementations§

Source§

impl BallisticInputs

Source

pub fn humidity_percent(&self) -> f64

humidity as a PERCENT in [0, 100], clamped — the scale the atmosphere density helpers expect. Centralizes the 0–1 → 0–100 conversion so callers don’t re-derive it (and can’t accidentally feed the raw 0–1 fraction as a percentage). See the field doc on BallisticInputs::humidity (MBA-722).

Source

pub fn windage_zero_bias_rad(&self, zero_distance_m: f64) -> f64

Azimuth bias (radians) a zero solved at zero_distance_m applies to the launch direction. Two independent terms share this one convergence point:

  • MBA-1359 — the deliberate horizontal POI offset at the zero range (zero_poi_horizontal_m), an angular zero-state bias;
  • MBA-1396 — the lateral sight-mount offset (sight_offset_lateral_m): the bore starts offset left of the LOS (see initial_position), so the windage zero steers offset / zero_distance right to cross the LOS at the zero range.

calculate_and_set_zero_angle applies this to its OWN solver’s azimuth_angle; callers that copy a solved zero angle onto separate flight inputs (the CLI/WASM auto-zero paths) must add this to their flight azimuth_angle themselves — the returned elevation angle cannot carry it. Returns exactly 0.0 when both offsets are 0.0 or zero_distance_m is not positive, so default inputs stay byte-identical.

Source

pub fn sectional_density_lb_in2(&self) -> Option<f64>

Sectional density in lb/in²: weight_grains / 7000 / diameter_in².

Derived from the imperial mirror fields (weight_grains / caliber_inches), falling back to the SI bullet_mass (kg) / bullet_diameter (meters) for SI-only callers (mirrors the fallbacks in derivatives.rs). None when neither source is usable.

Source

pub fn custom_drag_denominator(&self, resolved_bc: f64) -> f64

Retardation denominator to use when custom_drag_table is active.

resolved_bc is the BC the calling drag site has already resolved for the current speed, by the same precedence it applies to a built-in model: a velocity ladder’s band BC, else a Mach-segment BC, else the scalar bc_value.

  • Reference curve (Self::custom_drag_reference): returns resolved_bc, the very denominator a built-in model divides by, so the table flies Cd_ref / BC and a BC ladder’s band BCs reach it.
  • The projectile’s own curve (the default): the table supplies the projectile’s ACTUAL drag coefficient, so the point-mass retardation formula must divide it by the projectile’s SECTIONAL DENSITY (lb/in²), not by a ballistic coefficient: BC = SD / i (form factor i vs the reference projectile), and with the projectile’s own curve i == 1, so Cd_own / SD == Cd_ref / BC. Dividing the curve’s Cd by bc_value made custom-table trajectories wrongly scale with whatever BC happened to be set. Falls back to resolved_bc (with a one-time stderr warning) when mass/diameter are unavailable, so degenerate inputs degrade to the old behavior instead of panicking.
Source

pub fn bc_reference_standard_inert_warning(&self) -> Option<&'static str>

Whether a declared bc_reference_standard is inert on this configuration (MBA-1365), and if so, the message explaining why.

A custom drag table (custom_drag_table) flown as the projectile’s own curve supplies its actual Cd and divides by sectional density, not by a BC value (see custom_drag_denominator), so an ArmyStandardMetro reference has no physical effect once such a table is active. A table flown as a reference curve (custom_drag_reference) divides by the BC like a built-in model, so the conversion is meaningful there and this returns None. Pure and side-effect-free — same shape as main.rs’s adjustment_unit_noop_warning (MBA-1414) — so each surface decides how to surface it: the native CLI prints it to stderr once per run, while the WASM browser terminal (no visible stderr) splices it into its table-output text instead.

Source

pub fn normalize_for_solve(&mut self)

Apply every input-conditioning step integration requires, exactly once (MBA-1415).

Every public entry point into integration must call this, not just TrajectorySolver::new. fast_trajectory::fast_integrate and fast_integrate_with_segments are pub and are called directly by the Python binding, so conditioning that lives only in the solver constructor is invisible to those consumers: the caller sets a field, gets no error, and the value is silently ignored. That exact shape has already cost this project twice — MBA-1296 (a dropped field that zeroed Coriolis in production) and the MBA-1356 review catch (cd_scale dropped by the segmented fast path). Adding a step here rather than at a call site is what keeps the next one from repeating it.

Idempotent, and it must stay that way: Monte Carlo builds a solver per sample, and the fast entry points may receive inputs that already passed through a solver. Each step below is either an absolute override (derived fields, powder-resolved velocity) or self-disarming (the BC conversion rewrites bc_reference_standard to the reference it just converted into, so a second call finds nothing to do). A step that scales a value in place without disarming itself would double-apply silently — do not add one.

Trait Implementations§

Source§

impl Clone for BallisticInputs

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for BallisticInputs

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for BallisticInputs

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.