A Point-Mass External-Ballistics Firing-Solution Engine for Long-Range Target Shooting
Tyler Crockett — Macdaddy4sure.ai
_AugmentedIntelligence v11.0 · Ballistics Subsystem (ShootingCore, ShootingELRCore)_
Abstract
We describe the external-ballistics firing-solution engine implemented in the
_AugmentedIntelligence runtime for the long-range target-shooting disciplines
(F-Class, PRS, benchrest, and extreme-long-range steel). The engine integrates a
point-mass trajectory under a tabulated G1/G7 drag law and a standard-atmosphere
density model to produce elevation and windage corrections, time of flight, and
retained velocity and energy. For extreme ranges it augments the point-mass core
with the deterministic secondary effects that dominate beyond ~1000 yd —
gyroscopic (spin) drift, Coriolis and Eötvös deflection, aerodynamic jump, and
atmospheric density altitude — and provides a Monte-Carlo uncertainty model that
reports a probability of hit and an input-sensitivity (error) budget. We give the
governing equations, the numerical method, validation against a reference load,
and an explicit statement of the model’s limitations. **This is a marksmanship
training and planning aid; all computed dope must be verified against live fire.**
1. Introduction and scope
A firing solution is the set of sight corrections a shooter dials (or holds) to
place a projectile on a target at a known distance under known conditions. For
the target-shooting sports the relevant outputs are the elevation come-up and
wind hold, expressed in the shooter’s scope units (milliradians or minutes of
arc), together with supporting quantities — bullet drop, wind drift, time of
flight, and retained velocity and energy.
The physics is a classical initial-value problem: projectile motion under gravity
and aerodynamic drag. It is deterministic and well understood; the engineering
difficulty lies in (i) an accurate drag description, (ii) the secondary effects
that become first-order at long range, and (iii) the uncertainty in the inputs,
which at extreme range dominates the achievable precision. This paper documents
how the engine addresses each.
The engine deliberately targets known-distance, static-target shooting. It is
a calculator, not a fire-control system.
2. Coordinate system and problem statement
We integrate in the vertical plane containing the line of sight (LOS) — the
axis from the shooter’s eye through the scope to the aim point — with a lateral
axis for wind and spin effects. Let:
- s — distance traveled along the LOS (down-range),
- h — height of the projectile relative to the LOS (positive up),
- z — lateral offset (positive right).
The sight sits a distance H (sight height) above the bore, so the projectile
begins at h = −H. The bore is elevated above the LOS by a small launch angle
φ (determined by the zero, §7). The reported drop is h at the target
range; the come-up is the angle that must be added to the LOS to place the
bore such that h = 0 at that range.
3. Governing equations
3.1 Drag deceleration
For a point-mass projectile the aerodynamic drag produces a deceleration
anti-parallel to the velocity vector v relative to the air:
a_drag = ρ · C_D(M) · |v|² / (2 · B) [m/s²]
where ρ is air density, C_D(M) is the drag coefficient of the standard
reference projectile at Mach number M = |v|/c, and B is the ballistic
coefficient expressed as an SI areal density (kg/m²). This form folds the
projectile’s mass, diameter, and form factor into B, which is the shooter-known
quantity. The equivalence follows from the standard definition
B = m / (i · d²) and C_D,bullet = i · C_D,std, giving
a_drag = (π/8)·ρ·|v|²·C_D,std / B; absorbing the geometric constant into the
tabulated C_D and the unit conversion yields the expression above.
BC units. Shooters quote the G1 (or G7) BC in imperial lb/in². We convert
once at input:
B[kg/m²] = BC_imperial · 703.06957
3.2 Equations of motion
Decompose the velocity into along-LOS (v_s), perpendicular (v_h), and lateral
(v_z) components. With a crosswind w (positive from the left, §8), the
air-relative lateral velocity is v_rz = v_z − w, and `|v| = √(v_s² + v_h² +
v_rz²)`. The accelerations are:
a_s = −a_drag · (v_s / |v|)
a_h = −a_drag · (v_h / |v|) − g·cos(α)
a_z = −a_drag · (v_rz / |v|)
where g = 9.80665 m/s² and α is the look (incline) angle; the factor cos(α)
is the component of gravity perpendicular to the LOS (the “rifleman’s” correction
for uphill/downhill shots). Wind enters through v_rz, so lateral drift emerges
naturally from the integration rather than a closed-form add-on.
3.3 Auxiliary quantities
Speed of sound (m/s) from air temperature T_F (°F), with T_C in Celsius:
c = 331.3 · √(1 + T_C/273.15)
Muzzle/retained energy (ft·lb) from bullet weight w_gr (grains) and velocity
v_fps:
E = w_gr · v_fps² / 450240
Angular conversions (small-angle sight corrections): `1 rad = 3437.75 MOA =
1000 mil. The come-up and wind hold are atan2(|drop|, R)` and
atan2(drift, R) scaled to the shooter’s units, where R is the slant range.
4. Drag models
The engine ships two standard drag functions, tabulated as C_D versus Mach and
linearly interpolated:
- G1 — the classic flat-base reference projectile. Appropriate for
conventional bullets; the drag rises sharply through the transonic region and
peaks near Mach 1.3.
- G7 — a boat-tail, secant-ogive reference projectile. A markedly better
match for modern long, sleek match bullets, with correspondingly lower and
flatter C_D.
The choice of model must match the BC the shooter supplies (a bullet’s G7 BC is
numerically ~half its G1 BC). Selecting the correct reference is the single
largest fidelity lever short of a radar-measured custom drag curve.
5. Standard atmosphere
Air density is expressed as a ratio to the G1 standard metro condition
(59 °F, 29.92 inHg, sea level), because the tabulated C_D is referenced to that
standard:
ρ/ρ₀ = (P / 29.92) · (518.67 / (T_F + 459.67))
with pressure P in inHg. When only altitude is known, ICAO pressure altitude
supplies P. For field use we also report density altitude (DA), the single
number that captures the combined temperature/pressure/altitude effect on drag:
PA = (29.92 − P) · 1000 [ft, pressure altitude]
DA = PA + 118.8 · (T_F − (59 − 3.57·PA/1000))
Humidity is a small second-order effect and is neglected.
6. Numerical integration
The trajectory is advanced with a fixed-step semi-implicit (symplectic) Euler
scheme at Δt = 2×10⁻⁴ s. Velocities are updated from the accelerations, then
positions from the new velocities; this is stable and conserves the qualitative
structure of the motion far better than explicit Euler at the same step. At each
step the drag magnitude is re-evaluated at the current Mach number. When the
along-LOS coordinate first exceeds the target range, the solution (drop, drift,
time of flight, velocity) is linearly interpolated to the exact range so that
outputs are not quantized by the step size. Time of flight at extreme range is
5–10 s, so the small step is necessary to keep integrated error negligible.
7. Zeroing
A rifle is zeroed at a chosen range R₀ (commonly 100 yd): the shooter adjusts
the sight so the trajectory crosses the LOS at R₀. The engine solves for the
bore launch angle φ such that h(R₀) = 0 by bisection, exploiting the
monotonic dependence of h(R₀) on φ. All subsequent solutions integrate at the
fixed φ; the reported come-up at range R > R₀ is the additional elevation
needed beyond the zero.
8. Wind model
Wind is entered as a speed and a clock direction (the o’clock position the
wind blows from; 3 o’clock is a pure right-to-left crosswind). The crosswind
component driving lateral drift is
w = −W · sin(θ_clock), θ_clock = (clock/12)·2π
so a 9-o’clock wind (from the left) pushes the bullet right, a 3-o’clock wind
pushes left, and 12/6-o’clock (head/tail) winds produce no lateral drift. Because
w enters the air-relative velocity, drift accumulates through the full flight
rather than via a lag-time approximation.
9. Extreme-long-range corrections
Beyond ~1000 yd several effects that are negligible at short range become
first-order (feet, not inches). These are deterministic given their inputs and
are therefore computed, not learned or guessed. They are added to the point-mass
solution.
9.1 Gyroscopic stability (Miller)
The Miller formula estimates the gyroscopic stability factor S_g from bullet
mass m (gr), diameter d (in), length in calibers l = L/d, and twist in
calibers t = T/d, corrected for velocity and atmosphere:
S_g = [ 30·m / (t²·d³·l·(1+l²)) ] · (v/2800)^(1/3) · (T_R/518.67) · (29.92/P)
S_g < 1.4 flags marginal stability — a warning that the bullet may destabilize
as it decelerates through the transonic region.
9.2 Spin drift (Litz approximation)
A gyroscopically stabilized bullet precesses, drifting laterally in the direction
of barrel twist. We use Litz’s empirical form (inches; positive right for
right-hand twist):
SD = 1.25 · (S_g + 1.2) · TOF^1.83
9.3 Coriolis and Eötvös deflection
Earth’s rotation deflects the long-flight-time projectile. With rotation rate
Ω = 7.2921×10⁻⁵ rad/s, latitude L, azimuth of fire A (0 = north, 90 = east),
range R, and time of flight T:
Horizontal (right in N. hemisphere): Δz = Ω · R · T · sin(L)
Vertical (Eötvös; high shooting east): Δh = Ω · R · T · cos(L) · sin(A)
The horizontal term is azimuth-independent; the vertical term makes east-bound
shots print high and west-bound shots low.
9.4 Aerodynamic jump
A crosswind imparts a small vertical deflection at launch (angular, roughly
constant with range), modeled as ≈ 0.01 · S_g · W_cross (mil). It is small but
non-negligible at ELR and, unlike wind drift, acts vertically.
9.5 Powder-temperature velocity shift
Muzzle velocity varies with propellant temperature. Given a per-load sensitivity
k (fps/°F) and a reference (v₀, T₀), the corrected velocity is
v = v₀ + k·(T − T₀). At extreme range a 10 fps error is a foot or more of
vertical impact shift, so this correction is material.
10. Uncertainty quantification
At long range the precision of a firing solution is limited less by model
fidelity than by the uncertainty of its inputs — principally wind, then muzzle
velocity, then range. The engine therefore provides a Monte-Carlo dispersion
model. The mean shot is zeroed once; then N samples perturb the uncertain inputs
(muzzle velocity σ_v, wind σ_w, range σ_R, BC σ_BC) by independent Gaussians and
re-integrate at the fixed launch angle. The engine reports:
- Probability of hit (P_h) — the fraction of samples landing inside the target
box;
- the dispersion (standard deviation of vertical and horizontal miss);
- an input-sensitivity budget — impact shift per 10 fps of MV, per mph of
wind, and per yard of range error, computed by finite difference.
This reframes the extreme-range problem honestly: the output is not a single
number to dial but a cone, and the sensitivity budget shows which input
dominates it (almost always wind).
11. Truing
A generic solution is made rifle-specific by truing to observed impacts. Given
a measured drop at a known range, the engine solves (by bisection on velocity) for
the muzzle velocity that reproduces it — the first and most effective rung of
personalization. A learned residual model (a small neural network trained on a
shot log, confined to the observed envelope) is the natural next step for the
subsonic-drag error a single BC cannot capture; it is intentionally physics-anchored
so it corrects only what theory misses and never extrapolates.
12. Solution method: the _AugmentedIntelligence firing-solution pipeline
The preceding sections define the individual physical models; this section
describes how the engine composes them into a single firing solution, and the
design philosophy behind that composition. A solve is layered by order of trust:
a deterministic physics backbone first, then an honest uncertainty estimate, then
optional data-driven personalization — never the reverse.
Step 1 — Assemble the inputs. A solve takes a Shot (muzzle velocity, BC and
its drag model, bullet weight, sight height, zero range, temperature, pressure,
wind speed and clock, look angle) and, for long range, a Rifle (diameter,
length, twist rate and hand, shooter latitude and firing azimuth, and the scope’s
click value). These are the only quantities the shooter must supply.
Step 2 — Establish the atmosphere. From temperature and pressure the engine
computes the air-density ratio (§5) and the speed of sound (§3.3). The density
ratio scales the drag force; the speed of sound converts every velocity to a Mach
number so the correct point on the drag curve is used. This is done once and held
for the trajectory.
Step 3 — Zero the rifle (`solveZeroAngle`). Before any range solution the
engine finds the bore launch angle φ that puts the trajectory on the line of
sight at the zero range, by bisection (§7). This encodes the rifle’s actual
sight-in and is the reference against which all come-ups are reported.
Step 4 — Integrate the trajectory (`integrate`). Launching at φ, the engine
steps the point-mass equations of motion (§3.2) with the semi-implicit Euler
scheme (§6). At every step it re-evaluates the Mach number, looks up C_D from the
selected G1 or G7 table, and applies the drag, gravity-perpendicular, and wind
accelerations. When the down-range coordinate first passes the target range it
interpolates drop, drift, time of flight, and velocity to the exact distance.
This single routine yields the elevation, windage, TOF, and retained
velocity/energy — the core of the solution.
Step 5 — Convert to sight units. Drop and drift are converted from linear
offset to the shooter’s angular units — milliradians or MOA — via atan2, and
then to turret clicks using the scope’s click value. This is what the shooter
actually dials.
Step 6 — Apply the deterministic long-range corrections (`solveFull`). For
extreme range the engine adds the effects of §9 that are computable from the
inputs: it evaluates the Miller stability factor S_g, then adds Litz spin drift,
Coriolis (horizontal) and Eötvös (vertical) deflection, and aerodynamic jump, and
folds them into the total elevation and windage. It raises a transonic/stability
flag when S_g is marginal or the bullet has slowed below Mach 1.2. Crucially,
these are added analytically to the point-mass result rather than learned or
guessed — the engine computes everything theory can determine.
Step 7 — Quantify the uncertainty (`monteCarlo`). Recognizing that at long
range the limiting factor is input uncertainty, not model form, the engine zeroes
once and then re-integrates the trajectory hundreds of times with the muzzle
velocity, wind, range, and BC perturbed by their standard deviations. It returns a
probability of hit for the target, the dispersion ellipse, and a sensitivity
budget. The firing “solution” is thus delivered honestly as a *center plus a
cone*, with the sensitivity budget naming the dominant error (typically wind).
Step 8 — Personalize by truing (`trueVelocity`). Finally, the generic solution
is made rifle-specific: from an observed drop at a known range the engine solves
for the muzzle velocity that reproduces it, shifting the whole trajectory to match
the shooter’s actual dope. A physics-anchored learned residual (§11) is the
optional next layer for the subsonic-drag error a single BC cannot express.
Design principle. The pipeline embodies one rule: *compute what is knowable,
learn only the irreducible residual, and never present a point estimate where a
distribution is honest.* Steps 1–6 are pure, deterministic physics; step 7 makes
the residual uncertainty explicit; step 8 closes the loop with the shooter’s own
data. Deterministic effects (Coriolis, spin drift, stability) are never delegated
to a model — they are derived — so any learned component is confined to the small,
genuinely uncertain part of the problem and is barred from extrapolating outside
the data that trained it. This is what makes the solution both physically faithful
and trustworthy at the ranges where naïve models quietly fail.
13. Validation
The engine is exercised by an automated behavioural test suite
(suite_shooting.cpp, suite_shootingelr.cpp) covering unit conversions, the
atmosphere model, drag tables, monotonicity properties, and a reference load. For
a **.308 Winchester, 175 gr SMK, G1 BC 0.505, 2600 fps, 1.9 in sight height,
100 yd zero, standard conditions**, the engine produces:
| Range (yd) | Come-up (mil) | Retained V (fps) | TOF (s) | Spin drift (in) | Coriolis H (in) |
| 100 | 0.00 | 2456 | — | — | — |
| 1000 | 10.05 | 1349 | 1.61 | 10.7 | 3.0 |
with S_g = 2.40 (stable) and, under a Monte-Carlo model (σ_v = 10 fps, σ_w =
2 mph, σ_R = 3 yd), a horizontal dispersion (15.7 in) that substantially exceeds
the vertical (5.1 in) — correctly reproducing the field truth that **wind is the
dominant error source**. Velocity truing recovers a synthetic reference muzzle
velocity to within the test tolerance.
The come-up and retained velocity are in the expected range for this load; the
model is slightly optimistic at extreme range (§14).
14. Limitations
- Single flat BC. The point-mass core uses one BC per drag model. Real BC
degrades below Mach ~1.2, so the model under-predicts drag transonically and is
optimistic at extreme range. G7 selection and, ideally, a banded or
radar-measured custom drag curve reduce this.
- Point-mass, not 6-DOF. Spin drift and aerodynamic jump are empirical
approximations, not a full rigid-body (epicyclic) solution. Yaw-of-repose and
dynamic-stability transitions are not modeled.
- Single-layer atmosphere and wind. One density and one wind value are used;
at ELR both vary appreciably over the trajectory’s tens-of-feet apex.
- Transonic dispersion is physical, not modeled. As a bullet decelerates
through Mach 1 it may lose dynamic stability and disperse unpredictably; no
solver overcomes an unstable load.
- Estimates, not guarantees. All outputs are planning estimates. **Verified
live-fire dope always supersedes the model.**
15. Implementation notes
The physics is implemented as dependency-free, header-only C++ cores
(ShootingCore.hpp, ShootingELRCore.hpp) that are unit-tested in isolation, with
a thin typed-command layer (shoot …) and Lua bindings for the host runtime. A
companion MySQL schema (sql/shooting_schema.sql) logs profiles, the dope diary,
computed solutions, chronograph strings, groups, and truing history — the dataset
that feeds the truing and residual-learning workflow.
References
- R. L. McCoy, *Modern Exterior Ballistics: The Launch and Flight Dynamics of
Symmetric Projectiles*, 2nd ed., Schiffer, 2012.
- B. Litz, Applied Ballistics for Long Range Shooting, 3rd ed., Applied
Ballistics LLC, 2015.
- D. Miller, “A New Rule for Estimating Rifling Twist,” Precision Shooting,
March 2005 (gyroscopic stability formula).
- A. J. Pejsa, Modern Practical Ballistics, 2nd ed., 1991.
- Ballistics standard reference drag functions (G1, G7), derived from the
Gâvre/Ingalls and BRL/ARDC projectile drag measurements.
- E. Eötvös, on the latitude/azimuth dependence of apparent vertical
acceleration for east–west motion (Eötvös effect).
*Prepared as internal technical documentation for the _AugmentedIntelligence
ballistics subsystem. For target-shooting sport and educational use.*
Filed under: Uncategorized - @ July 18, 2026 6:33 am