|
lob 0.11.0
Exterior ballistics library — API + technical reference
|
Drag is tabulated as Cd(Mach). The solver evaluates it hundreds of times per trajectory, so access must be branch-light and monotonicity-preserving. lob stores drag as cubic Hermite splines with PCHIP (Piecewise Cubic Hermite Interpolating Polynomial, Fritsch–Carlson) tangents.
For each interval [x0,x1] with values y0,y1 and tangents m0,m1 (source/splines.hpp):
Tangents (source/splines.hpp):
n==2 or at an endpoint → secant of the first/last span.sec_prev·sec_next ≤ 0 → 0 (prevents overshoot).which preserves monotonicity for monotonic data.
kKnotCount = 16, kSegmentCount = 15, kCoefsSize = 60 (source/splines.hpp). Knots span Mach 0 to 5.0:
Chosen to keep the worst-case G1/G7 error below 5e-3 across a 5000-point truth grid interpolated from dragtable (test/source/splines_test.cpp, SplineOptimization::BaselineAccuracyBudget). Knot placement is static and constexpr; the G* coefficient tables kG1Coefs…kG8Coefs are built at compile time (source/splines.hpp).
Build (source/splines.hpp) projects an arbitrary input table onto the knots by evaluating the PCHIP interpolant of that table at each knot, then fitting a Hermite segment per knot interval via Segment. Hence any input grid can be resampled without re-optimizing knot locations.
CurveView (source/splines.hpp) / Cursor holds pointers to knots and coefficients and a cached segment index idx_:
Clamp(m) to [knots[0], knots[N−1]].Seek(m) walks idx_ forward/backward linearly — O(1) for monotonic Mach (projectiles only decelerate, so the solver walks downward except for rare transonic searches).Eval(m) = PolyVal(c + 4·idx_, m − knots[idx_])Deriv(m) = PolyDeriv(c + 4·idx_, m − knots[idx_])Both are constexpr-friendly and allocate nothing. The 60 floats are 240 bytes of contiguous storage.
Custom tables (source/lob_builder.cpp) produce coefficients via the same Build; BC bands use MakeRetardationCoefs + Merge (see BC/Velocity-Band Transformation).
Validation: test/source/splines_test.cpp checks secants/tangents, Hermite endpoint/tangent preservation, binary-search FindInterval, monotonic seeks, derivative correctness and the 5e-3 baseline budget.
Linear interpolation (dragtable::LobLerp in source/tables.hpp) is kept for reference but is slower to validate for Cd integrals; the Hermite form evaluates with 7 FLOPs and preserves C¹ continuity, which the benchmark benchmark/loblerp.cpp shows matters for tight loops.