Buffet Boundary Testing (flight-test-operations/envelope/buffet-boundary-testing)
Use when the task is the buffet boundary flight test of a transport
airplane: scheduling pull-up and steady-turn points across a Mach sweep
at constant altitude, detecting buffet onset from the vertical
accelerometer RMS rise above threshold, converting the onset load factor
to the boundary lift coefficient, and scoring the buffet margin at the
cruise condition against a maneuver buffet target. This leaf implements
the standard RMS-based onset detection and boundary fitting in pure
Python, stdlib only. It pairs with flight-test-operations/envelope/
load-factor-envelope for the V-n context of the tested load factors,
envelope-expansion for the expansion program that precedes the boundary
probe, and flight-test-operations/flutter/flutter-testing for the other
high speed clearance boundary. The RMS floor, RMS rise per g and the
0.02 g onset threshold below are documented typical engineering
criteria, not regulation values; FAR/CS-25 are referenced for buffet and
vibration context by name and paraphrase only.
Domain quick reference
- Test gross weight: W = m * g0, g0 = 9.80665 m/s2. Onset load factor
n_onset is in g, so the lift at onset is n_onset * W.
- ISA state at altitude: T = 288.15 - 0.0065 * h below 11000 m
(216.65 K above), P from the 5.25588 exponent law or the isothermal
stratosphere pressure, rho = P / (287.05 * T).
- Dynamic pressure: q = 0.5 * rho * V^2 with V = M * a and a =
sqrt(1.4 * 287.05 * T), the ISA speed of sound.
- Buffet-onset detection: with samples of (load factor n, vertical
accelerometer RMS) sorted by n and non-decreasing in RMS, the onset
load factor is the linear interpolation of the first crossing of the
onset RMS threshold between two consecutive samples. The documented
typical criteria are a 0.02 g onset RMS threshold, a 0.004 g RMS
floor below onset, and a 0.4 g RMS rise per g of load factor above
onset; they are engineering criteria, not regulation values.
- Boundary lift coefficient at one Mach: cl_buf = n_onset * W /
(q * S) with S the reference wing area.
- Boundary line fit: cl_buf = slope * M + intercept by least squares
(local 2x2 normal equations) over the tested Mach band.
- Buffet margin at cruise: n_buf_cruise = cl_buf(M_cr) * q(M_cr) * S /
W, margin_n = n_buf_cruise - target_n; verdict
"buffet-margin-pass" when margin_n >= 0.0, else "buffet-margin-fail".
- Units are SI throughout: kg, m, Pa, kg/m3, m/s; load factors in g.
Workflow
- Fix the test point schedule: weight_kg, wing_area_m2, altitude_m,
the mach_list sweep and the load factor samples per Mach
(rms_table), plus the cruise_mach where the margin is scored.
- Get the atmosphere with isa_state, then the dynamic pressure q per
Mach with dynamic_pressure.
- Detect the onset load factor per Mach with onset_detect on the
measured (n, rms_g) samples; the detector interpolates the first
RMS crossing of onset_rms_g.
- Convert each onset load factor to the boundary lift coefficient
with boundary_lift_coefficient.
- Fit the boundary line over the Mach band with fit_boundary_line,
passing cruise_mach so cl_at_cruise is evaluated; omit cruise_mach
when only the line is wanted (cl_at_cruise is then None).
- Score the cruise condition: n_buf_cruise from the line at
cruise_mach, the margin with buffet_margin against the maneuver
buffet target, and the verdict.
- Run the whole point schedule through analyze with one inputs dict;
it returns the per-Mach q, onset_n and cl_buf points, the fit, the
cruise reduction and the verdict.
- Confirm the deterministic checks with the contract test
scripts/test_buffet_boundary_testing.py.
Worked example
Transport at W = 195000 kg (W = 1912297 N), S = 360.0 m2, altitude
10668 m, Mach sweep [0.74, 0.76, 0.78, 0.80, 0.82], pull-ups with
load factor samples every 0.1 g from 1.0 to 2.2. The measured RMS
fixture (built in the test, unknown to the module) follows rms(n) =
0.004 g below the model onset n_onset(M) = 1.90 - 1.50 * (M - 0.74),
then rises 0.4 g per g above it.
- ISA at 10668 m: T = 218.81 K, P = 23842 Pa, rho = 0.3796 kg/m3,
a = 296.53 m/s.
- q and detected onset and cl_buf per Mach (module values):
| M |
q (Pa) |
onset_n (g) |
cl_buf |
| 0.74 |
9139.2 |
1.940 |
1.1276 |
| 0.76 |
9639.9 |
1.910 |
1.0525 |
| 0.78 |
10154.0 |
1.867 |
0.9765 |
| 0.80 |
10681.3 |
1.844 |
0.9173 |
| 0.82 |
11222.1 |
1.820 |
0.8615 |
With the 0.02 g threshold the detector crosses at the model onset
plus (0.02 - 0.004) / 0.4 = 0.04 g. On the 0.1 g sample grid the
crossing is exact where a sample sits at the model onset (M 0.74 and
0.76 give 1.94 and 1.91) and interpolated just above it elsewhere
(1.867 at M 0.78 and 1.844 at M 0.80, within one sample step of the
idealized 1.88 and 1.85). Each cl_buf sits within 0.01 of the
hand-checked spec anchors (1.1276, 1.0526, 0.9838, 0.9206, 0.8622).
- Least-squares fit over the band: slope = -3.337 per Mach,
intercept = 3.590, so cl_buf(0.80) = 0.9203 on the line.
- Cruise reduction at M 0.80: q = 10681.3 Pa gives n_buf_cruise =
0.9203 * 10681.3 * 360 / 1912297 = 1.8506. Margin vs target 1.3:
+0.55, verdict "buffet-margin-pass". Same data against target 2.0:
margin -0.15, verdict "buffet-margin-fail".
Pitfalls
- Setting the RMS onset threshold too high: the detector crosses at the
model onset plus (0.02 - 0.004) / 0.4 = 0.04 g with the 0.02 g
threshold, so a larger threshold delays the reported buffet onset
load factor.
- Extrapolating cl_buf outside the fitted band: the least-squares line
(slope -3.337 per Mach, intercept 3.590) is only fitted over the
swept band, and a cruise Mach outside that band raises ValueError
instead of extrapolating.
- Mixing the unit systems in the cruise reduction: n_buf_cruise =
cl_buf * q * S / W needs weight in N (1912297 N from 195000 kg), q
in Pa, and S in m2; non-positive weight, area, target, or onset
threshold raise ValueError.
- Reading the verdict without the target: the same cruise point passes
against a 1.3 target (margin +0.55) and fails against 2.0 (margin
-0.15), so the margin and verdict mean nothing without the stated
target.
- Sampling the onset sweep too coarsely: on the 0.1 g grid the crossing
is exact only where a sample sits at the model onset, and elsewhere
it is interpolated up to one sample step away from the idealized
crossing.
- Feeding non-physical tables: negative altitude, Mach outside (0.1,
2.0), empty or 1-sample RMS rows, non-monotonic RMS, no onset
crossing, fewer than two fit points, and mismatched table lengths
all raise ValueError.
Verification
- Confirm isa_state returns 288.15 K / 101325 Pa / 1.225 kg/m3 at sea
level and 218.81 K / 23843 Pa / 0.3796 kg/m3 at 10668 m.
- Confirm dynamic_pressure equals 0.5 * rho * (M * a)^2 from the
module ISA state at every Mach, and the q anchors 9139.5 to 11212.4
Pa within 10 Pa (the spec q column carries hand-rounding spread).
- Confirm onset_detect returns 1.94 at M 0.74 and stays within 0.02
of the idealized crossing at every Mach of the sweep.
- Confirm every cl_buf is within 0.01 of the anchors, n_buf_cruise is
1.85 within 0.01, the margins are +0.55 and -0.15 within 0.02, and
the verdicts are "buffet-margin-pass" and "buffet-margin-fail".
- Confirm the round trip: onset load factor to cl_buf and back
recovers the load factor at fixed q.
- Confirm ValueError rejection of non-physical inputs: negative
altitude, Mach outside (0.1, 2.0), non-positive weight, area, target
or onset threshold, empty or 1-sample RMS rows, non-monotonic RMS,
no onset crossing, fewer than two fit points, mismatched table
lengths, and a cruise Mach outside the fitted band.
- Run the contract test offline: python3
scripts/test_buffet_boundary_testing.py (38 tests, deterministic).
Related leaves
- flight-test-operations/envelope/load-factor-envelope: the V-n and
gust context that frames the load factors the boundary probe reaches.
- flight-test-operations/envelope/envelope-expansion: the expansion
program and step sizing that grow the envelope toward the tested
boundary.
- flight-test-operations/envelope/stall-characteristics-testing: stall
behavior and entry techniques at the low speed end, outside this
leaf's claim.
- flight-test-operations/flutter/flutter-testing: the flutter
clearance boundary, the other high speed limit checked alongside the
buffet boundary.
Behavior contract (gate 3)
Run the deterministic contract test (stdlib unittest, offline):
python3 scripts/test_buffet_boundary_testing.py
The test builds the measured RMS fixture from the spec onset model
n_onset(M) = 1.90 - 1.50 * (M - 0.74) and covers the ISA state anchors,
dynamic pressure identity and anchors, exact onset detection (1.94 at
M 0.74 and the sweep), boundary lift coefficients within 0.01 of the
anchors, the negative-slope boundary line fit with the cruise value,
the buffet margin pass and fail cases and their verdict strings, the
lift coefficient round trip, and ValueError rejection of every
non-physical input including the extrapolation guard.
Compliance
- Standards referenced, not reproduced: FAR 25.251 and CS 25.251
address vibration and buffeting, and the FAR/CS 25.3xx flight load
factor provisions frame the load factor context, by name and
paraphrase only per standards-map.yaml. The RMS floor, RMS rise and
the 0.02 g onset threshold are documented typical engineering
criteria, not regulation values.
- compliance: STANDARDS-REF, gated: false.
1---2name: buffet-boundary-testing3description: Use when you must plan and analyze the buffet boundary flight test for a transport airplane: schedule pull-up and steady-turn test points across a Mach sweep at constant altitude, detect buffet onset from the vertical accelerometer RMS rise above the 0.02 g threshold, convert the onset load factor to the boundary lift coefficient at each Mach, fit the buffet boundary line over the tested Mach band, and compute the buffet margin at the cruise Mach against the maneuver buffet target load factor. Produces the onset load factor and boundary lift coefficient per Mach, the fitted boundary line, the buffet margin, and the pass or fail verdict gating the high speed buffet clearance assessment. Trigger: buffet boundary flight test, buffet onset, high speed buffet, maneuver buffet, accelerometer RMS rise, pull-up sweep, buffet margin, boundary lift coefficient.4license: Apache-2.05---67# Buffet Boundary Testing (flight-test-operations/envelope/buffet-boundary-testing)89Use when the task is the buffet boundary flight test of a transport10airplane: scheduling pull-up and steady-turn points across a Mach sweep11at constant altitude, detecting buffet onset from the vertical12accelerometer RMS rise above threshold, converting the onset load factor13to the boundary lift coefficient, and scoring the buffet margin at the14cruise condition against a maneuver buffet target. This leaf implements15the standard RMS-based onset detection and boundary fitting in pure16Python, stdlib only. It pairs with flight-test-operations/envelope/17load-factor-envelope for the V-n context of the tested load factors,18envelope-expansion for the expansion program that precedes the boundary19probe, and flight-test-operations/flutter/flutter-testing for the other20high speed clearance boundary. The RMS floor, RMS rise per g and the210.02 g onset threshold below are documented typical engineering22criteria, not regulation values; FAR/CS-25 are referenced for buffet and23vibration context by name and paraphrase only.2425## Domain quick reference2627- Test gross weight: W = m * g0, g0 = 9.80665 m/s2. Onset load factor28 n_onset is in g, so the lift at onset is n_onset * W.29- ISA state at altitude: T = 288.15 - 0.0065 * h below 11000 m30 (216.65 K above), P from the 5.25588 exponent law or the isothermal31 stratosphere pressure, rho = P / (287.05 * T).32- Dynamic pressure: q = 0.5 * rho * V^2 with V = M * a and a =33 sqrt(1.4 * 287.05 * T), the ISA speed of sound.34- Buffet-onset detection: with samples of (load factor n, vertical35 accelerometer RMS) sorted by n and non-decreasing in RMS, the onset36 load factor is the linear interpolation of the first crossing of the37 onset RMS threshold between two consecutive samples. The documented38 typical criteria are a 0.02 g onset RMS threshold, a 0.004 g RMS39 floor below onset, and a 0.4 g RMS rise per g of load factor above40 onset; they are engineering criteria, not regulation values.41- Boundary lift coefficient at one Mach: cl_buf = n_onset * W /42 (q * S) with S the reference wing area.43- Boundary line fit: cl_buf = slope * M + intercept by least squares44 (local 2x2 normal equations) over the tested Mach band.45- Buffet margin at cruise: n_buf_cruise = cl_buf(M_cr) * q(M_cr) * S /46 W, margin_n = n_buf_cruise - target_n; verdict47 "buffet-margin-pass" when margin_n >= 0.0, else "buffet-margin-fail".48- Units are SI throughout: kg, m, Pa, kg/m3, m/s; load factors in g.4950## Workflow51521. Fix the test point schedule: weight_kg, wing_area_m2, altitude_m,53 the mach_list sweep and the load factor samples per Mach54 (rms_table), plus the cruise_mach where the margin is scored.552. Get the atmosphere with isa_state, then the dynamic pressure q per56 Mach with dynamic_pressure.573. Detect the onset load factor per Mach with onset_detect on the58 measured (n, rms_g) samples; the detector interpolates the first59 RMS crossing of onset_rms_g.604. Convert each onset load factor to the boundary lift coefficient61 with boundary_lift_coefficient.625. Fit the boundary line over the Mach band with fit_boundary_line,63 passing cruise_mach so cl_at_cruise is evaluated; omit cruise_mach64 when only the line is wanted (cl_at_cruise is then None).656. Score the cruise condition: n_buf_cruise from the line at66 cruise_mach, the margin with buffet_margin against the maneuver67 buffet target, and the verdict.687. Run the whole point schedule through analyze with one inputs dict;69 it returns the per-Mach q, onset_n and cl_buf points, the fit, the70 cruise reduction and the verdict.718. Confirm the deterministic checks with the contract test72 scripts/test_buffet_boundary_testing.py.7374## Worked example7576Transport at W = 195000 kg (W = 1912297 N), S = 360.0 m2, altitude7710668 m, Mach sweep [0.74, 0.76, 0.78, 0.80, 0.82], pull-ups with78load factor samples every 0.1 g from 1.0 to 2.2. The measured RMS79fixture (built in the test, unknown to the module) follows rms(n) =800.004 g below the model onset n_onset(M) = 1.90 - 1.50 * (M - 0.74),81then rises 0.4 g per g above it.8283- ISA at 10668 m: T = 218.81 K, P = 23842 Pa, rho = 0.3796 kg/m3,84 a = 296.53 m/s.85- q and detected onset and cl_buf per Mach (module values):8687| M | q (Pa) | onset_n (g) | cl_buf |88|---|---|---|---|89| 0.74 | 9139.2 | 1.940 | 1.1276 |90| 0.76 | 9639.9 | 1.910 | 1.0525 |91| 0.78 | 10154.0 | 1.867 | 0.9765 |92| 0.80 | 10681.3 | 1.844 | 0.9173 |93| 0.82 | 11222.1 | 1.820 | 0.8615 |9495 With the 0.02 g threshold the detector crosses at the model onset96 plus (0.02 - 0.004) / 0.4 = 0.04 g. On the 0.1 g sample grid the97 crossing is exact where a sample sits at the model onset (M 0.74 and98 0.76 give 1.94 and 1.91) and interpolated just above it elsewhere99 (1.867 at M 0.78 and 1.844 at M 0.80, within one sample step of the100 idealized 1.88 and 1.85). Each cl_buf sits within 0.01 of the101 hand-checked spec anchors (1.1276, 1.0526, 0.9838, 0.9206, 0.8622).102- Least-squares fit over the band: slope = -3.337 per Mach,103 intercept = 3.590, so cl_buf(0.80) = 0.9203 on the line.104- Cruise reduction at M 0.80: q = 10681.3 Pa gives n_buf_cruise =105 0.9203 * 10681.3 * 360 / 1912297 = 1.8506. Margin vs target 1.3:106 +0.55, verdict "buffet-margin-pass". Same data against target 2.0:107 margin -0.15, verdict "buffet-margin-fail".108109## Pitfalls110111- Setting the RMS onset threshold too high: the detector crosses at the112 model onset plus (0.02 - 0.004) / 0.4 = 0.04 g with the 0.02 g113 threshold, so a larger threshold delays the reported buffet onset114 load factor.115- Extrapolating cl_buf outside the fitted band: the least-squares line116 (slope -3.337 per Mach, intercept 3.590) is only fitted over the117 swept band, and a cruise Mach outside that band raises ValueError118 instead of extrapolating.119- Mixing the unit systems in the cruise reduction: n_buf_cruise =120 cl_buf * q * S / W needs weight in N (1912297 N from 195000 kg), q121 in Pa, and S in m2; non-positive weight, area, target, or onset122 threshold raise ValueError.123- Reading the verdict without the target: the same cruise point passes124 against a 1.3 target (margin +0.55) and fails against 2.0 (margin125 -0.15), so the margin and verdict mean nothing without the stated126 target.127- Sampling the onset sweep too coarsely: on the 0.1 g grid the crossing128 is exact only where a sample sits at the model onset, and elsewhere129 it is interpolated up to one sample step away from the idealized130 crossing.131- Feeding non-physical tables: negative altitude, Mach outside (0.1,132 2.0), empty or 1-sample RMS rows, non-monotonic RMS, no onset133 crossing, fewer than two fit points, and mismatched table lengths134 all raise ValueError.135136## Verification137138- Confirm isa_state returns 288.15 K / 101325 Pa / 1.225 kg/m3 at sea139 level and 218.81 K / 23843 Pa / 0.3796 kg/m3 at 10668 m.140- Confirm dynamic_pressure equals 0.5 * rho * (M * a)^2 from the141 module ISA state at every Mach, and the q anchors 9139.5 to 11212.4142 Pa within 10 Pa (the spec q column carries hand-rounding spread).143- Confirm onset_detect returns 1.94 at M 0.74 and stays within 0.02144 of the idealized crossing at every Mach of the sweep.145- Confirm every cl_buf is within 0.01 of the anchors, n_buf_cruise is146 1.85 within 0.01, the margins are +0.55 and -0.15 within 0.02, and147 the verdicts are "buffet-margin-pass" and "buffet-margin-fail".148- Confirm the round trip: onset load factor to cl_buf and back149 recovers the load factor at fixed q.150- Confirm ValueError rejection of non-physical inputs: negative151 altitude, Mach outside (0.1, 2.0), non-positive weight, area, target152 or onset threshold, empty or 1-sample RMS rows, non-monotonic RMS,153 no onset crossing, fewer than two fit points, mismatched table154 lengths, and a cruise Mach outside the fitted band.155- Run the contract test offline: python3156 scripts/test_buffet_boundary_testing.py (38 tests, deterministic).157158## Related leaves159160- flight-test-operations/envelope/load-factor-envelope: the V-n and161 gust context that frames the load factors the boundary probe reaches.162- flight-test-operations/envelope/envelope-expansion: the expansion163 program and step sizing that grow the envelope toward the tested164 boundary.165- flight-test-operations/envelope/stall-characteristics-testing: stall166 behavior and entry techniques at the low speed end, outside this167 leaf's claim.168- flight-test-operations/flutter/flutter-testing: the flutter169 clearance boundary, the other high speed limit checked alongside the170 buffet boundary.171172## Behavior contract (gate 3)173174Run the deterministic contract test (stdlib unittest, offline):175176 python3 scripts/test_buffet_boundary_testing.py177178The test builds the measured RMS fixture from the spec onset model179n_onset(M) = 1.90 - 1.50 * (M - 0.74) and covers the ISA state anchors,180dynamic pressure identity and anchors, exact onset detection (1.94 at181M 0.74 and the sweep), boundary lift coefficients within 0.01 of the182anchors, the negative-slope boundary line fit with the cruise value,183the buffet margin pass and fail cases and their verdict strings, the184lift coefficient round trip, and ValueError rejection of every185non-physical input including the extrapolation guard.186187## Compliance188189- Standards referenced, not reproduced: FAR 25.251 and CS 25.251190 address vibration and buffeting, and the FAR/CS 25.3xx flight load191 factor provisions frame the load factor context, by name and192 paraphrase only per standards-map.yaml. The RMS floor, RMS rise and193 the 0.02 g onset threshold are documented typical engineering194 criteria, not regulation values.195- compliance: STANDARDS-REF, gated: false.