Pointing Error Budget (space-systems/adcs/pointing-error-budget)
Use when the task is the ADCS pointing error chain: summing the
independent 1-sigma error contributors of the attitude determination
and control system into one RSS pointing error, converting it to
3-sigma, checking it against the pointing requirement, allocating the
remaining budget to the contributor that is not yet sized (typically
the control deadband), and ranking the contributors by variance share.
This leaf is the assembly layer between the sensor noise metrology of
the ADCS and the payload or antenna that consumes the delivered
pointing error. Pure Python, stdlib only, unit-agnostic with the ADCS
example in arcsec.
Domain quick reference
- RSS combination: rss_1sigma = sqrt(sum(c_i^2)) over the independent
1-sigma contributors. Independence is assumed; correlated errors are
summed linearly, not by RSS.
- 3-sigma conversion: rss_3sigma = 3 * rss_1sigma (normal distribution
convention).
- Requirement verdict: requirement_met = rss_3sigma <= requirement_3sigma.
- Budget allocation to one remaining contributor: remaining_1sigma =
sqrt((requirement_3sigma / 3)^2 - sum(c_fixed^2)). The fixed RSS must
stay below requirement / 3 or the radicand is negative and the
allocation fails.
- Variance share: share_i = c_i^2 / sum(c_j^2); the dominant error
source is the contributor with the largest share.
- Units: the functions are unit-agnostic; the reference ADCS chain uses
arcsec (1-sigma) and the requirement uses arcsec (3-sigma).
Workflow
- List the independent 1-sigma contributors in arcsec: star tracker
determination noise, gyro propagation, control deadband, jitter,
thermal distortion (add other known terms as needed).
- Combine them with rss_pointing_error to get the 1-sigma RSS.
- Convert with three_sigma_error and judge the requirement with
three_sigma_verdict against the 3-sigma pointing requirement.
- When one contributor is not yet sized (the control deadband in the
reference chain), allocate its budget with allocate_error_budget
using the requirement and the fixed contributors.
- Rank the contributors by variance share with
dominant_error_source; pass a dict of {name: value} to get the
dominant contributor name back.
- Assemble the full picture with pointing_error_budget, which returns
the RSS values, the verdict, the dominant index and share, and the
per-contributor variance shares in one dict.
- Confirm the deterministic checks with the contract test
scripts/test_pointing_error_budget.py.
Worked example
Reference ADCS chain (arcsec, 1-sigma): star tracker determination
noise 3, gyro propagation 2, control deadband 25, jitter 8, thermal
distortion 5; pointing requirement 90 arcsec 3-sigma.
- rss_pointing_error([3, 2, 25, 8, 5]) = sqrt(9 + 4 + 625 + 64 + 25) =
sqrt(727) = 26.962938 arcsec.
- three_sigma_error([3, 2, 25, 8, 5]) = 3 * 26.962938 = 80.888813
arcsec.
- three_sigma_verdict([3, 2, 25, 8, 5], 90) = True: 80.888813 <= 90,
the requirement is met with margin.
- allocate_error_budget(90, [3, 2, 8, 5]) = sqrt(30^2 - (9 + 4 + 64 +
25)) = sqrt(798) = 28.248894 arcsec, the budget left for the control
deadband. It exceeds the 25 arcsec actual deadband, consistent with
the requirement verdict True.
- dominant_error_source([3, 2, 25, 8, 5]) = (index 2, control deadband,
share 625/727 = 0.8597), so the control deadband carries 86.0% of the
error variance.
Pitfalls
- Mixing 1-sigma and 3-sigma: the contributors are 1-sigma and the
requirement is 3-sigma; compare three_sigma_error against the
requirement, not the raw RSS.
- Adding correlated contributors by RSS: the root-sum-square assumes
independence; correlated errors sum linearly, so RSS understates the
chain when the terms share a common source.
- Allocating against an already-over budget: allocate_error_budget
raises ValueError when the fixed contributors push the radicand
negative (fixed RSS above requirement / 3); size the fixed chain
first.
- Trusting a verdict at the exact boundary: a requirement exactly
equal to the 3-sigma value returns True with zero margin - treat
boundary equality as met but not robust.
- Ranking by magnitude instead of variance share: the dominant source
is the largest share of the variance (the 25 arcsec deadband carries
625/727 = 86.0% in the worked example), and an all-zero contributor
list raises ValueError.
- Forgetting that a zero contributor is inert: adding a zero leaves
the RSS unchanged and reversing the input order leaves it unchanged,
so the input list order must not leak into the reported dominant
index.
Verification
- Confirm rss_pointing_error([3, 2, 25, 8, 5]) returns 26.962938 arcsec
and three_sigma_error returns 80.888813 arcsec.
- Confirm adding a zero contributor leaves the RSS unchanged, reversing
the input order leaves it unchanged, and a contributor equal to the
RSS of the others raises the total by sqrt(2).
- Confirm the verdict boundary: a requirement exactly equal to the
3-sigma value returns True.
- Confirm allocate_error_budget(90, [3, 2, 8, 5]) returns 28.248894
arcsec, and that shrinking the requirement shrinks the allocation.
- Confirm ValueError is raised for an empty contributor list, any
negative contributor, a non-positive requirement, a negative radicand
in the allocation (fixed contributors already over the 1-sigma
budget), and an all-zero contributor list in the dominant-source
ranking.
- Run the contract test offline: python3
scripts/test_pointing_error_budget.py (34 tests, deterministic).
Related leaves
- space-systems/adcs/attitude-control-sizing: actuator sizing sibling;
boundary is actuator sizing and margins versus this leaf's error
chain sum.
- space-systems/adcs/attitude-determination-quest: determination
sibling whose residual feeds this leaf's determination-noise entry.
- space-systems/subsystems/antenna-aperture-sizing: downstream consumer
of the delivered pointing error as a signal loss term.
- space-systems/adcs/gyro-allan-variance: sensor noise metrology that
characterizes the gyro propagation entry.
Behavior contract (gate 3)
Run the deterministic contract test (stdlib unittest, offline):
python3 scripts/test_pointing_error_budget.py
The test covers the reference-chain contract (RSS 26.962938 arcsec,
3-sigma 80.888813 arcsec, verdict True at 90 arcsec, allocation
28.248894 arcsec, control deadband dominant at 86.0% variance share),
the RSS identities (zero padding, order invariance, single component,
sqrt(2) growth), the verdict boundary, allocation monotonicity and
negative-radicand rejection, dominant-source ranking on the [1, 100]
case at 99.99%, dict-name support, the convenience-dict keys, run-to-
run determinism, and ValueError rejection of non-physical inputs.
Compliance
- Standards referenced, not reproduced: the ECSS ADCS error-budget
convention (reference-only per standards-map.yaml). The relations
above are standard engineering methodology, summary-only.
- compliance: STANDARDS-REF, gated: false.
1---2name: pointing-error-budget3description: Use when you must assemble the spacecraft pointing error budget for the attitude determination and control system: combine independent 1-sigma error contributors (determination noise, gyro propagation, control deadband, jitter, thermal distortion) by root-sum-square, convert to 3-sigma, check it against the pointing requirement, allocate the remaining budget to a not-yet-sized contributor, and rank error sources by variance share. Produces the RSS pointing error, the requirement verdict, the allocated contributor budget, and the dominant error source, the assembly layer from sensor metrology to payload pointing. Trigger: rss pointing error, 3 sigma requirement, error budget allocation, control deadband, jitter budget, dominant error source.4license: Apache-2.05---67# Pointing Error Budget (space-systems/adcs/pointing-error-budget)89Use when the task is the ADCS pointing error chain: summing the10independent 1-sigma error contributors of the attitude determination11and control system into one RSS pointing error, converting it to123-sigma, checking it against the pointing requirement, allocating the13remaining budget to the contributor that is not yet sized (typically14the control deadband), and ranking the contributors by variance share.15This leaf is the assembly layer between the sensor noise metrology of16the ADCS and the payload or antenna that consumes the delivered17pointing error. Pure Python, stdlib only, unit-agnostic with the ADCS18example in arcsec.1920## Domain quick reference2122- RSS combination: rss_1sigma = sqrt(sum(c_i^2)) over the independent23 1-sigma contributors. Independence is assumed; correlated errors are24 summed linearly, not by RSS.25- 3-sigma conversion: rss_3sigma = 3 * rss_1sigma (normal distribution26 convention).27- Requirement verdict: requirement_met = rss_3sigma <= requirement_3sigma.28- Budget allocation to one remaining contributor: remaining_1sigma =29 sqrt((requirement_3sigma / 3)^2 - sum(c_fixed^2)). The fixed RSS must30 stay below requirement / 3 or the radicand is negative and the31 allocation fails.32- Variance share: share_i = c_i^2 / sum(c_j^2); the dominant error33 source is the contributor with the largest share.34- Units: the functions are unit-agnostic; the reference ADCS chain uses35 arcsec (1-sigma) and the requirement uses arcsec (3-sigma).3637## Workflow38391. List the independent 1-sigma contributors in arcsec: star tracker40 determination noise, gyro propagation, control deadband, jitter,41 thermal distortion (add other known terms as needed).422. Combine them with rss_pointing_error to get the 1-sigma RSS.433. Convert with three_sigma_error and judge the requirement with44 three_sigma_verdict against the 3-sigma pointing requirement.454. When one contributor is not yet sized (the control deadband in the46 reference chain), allocate its budget with allocate_error_budget47 using the requirement and the fixed contributors.485. Rank the contributors by variance share with49 dominant_error_source; pass a dict of {name: value} to get the50 dominant contributor name back.516. Assemble the full picture with pointing_error_budget, which returns52 the RSS values, the verdict, the dominant index and share, and the53 per-contributor variance shares in one dict.547. Confirm the deterministic checks with the contract test55 scripts/test_pointing_error_budget.py.5657## Worked example5859Reference ADCS chain (arcsec, 1-sigma): star tracker determination60noise 3, gyro propagation 2, control deadband 25, jitter 8, thermal61distortion 5; pointing requirement 90 arcsec 3-sigma.6263- rss_pointing_error([3, 2, 25, 8, 5]) = sqrt(9 + 4 + 625 + 64 + 25) =64 sqrt(727) = 26.962938 arcsec.65- three_sigma_error([3, 2, 25, 8, 5]) = 3 * 26.962938 = 80.88881366 arcsec.67- three_sigma_verdict([3, 2, 25, 8, 5], 90) = True: 80.888813 <= 90,68 the requirement is met with margin.69- allocate_error_budget(90, [3, 2, 8, 5]) = sqrt(30^2 - (9 + 4 + 64 +70 25)) = sqrt(798) = 28.248894 arcsec, the budget left for the control71 deadband. It exceeds the 25 arcsec actual deadband, consistent with72 the requirement verdict True.73- dominant_error_source([3, 2, 25, 8, 5]) = (index 2, control deadband,74 share 625/727 = 0.8597), so the control deadband carries 86.0% of the75 error variance.767778## Pitfalls7980- Mixing 1-sigma and 3-sigma: the contributors are 1-sigma and the81 requirement is 3-sigma; compare three_sigma_error against the82 requirement, not the raw RSS.83- Adding correlated contributors by RSS: the root-sum-square assumes84 independence; correlated errors sum linearly, so RSS understates the85 chain when the terms share a common source.86- Allocating against an already-over budget: allocate_error_budget87 raises ValueError when the fixed contributors push the radicand88 negative (fixed RSS above requirement / 3); size the fixed chain89 first.90- Trusting a verdict at the exact boundary: a requirement exactly91 equal to the 3-sigma value returns True with zero margin - treat92 boundary equality as met but not robust.93- Ranking by magnitude instead of variance share: the dominant source94 is the largest share of the variance (the 25 arcsec deadband carries95 625/727 = 86.0% in the worked example), and an all-zero contributor96 list raises ValueError.97- Forgetting that a zero contributor is inert: adding a zero leaves98 the RSS unchanged and reversing the input order leaves it unchanged,99 so the input list order must not leak into the reported dominant100 index.101## Verification102103- Confirm rss_pointing_error([3, 2, 25, 8, 5]) returns 26.962938 arcsec104 and three_sigma_error returns 80.888813 arcsec.105- Confirm adding a zero contributor leaves the RSS unchanged, reversing106 the input order leaves it unchanged, and a contributor equal to the107 RSS of the others raises the total by sqrt(2).108- Confirm the verdict boundary: a requirement exactly equal to the109 3-sigma value returns True.110- Confirm allocate_error_budget(90, [3, 2, 8, 5]) returns 28.248894111 arcsec, and that shrinking the requirement shrinks the allocation.112- Confirm ValueError is raised for an empty contributor list, any113 negative contributor, a non-positive requirement, a negative radicand114 in the allocation (fixed contributors already over the 1-sigma115 budget), and an all-zero contributor list in the dominant-source116 ranking.117- Run the contract test offline: python3118 scripts/test_pointing_error_budget.py (34 tests, deterministic).119120## Related leaves121122- space-systems/adcs/attitude-control-sizing: actuator sizing sibling;123 boundary is actuator sizing and margins versus this leaf's error124 chain sum.125- space-systems/adcs/attitude-determination-quest: determination126 sibling whose residual feeds this leaf's determination-noise entry.127- space-systems/subsystems/antenna-aperture-sizing: downstream consumer128 of the delivered pointing error as a signal loss term.129- space-systems/adcs/gyro-allan-variance: sensor noise metrology that130 characterizes the gyro propagation entry.131132## Behavior contract (gate 3)133134Run the deterministic contract test (stdlib unittest, offline):135136 python3 scripts/test_pointing_error_budget.py137138The test covers the reference-chain contract (RSS 26.962938 arcsec,1393-sigma 80.888813 arcsec, verdict True at 90 arcsec, allocation14028.248894 arcsec, control deadband dominant at 86.0% variance share),141the RSS identities (zero padding, order invariance, single component,142sqrt(2) growth), the verdict boundary, allocation monotonicity and143negative-radicand rejection, dominant-source ranking on the [1, 100]144case at 99.99%, dict-name support, the convenience-dict keys, run-to-145run determinism, and ValueError rejection of non-physical inputs.146147## Compliance148149- Standards referenced, not reproduced: the ECSS ADCS error-budget150 convention (reference-only per standards-map.yaml). The relations151 above are standard engineering methodology, summary-only.152- compliance: STANDARDS-REF, gated: false.