Gyro Allan Variance (space-systems/adcs/gyro-allan-variance)
Use when you must characterize gyroscope noise for ADCS sensor selection:
turning a rate sample time series into the overlapping Allan deviation
curve and reading the noise process off its log-log slope. This leaf
implements the time-domain Allan method in pure Python, stdlib only, and
pairs with space-systems/adcs/attitude-determination-quest for the
attitude side of the sensor suite; gnc-autonomy/estimation-filtering/
complementary-filter consumes gyro noise specs in gyro/vector fusion, so
the ARW coefficient produced here is the metrology layer beneath any
gyro-using estimation leaf.
Domain quick reference
Overlapping Allan deviation at cluster time tau = m * tau0, N rate
samples spaced tau0 seconds apart:
AD(tau) = sqrt( 1 / (2 (N - 2m)) * sum_{k=0}^{N-2m-1}
( mean(samples[k+m : k+2m]) - mean(samples[k : k+m]) )^2 )
Implemented with cumulative sums S[i] = sum of samples[:i], so each
cluster mean is (S[b] - S[a]) / m and the estimator stays stable on
long series.
White rate noise: AD(tau) = sigma * sqrt(tau0 / tau), a straight line
of slope -1/2 on a log-log plot. The tau = 1 s deviation equals the
rate standard deviation sigma.
Angle random walk coefficient in deg/sqrt(h): ARW = AD(1 s) * 57.2958
- sqrt(3600 * tau0). With tau0 = 1 s the scale is 3437.748, so
sigma = 2.0e-5 rad/s gives about 0.0688 deg/sqrt(h), a high-grade
MEMS/RLG band.
Noise classes from the log-log slope: about -1/2 angle random walk,
about +1/2 rate random walk, about -1 quantization noise, flat (near
zero slope) bias instability.
classify_noise bands: slope <= -0.85 quantization-noise; [-0.75,
-0.25] angle-random-walk; [0.25, 0.75] rate-random-walk; |slope| <
0.15 bias-instability; otherwise mixed.
Units are SI: rate samples in rad/s, tau in s, AD in rad/s. ECSS
frames the ADCS context; the relations above are standard engineering
methodology, summary-only.
Workflow
- Load the gyro rate time series (rad/s) and its sample period tau0 in
seconds.
- Choose the correlation-time grid: integer multiples of tau0, with the
largest cluster m = tau / tau0 at most (N - 1) / 2.
- Compute the Allan deviation curve with allan_deviation(rate_samples,
tau0_s, taus); it returns AD values in rad/s in the order of taus.
- Fit the noise slope: log(AD) against log(tau) with noise_slope, then
categorize with classify_noise (angle-random-walk, rate-random-walk,
quantization-noise, bias-instability, or mixed).
- Read off the angle random walk coefficient: angle_random_walk(ad_at_
tau1, tau0_s) scales AD at tau = 1 s into deg/sqrt(h).
- For the full picture in one call, gyro_noise_summary(rate_samples,
tau0_s, taus) returns the dict {taus, allan_deviations, fitted_slope,
noise_class, arw_deg_per_sqrt_h, ad_at_1s}.
- Confirm the deterministic checks with the contract test
scripts/test_gyro_allan_variance.py.
Worked example
Seeded white rate noise: sigma = 2.0e-5 rad/s, tau0 = 1 s, N = 65536
samples, generated with random.Random(20260904) via the Box-Muller
transform (module inputs only; the module itself draws no randomness).
Real module outputs on that fixture:
- AD(1 s) = 2.0009e-5 rad/s, ratio 1.0005 to sigma (theory 1.0000).
- Decay: AD(4 s) / AD(1 s) = 0.5009, matching the 1/sqrt(tau) law
(theory 0.5000).
- AD(256 s) = 1.2680e-6 rad/s, ratio 1.0144 to sigma / sqrt(256)
(theory 1.2500e-6).
- Fitted slope over the dyadic grid tau = 2..256 s: -0.4977 (theory
-0.5); classify_noise(-0.4977) = "angle-random-walk".
- Angle random walk: angle_random_walk(2.0009e-5, 1.0) = 0.0688
deg/sqrt(h), the metrology number a gyro datasheet quotes.
- Integrated white noise (rate random walk, cumulative sum of the same
fixture): fitted slope +0.5006 (theory +0.5), categorized
"rate-random-walk".
- gyro_noise_summary on the white fixture returns noise_class
"angle-random-walk", fitted_slope -0.4977, ad_at_1s 2.0009e-5 and
arw_deg_per_sqrt_h 0.0688.
Pitfalls
- Asking for an invalid cluster time: a tau below tau0, a tau that is
not a whole multiple of tau0, or a cluster longer than (N - 1) / 2
samples raises ValueError - the Allan deviation is only defined on
the grid of integer multiples up to half the series.
- Running on too few samples: allan_deviation needs at least 3 rate
samples, and short series give noisy high-tau points that drag the
fitted slope off its theory value.
- Reading the noise class off too short a tau range: the -0.5 slope of
angle random walk only shows over a wide dyadic grid (the worked
example fits tau = 2..256 s); a few points near tau0 classify
wrongly.
- Confusing the process signatures: white rate noise slopes -1/2
(angle random walk), its integral slopes +1/2 (rate random walk),
quantization slopes -1, and bias instability is the flat floor -
classify against the documented bands, not by eye.
- Scaling ARW with the wrong tau0: angle_random_walk converts the
AD at tau = 1 s using tau0_s; a mismatched sample period corrupts
the deg/sqrt(h) coefficient a datasheet would quote.
- Injecting randomness into the module: the logic draws no RNG (the
worked example seeds its fixture outside the module), so identical
inputs must give byte-identical outputs run to run.
Verification
- allan_deviation raises ValueError for fewer than 3 samples, tau0 <= 0,
a tau below tau0, a tau that is not a whole multiple of tau0, and a
cluster longer than (N - 1) / 2 samples.
- noise_slope raises ValueError on empty or mismatched lists, fewer than
two points, and a zero-variance log-tau grid.
- angle_random_walk raises ValueError on non-positive AD or tau0.
- The white-noise closed form AD(tau) = sigma sqrt(tau0 / tau) is
checked inside the contract test with ratio bands [0.97, 1.03] from
tau = 1 s up to 256 s, and the integrated fixture must fit a slope in
[0.45, 0.55].
- Module determinism: identical inputs give identical outputs; the
seeded fixture is reproducible run-to-run.
Related leaves
- space-systems/adcs/attitude-determination-quest: determination
sibling; the QUEST attitude from vector observations is the consumer
of a gyro-specified pointing budget.
- gnc-autonomy/estimation-filtering/complementary-filter: consumer of
gyro noise specs in gyro/vector fusion, where the ARW coefficient
weights the gyro channel.
- gnc-autonomy/navigation/inertial-navigation: INS error propagation
boundary; that leaf propagates given drift and bias, this leaf
characterizes sensor noise, metrology vs propagation.
- cross-cutting/numerics/power-spectral-density: frequency-domain
boundary; PSD estimation with the Welch periodogram, not the
time-domain Allan method.
Behavior contract (gate 3)
Run the deterministic contract test (stdlib unittest, offline):
python3 scripts/test_gyro_allan_variance.py
The 34 tests cover the overlapping Allan deviation against the
white-noise closed form, the seeded fixture anchors (AD(1 s), AD(256 s),
fitted slope -0.4977, ARW 0.0688 deg/sqrt(h)), the rate random walk
slope, classification band boundaries, ARW scaling with tau0, summary
dict keys and consistency, module determinism, and ValueError rejection
of every non-physical input.
Compliance
- Standards referenced, not reproduced: ECSS is the adcs convention id
in standards-map.yaml; the Allan deviation relations above are
standard engineering methodology, summary-only.
- compliance: STANDARDS-REF, gated: false.
1---2name: gyro-allan-variance3description: Use when you must characterize gyroscope noise for ADCS sensor selection: compute the overlapping Allan deviation AD(tau) over a correlation-time grid from a rate sample time series with cumulative sums, fit the log-log noise slope, categorize the noise process from the slope band (white noise or angle random walk at about -1/2, rate random walk at about +1/2, quantization at about -1, bias instability as a flat floor), and extract the angle random walk coefficient in deg/sqrt(h). Produces the Allan deviation curve, the noise classification, the fitted slope and the ARW coefficient that gate gyro selection. Trigger: gyro Allan deviation, allan deviation, angle random walk, rate random walk, bias instability, gyro noise model, noise slope, gyroscope rate noise, ARW coefficient, deg per root hour.4license: Apache-2.05---67# Gyro Allan Variance (space-systems/adcs/gyro-allan-variance)89Use when you must characterize gyroscope noise for ADCS sensor selection:10turning a rate sample time series into the overlapping Allan deviation11curve and reading the noise process off its log-log slope. This leaf12implements the time-domain Allan method in pure Python, stdlib only, and13pairs with space-systems/adcs/attitude-determination-quest for the14attitude side of the sensor suite; gnc-autonomy/estimation-filtering/15complementary-filter consumes gyro noise specs in gyro/vector fusion, so16the ARW coefficient produced here is the metrology layer beneath any17gyro-using estimation leaf.1819## Domain quick reference2021- Overlapping Allan deviation at cluster time tau = m * tau0, N rate22 samples spaced tau0 seconds apart:2324 AD(tau) = sqrt( 1 / (2 (N - 2m)) * sum_{k=0}^{N-2m-1}25 ( mean(samples[k+m : k+2m]) - mean(samples[k : k+m]) )^2 )2627 Implemented with cumulative sums S[i] = sum of samples[:i], so each28 cluster mean is (S[b] - S[a]) / m and the estimator stays stable on29 long series.30- White rate noise: AD(tau) = sigma * sqrt(tau0 / tau), a straight line31 of slope -1/2 on a log-log plot. The tau = 1 s deviation equals the32 rate standard deviation sigma.33- Angle random walk coefficient in deg/sqrt(h): ARW = AD(1 s) * 57.295834 * sqrt(3600 * tau0). With tau0 = 1 s the scale is 3437.748, so35 sigma = 2.0e-5 rad/s gives about 0.0688 deg/sqrt(h), a high-grade36 MEMS/RLG band.37- Noise classes from the log-log slope: about -1/2 angle random walk,38 about +1/2 rate random walk, about -1 quantization noise, flat (near39 zero slope) bias instability.40- classify_noise bands: slope <= -0.85 quantization-noise; [-0.75,41 -0.25] angle-random-walk; [0.25, 0.75] rate-random-walk; |slope| <42 0.15 bias-instability; otherwise mixed.43- Units are SI: rate samples in rad/s, tau in s, AD in rad/s. ECSS44 frames the ADCS context; the relations above are standard engineering45 methodology, summary-only.4647## Workflow48491. Load the gyro rate time series (rad/s) and its sample period tau0 in50 seconds.512. Choose the correlation-time grid: integer multiples of tau0, with the52 largest cluster m = tau / tau0 at most (N - 1) / 2.533. Compute the Allan deviation curve with allan_deviation(rate_samples,54 tau0_s, taus); it returns AD values in rad/s in the order of taus.554. Fit the noise slope: log(AD) against log(tau) with noise_slope, then56 categorize with classify_noise (angle-random-walk, rate-random-walk,57 quantization-noise, bias-instability, or mixed).585. Read off the angle random walk coefficient: angle_random_walk(ad_at_59 tau1, tau0_s) scales AD at tau = 1 s into deg/sqrt(h).606. For the full picture in one call, gyro_noise_summary(rate_samples,61 tau0_s, taus) returns the dict {taus, allan_deviations, fitted_slope,62 noise_class, arw_deg_per_sqrt_h, ad_at_1s}.637. Confirm the deterministic checks with the contract test64 scripts/test_gyro_allan_variance.py.6566## Worked example6768Seeded white rate noise: sigma = 2.0e-5 rad/s, tau0 = 1 s, N = 6553669samples, generated with random.Random(20260904) via the Box-Muller70transform (module inputs only; the module itself draws no randomness).71Real module outputs on that fixture:7273- AD(1 s) = 2.0009e-5 rad/s, ratio 1.0005 to sigma (theory 1.0000).74- Decay: AD(4 s) / AD(1 s) = 0.5009, matching the 1/sqrt(tau) law75 (theory 0.5000).76- AD(256 s) = 1.2680e-6 rad/s, ratio 1.0144 to sigma / sqrt(256)77 (theory 1.2500e-6).78- Fitted slope over the dyadic grid tau = 2..256 s: -0.4977 (theory79 -0.5); classify_noise(-0.4977) = "angle-random-walk".80- Angle random walk: angle_random_walk(2.0009e-5, 1.0) = 0.068881 deg/sqrt(h), the metrology number a gyro datasheet quotes.82- Integrated white noise (rate random walk, cumulative sum of the same83 fixture): fitted slope +0.5006 (theory +0.5), categorized84 "rate-random-walk".85- gyro_noise_summary on the white fixture returns noise_class86 "angle-random-walk", fitted_slope -0.4977, ad_at_1s 2.0009e-5 and87 arw_deg_per_sqrt_h 0.0688.888990## Pitfalls9192- Asking for an invalid cluster time: a tau below tau0, a tau that is93 not a whole multiple of tau0, or a cluster longer than (N - 1) / 294 samples raises ValueError - the Allan deviation is only defined on95 the grid of integer multiples up to half the series.96- Running on too few samples: allan_deviation needs at least 3 rate97 samples, and short series give noisy high-tau points that drag the98 fitted slope off its theory value.99- Reading the noise class off too short a tau range: the -0.5 slope of100 angle random walk only shows over a wide dyadic grid (the worked101 example fits tau = 2..256 s); a few points near tau0 classify102 wrongly.103- Confusing the process signatures: white rate noise slopes -1/2104 (angle random walk), its integral slopes +1/2 (rate random walk),105 quantization slopes -1, and bias instability is the flat floor -106 classify against the documented bands, not by eye.107- Scaling ARW with the wrong tau0: angle_random_walk converts the108 AD at tau = 1 s using tau0_s; a mismatched sample period corrupts109 the deg/sqrt(h) coefficient a datasheet would quote.110- Injecting randomness into the module: the logic draws no RNG (the111 worked example seeds its fixture outside the module), so identical112 inputs must give byte-identical outputs run to run.113## Verification114115- allan_deviation raises ValueError for fewer than 3 samples, tau0 <= 0,116 a tau below tau0, a tau that is not a whole multiple of tau0, and a117 cluster longer than (N - 1) / 2 samples.118- noise_slope raises ValueError on empty or mismatched lists, fewer than119 two points, and a zero-variance log-tau grid.120- angle_random_walk raises ValueError on non-positive AD or tau0.121- The white-noise closed form AD(tau) = sigma sqrt(tau0 / tau) is122 checked inside the contract test with ratio bands [0.97, 1.03] from123 tau = 1 s up to 256 s, and the integrated fixture must fit a slope in124 [0.45, 0.55].125- Module determinism: identical inputs give identical outputs; the126 seeded fixture is reproducible run-to-run.127128## Related leaves129130- space-systems/adcs/attitude-determination-quest: determination131 sibling; the QUEST attitude from vector observations is the consumer132 of a gyro-specified pointing budget.133- gnc-autonomy/estimation-filtering/complementary-filter: consumer of134 gyro noise specs in gyro/vector fusion, where the ARW coefficient135 weights the gyro channel.136- gnc-autonomy/navigation/inertial-navigation: INS error propagation137 boundary; that leaf propagates given drift and bias, this leaf138 characterizes sensor noise, metrology vs propagation.139- cross-cutting/numerics/power-spectral-density: frequency-domain140 boundary; PSD estimation with the Welch periodogram, not the141 time-domain Allan method.142143## Behavior contract (gate 3)144145Run the deterministic contract test (stdlib unittest, offline):146147 python3 scripts/test_gyro_allan_variance.py148149The 34 tests cover the overlapping Allan deviation against the150white-noise closed form, the seeded fixture anchors (AD(1 s), AD(256 s),151fitted slope -0.4977, ARW 0.0688 deg/sqrt(h)), the rate random walk152slope, classification band boundaries, ARW scaling with tau0, summary153dict keys and consistency, module determinism, and ValueError rejection154of every non-physical input.155156## Compliance157158- Standards referenced, not reproduced: ECSS is the adcs convention id159 in standards-map.yaml; the Allan deviation relations above are160 standard engineering methodology, summary-only.161- compliance: STANDARDS-REF, gated: false.