Project APEX

by 434 Aerospace

Technical Reference

Physics Notes

The complete description of every model inside Project APEX — stability, drag, compressibility, numerical integration, and atmosphere.

Barrowman Stability 7-Component Drag Prandtl-Glauert Ackeret Wave Drag RK4 Integration ISA Atmosphere
Contents
📐
Overview
What APEX models and how it fits together

Project APEX solves a one-dimensional vertical flight from launch to apogee using a physics-based model with no lookup tables for the core dynamics. Every quantity — drag coefficient, stability margin, air density, speed of sound — is computed analytically at each timestep from the current state of the rocket and the atmosphere.

The model has three main layers. The aerodynamics layer computes the centre of pressure (CP), the drag coefficient (Cd), and the lift-curve slope from the rocket's geometry. The flight integration layer uses those forces together with the motor thrust curve to propagate position and velocity forward in time. The atmosphere layer supplies air density, dynamic viscosity, and speed of sound at each altitude, updated at every step.

All internal calculations use SI units throughout. Inputs entered in imperial units are converted before the simulation runs and converted back for display.

LayerOutputMethod
StabilityXcp, CNα, static marginBarrowman (1966) + PG correction
DragTotal Cd (7 components)Analytical, Re-based skin friction
CompressibilityKPG correction factorPG subsonic, Ackeret supersonic, linear blend transonic
IntegrationAltitude, velocity vs time4th-order Runge-Kutta, dt = 0.05 s
Atmosphereρ, T, P, a, μISA 1976, 3 layers to 32 km
🎯
Stability Model
Barrowman equations with Mach-dependent CP correction

Barrowman CP 1966

The centre of pressure is calculated using the Barrowman method, which treats the rocket as a body of revolution and sums the normal-force contributions of the nosecone and fins separately. The CP is the weighted average of those contributions, weighted by their respective normal-force slope coefficients (CNα).

Xcp = (CNα_nose · Xcp_nose + CNα_fins · Xcp_fins) / (CNα_nose + CNα_fins)

All distances are measured from the nose tip. A larger Xcp means the CP is further aft, which increases the stability margin.

Normal-Force Coefficients

Nosecone — CNα_nose = 2.0

For a slender body of revolution, the nosecone normal-force slope is 2.0 regardless of shape. The shape affects the CP location of the nose contribution:

Nose shapeXcp_nose (from tip)
Cone2/3 · Ln
Ogive0.466 · Ln
Von Kármán0.437 · Ln
Parabolic0.500 · Ln

Fins — CNα_fins

The fin normal-force slope uses the Barrowman trapezoidal fin formula with a body-interference factor K:

K = 1 + r / (s + r) lm = √(s² + sb²) sb = sweepLen + (CT − CR)/2 CNα_fins = K · (4·N·(s/d)²) / (1 + √(1 + (2·lm / (CR + CT))²))

The fin CP location:

Xcp_fins = Xf + (lm/3)·(CR + 2·CT)/(CR + CT) + (1/6)·(CR + CT − CR·CT/(CR+CT))

Dynamic CP and Static Margin

APEX recomputes CP at every recorded timestep using the Prandtl-Glauert correction factor:

CNα_fins_effective = CNα_fins · KPG(Mach)

The static margin in calibers (body diameters):

Static Margin = (Xcp − Xcg) / d

A margin of 1–2 calibers is the conventional HPR target. APEX applies an increasing drag penalty for unstable rockets — ramping from 1× at 0 calibers to up to 10× at −2 calibers. During the burn, CG moves forward as propellant is consumed:

Xcg(t) = (m_launch · Xcg0 − m_burned(t) · Xcg_motor) / m_current(t)
Note: APEX requires the user to enter the CG position directly. Unlike OpenRocket, APEX does not compute CG from component masses. The entered value is used as the initial (full propellant) CG.
💨
Drag Model
Prandtl-Glauert, transonic blend, Ackeret

The total drag coefficient is the sum of seven analytically computed terms, recalculated at every simulation step. The total drag force is:

F_drag = 0.5 · ρ · v² · Cd_total · A_ref · Cd_Scale
ComponentSymbolRegime
Skin friction (body)Cd_bodyAll speeds
Nose pressure dragCd_noseAll speeds
Base dragCd_baseAll speeds
Fin friction + profileCd_fin_frictionAll speeds
Fin LE/TE pressureCd_fin_LE / TEAll speeds
Fin interferenceCd_fin_interferenceAll speeds
Fin wave dragCd_fin_waveM > 0.75
Body shoulder wave dragCd_wave0.82 < M < 1.25

Skin Friction

Body skin friction uses the Prandtl-Schlichting turbulent flat-plate formula with a Schlichting roughness lower bound, applied to the wetted surface area of the body:

Re = ρ · v · L / μ // Reynolds number on body length Cf_smooth = 0.455 / (log₁₀(Re))²·&sup5;&sup8; // Prandtl-Schlichting turbulent Cf_rough = 0.032 · (ε / L)^0.2 // Schlichting fully-rough (ε = surface roughness) Cf = max(Cf_smooth, Cf_rough) Cd_body = Cf · (1 + 60/(L/d)³ + 0.0025·(L/d)) · (π·d·L) / A_ref

The roughness ε (in metres) sets a lower limit on skin friction; once the boundary layer is fully rough, increasing Reynolds number no longer reduces Cf.

Fin skin friction is computed separately at the fin chord Reynolds number, not the full body length Re. Fin chords are typically much shorter than the body, giving a substantially higher Cf than the body value:

Re_fin = Re · (c_mac / L) // Re at mean aerodynamic chord, not full body Cf_smooth_fin = 0.455 / (log₁₀(Re_fin))²·&sup5;&sup8; Cf_rough_fin = 0.032 · (ε_fin / c_mac)^0.2 // uses Fin Roughness and fin chord Cf_fin = max(Cf_smooth_fin, Cf_rough_fin) Cd_fin_friction = Cf_fin · finFF · (2 · N · A_fin_exposed) / A_ref

The Fin Roughness parameter (ε_fin) is independent of body roughness, allowing correct per-surface calibration — a painted carbon-fibre body (~20 µm) and polished aluminium fins (~0.5 µm) have very different Cf values.

Why use fin chord Re? Using the body length Re for fins underestimates fin skin friction by 40–60% on typical HPR airframes. The Schlichting roughness formula explicitly depends on the reference length — computing it at body length applies an artificially long averaging length to the fin, masking roughness-dominated friction.

Nose Pressure Drag

Nose pressure drag is shape-dependent and grows with Mach number via the Prandtl-Glauert compressibility correction. In the supersonic regime Ackeret theory takes over, with the correct 1/β (not 1/β²) dependence:

θ = atan(r / Ln) // half-angle of the nose cone β = √(M² − 1) // Prandtl-Glauert factor M ≤ 1.2 : Cd_nose = Cd_nose₀(shape) · KPG(M) M > 1.2 : Cd_nose = 2.1 · atan²(θ) · √0.44 / β // Ackeret, anchored at M=1.2

Pressure drag scales as the square of the flow deflection angle and falls off as 1/β as the rocket accelerates deeper into the supersonic regime. The constant √0.44 anchors the Ackeret value to the PG result at M = 1.2 for a continuous transition. A longer nose (larger Ln) reduces θ and therefore reduces wave drag — this is why HPR rockets favour 5:1 or 7:1 nose fineness ratios.

Base Drag

The rocket's blunt base creates a low-pressure wake. The model uses a Mach-dependent formula calibrated to match measured drag behaviour: low at rest, rising to a peak near M = 1, then decaying in the supersonic regime as the base flow changes character:

M < 1.0 : Cd_base = 0.025 + 0.165 · M² // subsonic: 0.025 at rest, 0.190 at M=1 M ≥ 1.0 : Cd_base = 0.19 / M^1.25 // supersonic: continuous at M=1, ~0.08 at M=2

The subsonic formula anchors at 0.025 at zero speed and rises quadratically to 0.190 at Mach 1. The supersonic formula is continuous at that boundary and decays with the M^1.25 exponent, correctly representing the gradual increase in base pressure recovery as the Mach number rises.

Fin Drag

LE / TE Pressure Drag and Kwave

Leading and trailing edge pressure drag depends on the fin cross-section profile. For bevelled profiles the subsonic LE drag follows linearised wedge theory — the same functional form as the Ackeret term but active at all speeds. The profile also sets Kwave for the supersonic regime:

f_le = LE bevel depth as fraction of chord // e.g. 0.25 for quarter-chord bevel Bevelled LE (subsonic): Cd_fin_LE = t_c² / f_le · (A_planform · N / A_ref) // deeper bevel → less drag Blunt LE (flat plate): Cd_fin_LE = 0.15 · t_c · (A_planform · N / A_ref)
Cross-sectionLE profileTE profileKwave (Ackeret)
Double wedgeSharpSharp4·t_c²
Quarter-chord bevelBevelledSharp2·t_c²/f_le
Hexagonal / LE bevelBevelledBevelled8·t_c²
Flat plate (default)BluntBlunt4·t_c

where t_c = fin thickness / root chord. For the quarter-chord bevel, the LE Bevel Depth (f_le) appears in both the subsonic and supersonic drag terms — a deeper bevel distributes the deflection over more chord, reducing the effective wedge angle and lowering drag at all speeds.

Fin Interference Drag

Where the fins attach to the body, the disturbed boundary layer produces additional drag:

Cd_fin_interference = 2 · Cf_fin · N · (t_fin · CR) / A_ref

Wave Drag

Wave drag is the dominant drag increase in the transonic and supersonic regimes, arising from three independent sources. For a full treatment see the blog post Wave Drag Explained.

Fin Wave Drag — Ackeret

M_eff = M · cos(sweep_angle) Cd_fin_wave = Kwave / √(max(M_eff² − 1, 1.0)) // M_eff > 1.0 Cd_fin_wave = Kwave · sin(π·(M_eff − 0.75)/0.5) // 0.75 < M_eff < 1.0 (build-up)

The clamping of the denominator to 1.0 regularises the Ackeret singularity at M_eff = 1. Swept fins maintain a lower M_eff than the freestream Mach number, delaying and reducing the wave drag onset.

Nosecone Wave Drag — Prandtl-Glauert / Ackeret

Nose wave drag grows via the PG correction below M = 0.8, blends linearly through transonic, and transitions to Ackeret above M = 1.2. See the Nose Pressure Drag section above for the formula.

Body Shoulder Transonic Wave Drag

At the nosecone-to-body junction a recompression shock exists only in the transonic band:

Cd_wave = 0.18 · sin(π·(M − 0.82)/0.43) · (d/Ln)^0.4 // 0.82 < M < 1.25 Cd_wave = 0 // otherwise

This term peaks near M = 1 and disappears once the flow is fully supersonic.

In the app: the Aerodynamics tab shows the Cd vs Mach curve with component breakdown, letting you see exactly which term is driving total drag at any Mach.
〰️
Compressibility Corrections
Prandtl-Glauert, transonic blend, Ackeret

As the rocket approaches and exceeds Mach 1, compressibility changes the pressure distribution and normal-force generation. APEX applies a single correction factor KPG that transitions continuously between three regimes:

M < 0.8 : KPG = 1 / √(1 − M²) // Prandtl-Glauert subsonic M > 1.2 : KPG = 1 / √(M² − 1) // Ackeret supersonic 0.8–1.2 : KPG = linear blend // avoids M=1 singularity

The PG correction at M = 0.8 evaluates to approximately 1.67 — meaning fin normal-force authority is 67% higher than the incompressible value. At M = 1.2 the Ackeret result is approximately 1.51. The linear transonic blend connects these continuously.

This correction is applied to the fin normal-force slope (CNα_fins) before computing CP, and also feeds into the nose pressure drag model. As fins gain authority approaching M = 1, CP moves aft, increasing stability margin. In the fully supersonic regime, fin authority drops off and CP shifts forward.

Note: The Prandtl-Glauert correction is a linearised theory and its accuracy degrades close to M = 1. The transonic blend used in APEX is a pragmatic engineering approximation. For flights that spend significant time at M = 0.9–1.1, treat the CP prediction in that range as approximate.
Flight Integration
Fourth-order Runge-Kutta, dt = 0.05 s

The flight is solved as a system of two first-order ODEs — altitude (dh/dt = v) and velocity (dv/dt = net acceleration) — using the fourth-order Runge-Kutta method (RK4) with a fixed timestep of 50 ms.

k1 = deriv(h, v, t ) k2 = deriv(h+k1·dt/2, v+k1·dt/2, t+dt/2 ) k3 = deriv(h+k2·dt/2, v+k2·dt/2, t+dt/2 ) k4 = deriv(h+k3·dt, v+k3·dt, t+dt ) dh = (k1.dh + 2·k2.dh + 2·k3.dh + k4.dh) / 6 dv = (k1.dv + 2·k2.dv + 2·k3.dv + k4.dv) / 6

Forces at each step

Each call to the derivative function performs a full atmosphere lookup, computes the current Mach and Reynolds number, evaluates all seven drag components, reads the thrust from the interpolated thrust curve, and returns net acceleration:

a_net = (Thrust(t) − F_drag(h,v,t)) / m(t) − g

Mass decreases linearly through the burn phase as propellant is depleted. After burnout, mass is constant at the dry mass. Gravity: g = 9.80665 m/s².

Timestep and output resolution

The integrator runs at 50 ms per step internally. Output is recorded every 100 ms (every other integration step) to keep the data arrays at a manageable size for charting. For a typical 30-second flight this produces approximately 300 data points per output channel.

Why RK4? A simple Euler integration at 50 ms introduces meaningful energy error over a multi-second burn. RK4 is fourth-order accurate — local error scales as dt5 — making it accurate enough that halving the timestep changes the apogee prediction by less than 0.1% for typical HPR flights.
🌡️
Atmosphere Model
ICAO International Standard Atmosphere (ISA), 3 layers

Air density, temperature, pressure, speed of sound, and dynamic viscosity are computed from altitude using the International Standard Atmosphere (ISA 1976), covering three layers up to 32 km.

LayerAltitude rangeLapse rateBase temperature
Troposphere0 – 11 km−6.5 K/km288.15 K (15 °C)
Tropopause11 – 20 km0 K/km (isothermal)216.65 K (−56.5 °C)
Lower stratosphere20 – 32 km0 K/km (isothermal)216.65 K
T(h) = T0 − L·h // T0 = 288.15 K, L = 0.0065 K/m P(h) = P0 · (T(h)/T0)^(g/L·R) // P0 = 101325 Pa, R = 287.05 J/kg·K ρ(h) = P(h) / (R·T(h)) a(h) = √(γ · R · T) // γ = 1.4 μ(h) = 1.458×10−&sup6; · T^1.5 / (T + 110.4) // Sutherland's law

All five quantities are updated at every integration step. The launch altitude input allows the simulation to start at field elevation, important for high-desert launch sites where sea-level density assumptions would overestimate drag.

Note: ISA is a standardised atmosphere, not a forecast. Actual air density on launch day will differ from ISA depending on temperature, humidity, and barometric pressure. For most HPR flights the difference is small (1–3% apogee error), but users at very high-altitude or extreme-temperature launch sites should be aware of this limitation.
📊
Drag Calibration
Matching the model to measured flight data

With correct physics inputs — accurate surface roughness values for body and fins, the right fin cross-section profile, and a well-measured geometry — APEX's analytical drag model typically matches real flight data within 3–5% apogee error without any fudge factor. The Cd Scale Factor (default 1.0) exists as a fine-tuning tool, but should not be needed to achieve a good baseline prediction.

Cd_effective = Cd_computed · Cd_Scale_Factor
Validation result: A Balls rocket on an L1050 motor simulated to 17,782 ft with Cd Scale = 1.0 (body roughness 20 µm, fin roughness 0.5 µm, quarter-chord bevel fins). Actual flight: 17,147 ft — 3.7% error. OpenRocket predicted 18,263 ft — 6.5% error. APEX matched the real flight more closely than OpenRocket with no scale factor adjustment.

Choosing the right surface roughness

Surface roughness is the most influential calibration input. The Body Roughness and Fin Roughness parameters should match the actual finish of each surface:

Surface finishRoughness (µm)
Polished metal / bare carbon fibre0.5 – 2
Smooth paint (glossy finish)5 – 20
Matte / spray paint30 – 60
Rough fibreglass100 – 300

Body roughness 20 µm and fin roughness 0.5 µm is a good starting point for a painted airframe with polished aluminium fins. Note that OpenRocket sets roughness per component in the General tab of the component editor (not the Appearance tab).

Back-calculating Cd from flight data

When a Featherweight Blue Raven altimeter CSV is loaded into APEX, the Aerodynamics tab back-calculates actual Cd versus Mach from the coast phase — the interval between burnout and apogee when thrust is zero, making drag the only unknown:

F_drag(t) = m · (g + a_measured(t)) // coast phase: thrust = 0 Cd(t) = F_drag(t) / (0.5 · ρ(h) · v² · A_ref)

This produces a measured Cd vs Mach curve plotted alongside the model prediction. If the curves are offset, first check that surface roughness and fin profile parameters reflect the actual airframe — a persistent offset usually means the geometry or roughness inputs are wrong, not that the scale factor needs adjustment.

Practical workflow: fly the rocket on a well-characterised motor, load the altimeter CSV, and compare the back-calculated Cd to the APEX prediction. Tune surface roughness values to match the curve shape and magnitude. If a small residual offset remains, a Cd Scale Factor of 0.95–1.05 is a reasonable final trim. Save the config — future motor swap predictions are then grounded in real flight data.

OpenRocket Cd import

APEX can also import an OpenRocket Cd CSV (exported from OR's drag breakdown) as a visual reference overlay on the Aerodynamics chart. The simulation always uses the APEX computed Cd — the OR import is a visual comparison only, useful for identifying where the two models diverge.