ADS-B Surveillance (avionics/surveillance/ads-b-surveillance)
Use when the task is assessing an ADS-B Out installation and an ADS-B
In reception geometry against the DO-260B-style performance
categories: the containment radius guaranteed by a navigation
integrity category (NIC), the 95-percent horizontal accuracy bound of
a navigation accuracy category for position (NACp), the per-flight-hour
integrity probability of a source integrity level (SIL), the NIC and
NACp whose bounds cover a required containment or accuracy value, and
the 1090 MHz extended squitter radio line-of-sight range between two
altitudes. This leaf is the second of the avionics/surveillance pack;
avionics/surveillance/tcas-resolution-advisory owns the TCAS sense
logic on measured state, while this leaf sizes the surveillance
performance claims that gate an equipage assessment. The category
bounds are paraphrased DO-260B summary values held as module constants
in the logic file, never a reproduction of the MOPS tables. Pure
Python stdlib, deterministic and offline. Units: containment radius
and accuracy in metres, altitude in feet, range in kilometres,
integrity as a probability per flight hour.
Domain quick reference
- NIC containment radius: each navigation integrity category 1 to 11
maps to the containment radius the position source guarantees, from
7.5 m at NIC 11 down to 37040 m at NIC 1; NIC 0 means unknown and
maps to None. NIC 8, for example, bounds containment to 185.2 m (one
tenth of a nautical mile). Exact per-category values live in the
NIC_RADIUS_M module constant in ads_b_surveillance_logic.py.
- NACp accuracy: each navigation accuracy category for position 1 to
11 maps to the 95-percent horizontal accuracy bound, from 3 m at
NACp 11 down to 18520 m at NACp 1; NACp 0 is unknown. NACp 9 bounds
the 95-percent position error to 30 m. Values live in NACp_95_M.
- SIL integrity: each source integrity level 1 to 3 maps to the
maximum probability of an undetected failure per flight hour, 1e-7
at SIL 3, 1e-5 at SIL 2 and 1e-3 at SIL 1; SIL 0 is unknown. Values
live in SIL_PROB.
- Category selection: nic_for_radius(required_radius_m) and
nacp_for_accuracy(required_95_m) walk the categories from the
tightest bound (highest number) down to category 1 and return the
first whose bound is >= the required value, the least-integrity
category that still bounds the requirement. A returned 0 means no
category covers the requirement, not even category 1.
- Radio line-of-sight range: d = RANGE_COEFF * (sqrt(h_own * FT_TO_M) +
sqrt(h_other * FT_TO_M)) with RANGE_COEFF = 4.12 km per sqrt(metre)
and FT_TO_M = 0.3048, the standard-atmosphere 4/3-earth radio
horizon used for 1090 MHz extended squitter coverage.
- Assessment bundle: adsb_assessment(nic, nacp, sil, alt_ft_own,
alt_ft_other) returns {containment_radius_m, accuracy_95_m,
integrity_prob, range_km} in one call.
Workflow
- Fix the assessment state: the candidate NIC, NACp and SIL from the
position source and the own and other altitudes in feet.
- Map the categories to bounds with nic_containment_radius(nic),
nacp_accuracy(nacp) and sil_probability(sil); category 0 returns
None, meaning the value is unknown.
- For a required containment radius or 95-percent accuracy, select
the covering category with nic_for_radius(required_radius_m) or
nacp_for_accuracy(required_95_m); a returned 0 flags that no
category bound covers the requirement.
- Compute the reception coverage with
adsb_range_km(alt_ft_own, alt_ft_other), passing 0 ft for the
altitude of a ground ADS-B receiver.
- Bundle the whole case with adsb_assessment(nic, nacp, sil,
alt_ft_own, alt_ft_other) and read containment_radius_m,
accuracy_95_m, integrity_prob and range_km.
- Confirm the deterministic checks with the contract test
scripts/test_ads_b_surveillance.py.
Worked example
Own ship at 10 000 ft receiving an ADS-B In target at 30 000 ft, with
the source reporting NIC 8, NACp 9, SIL 2.
- nic_containment_radius(8) = 185.2 m: the position source guarantees
containment within 185.2 m.
- nacp_accuracy(9) = 30.0 m: the 95-percent horizontal position error
stays within 30 m.
- sil_probability(2) = 1e-5: at most one undetected failure per
100 000 flight hours.
- nic_for_radius(100.0) = 8: NIC 9 bounds only 75 m, too small for the
100 m required containment radius; NIC 8 bounds 185.2 m and covers
it, so NIC 8 is the chosen category.
- nacp_for_accuracy(50.0) = 8: NACp 9 bounds only 30 m, too small for
the 50 m required accuracy; NACp 8 bounds 92.6 m and covers it.
- adsb_range_km(10000, 30000) = 621.4 km: sqrt(3048) = 55.21,
sqrt(9144) = 95.62, sum 150.83 times 4.12 gives 621.4 km, inside the
600 to 650 km band for the altitude pair.
- adsb_assessment(8, 9, 2, 10000, 30000) returns {containment_radius_m:
185.2, accuracy_95_m: 30.0, integrity_prob: 1e-5, range_km: 621.4}.
Verification
- nic_containment_radius(8) is 185.2 m and nacp_accuracy(9) is 30.0 m,
exactly the table entries (equal within 1e-9 relative).
- nic_for_radius(7.5) is 11 and nic_for_radius(1e6) is 0, the
exact-bound and no-coverage ends of the selection rule;
nacp_for_accuracy(50.0) is 8.
- adsb_range_km(0, 0) is 0.0 and the 10 000/30 000 ft case sits inside
the 600 to 650 km bound; SIL 3 gives the stricter probability (1e-7
below the 1e-5 of SIL 2).
- Every out-of-range category (NIC or NACp outside 0 to 11, SIL
outside 0 to 3), every negative altitude and every non-positive
required radius or accuracy raises ValueError.
- Run the contract test offline: python3
scripts/test_ads_b_surveillance.py (34 tests, deterministic).
Related leaves
- avionics/surveillance/tcas-resolution-advisory: the sibling leaf in
the surveillance pack; it owns the TCAS II sense logic on measured
range and altitude state, this leaf owns the surveillance
performance categories.
- gnc-autonomy/navigation/gnss-pseudorange-positioning: the position
solution whose accuracy and integrity feed the NACp and NIC claims.
- gnc-autonomy/navigation/gnss-raim-fde: fault detection that backs a
source integrity level claim.
- avionics/flight-management/radio-navigation-aids: navaid sensing
context for the airborne navigation suite.
Pitfalls
- Treating NIC, NACp, and SIL as one quality number: NIC bounds
containment radius, NACp bounds the 95-percent horizontal position
error, and SIL is an integrity probability per flight hour - NIC 8
at 185.2 m and NACp 9 at 30.0 m describe different guarantees, and
neither is comparable with a SIL 2 probability of 1e-5.
- Choosing a category that does not cover the requirement: the
selection walks from the tightest bound down and returns the first
category whose bound is >= the required value - for a 100 m
containment radius NIC 9 (75 m) is too small and NIC 8 (185.2 m)
is chosen, so never pick the category whose bound merely comes
closest from below.
- Reading the selection result 0 as the unknown category: a returned 0
from nic_for_radius or nacp_for_accuracy means no category bound
covers the requirement at all (not even category 1's 37040 m or
18520 m), while an input category of 0 maps to None for an unknown
value - the two zeros are different verdicts.
- Forgetting the feet-to-metres conversion in the range law: the radio
horizon uses sqrt(h_ft * FT_TO_M), so 10 000 ft enters as
sqrt(3048) = 55.21 and the 10 000/30 000 ft pair reaches 621.4 km -
feeding feet straight into the square root without the 0.3048
factor inflates the coverage estimate.
- Assigning coverage without altitudes: a zero altitude (a ground
ADS-B receiver at 0 ft) contributes zero horizon and the pair range
is 0.0 km - the own/other altitude pair is part of the input, and
negative altitudes raise ValueError.
- Quoting the category bounds as MOPS tables: the NIC/NACp/SIL values
are paraphrased summary data in the module constants used for
equipage assessment, stated as module data and never as reproduced
rtca-do-260b tables - confirm against the current MOPS before a
formal claim.
Behavior contract (gate 3)
Run the deterministic contract test (stdlib unittest, offline):
python3 scripts/test_ads_b_surveillance.py
The test covers the exact table anchors (NIC 8 at 185.2 m, NACp 9 at
30.0 m, SIL 2 at 1e-5), table spot checks with unknown-category None
returns, the selection rule for required containment radii and
accuracies including the exact-bound and no-coverage cases, the
10 000/30 000 ft range worked example (621.4 km inside the 600 to
650 km bound), the zero-altitude range, the assessment bundle,
ValueError rejection of out-of-range categories, negative altitudes
and non-positive requirements, and determinism of the repeated calls.
Compliance
- Standards referenced, not reproduced: rtca-do-260b (DO-260B) is a
gated RTCA standard; the category bounds above are paraphrased
summary values used in equipage assessments, stated as module data,
never as reproduced MOPS tables.
- compliance: STANDARDS-REF, gated: false.
1---2name: ads-b-surveillance3description: Use when you must assess an ADS-B Out installation and ADS-B In reception geometry against the DO-260B-style performance categories: map the navigation integrity category (NIC) to its containment radius, map the navigation accuracy category for position (NACp) to its 95-percent accuracy bound, map the source integrity level (SIL) to its per-flight-hour probability bound, select the NIC and NACp category whose bound covers a required containment or accuracy value, and compute the 1090 MHz extended squitter radio line-of-sight range between two altitudes. Produces the containment radius, accuracy bound, integrity probability, chosen categories, and coverage range that gate an ADS-B surveillance assessment. Trigger: ads-b-out, ads-b-in, extended-squitter, nic, nacp, sil, containment-radius, ads-b-range.4license: Apache-2.05---67# ADS-B Surveillance (avionics/surveillance/ads-b-surveillance)89Use when the task is assessing an ADS-B Out installation and an ADS-B10In reception geometry against the DO-260B-style performance11categories: the containment radius guaranteed by a navigation12integrity category (NIC), the 95-percent horizontal accuracy bound of13a navigation accuracy category for position (NACp), the per-flight-hour14integrity probability of a source integrity level (SIL), the NIC and15NACp whose bounds cover a required containment or accuracy value, and16the 1090 MHz extended squitter radio line-of-sight range between two17altitudes. This leaf is the second of the avionics/surveillance pack;18avionics/surveillance/tcas-resolution-advisory owns the TCAS sense19logic on measured state, while this leaf sizes the surveillance20performance claims that gate an equipage assessment. The category21bounds are paraphrased DO-260B summary values held as module constants22in the logic file, never a reproduction of the MOPS tables. Pure23Python stdlib, deterministic and offline. Units: containment radius24and accuracy in metres, altitude in feet, range in kilometres,25integrity as a probability per flight hour.2627## Domain quick reference2829- NIC containment radius: each navigation integrity category 1 to 1130 maps to the containment radius the position source guarantees, from31 7.5 m at NIC 11 down to 37040 m at NIC 1; NIC 0 means unknown and32 maps to None. NIC 8, for example, bounds containment to 185.2 m (one33 tenth of a nautical mile). Exact per-category values live in the34 NIC_RADIUS_M module constant in ads_b_surveillance_logic.py.35- NACp accuracy: each navigation accuracy category for position 1 to36 11 maps to the 95-percent horizontal accuracy bound, from 3 m at37 NACp 11 down to 18520 m at NACp 1; NACp 0 is unknown. NACp 9 bounds38 the 95-percent position error to 30 m. Values live in NACp_95_M.39- SIL integrity: each source integrity level 1 to 3 maps to the40 maximum probability of an undetected failure per flight hour, 1e-741 at SIL 3, 1e-5 at SIL 2 and 1e-3 at SIL 1; SIL 0 is unknown. Values42 live in SIL_PROB.43- Category selection: nic_for_radius(required_radius_m) and44 nacp_for_accuracy(required_95_m) walk the categories from the45 tightest bound (highest number) down to category 1 and return the46 first whose bound is >= the required value, the least-integrity47 category that still bounds the requirement. A returned 0 means no48 category covers the requirement, not even category 1.49- Radio line-of-sight range: d = RANGE_COEFF * (sqrt(h_own * FT_TO_M) +50 sqrt(h_other * FT_TO_M)) with RANGE_COEFF = 4.12 km per sqrt(metre)51 and FT_TO_M = 0.3048, the standard-atmosphere 4/3-earth radio52 horizon used for 1090 MHz extended squitter coverage.53- Assessment bundle: adsb_assessment(nic, nacp, sil, alt_ft_own,54 alt_ft_other) returns {containment_radius_m, accuracy_95_m,55 integrity_prob, range_km} in one call.5657## Workflow58591. Fix the assessment state: the candidate NIC, NACp and SIL from the60 position source and the own and other altitudes in feet.612. Map the categories to bounds with nic_containment_radius(nic),62 nacp_accuracy(nacp) and sil_probability(sil); category 0 returns63 None, meaning the value is unknown.643. For a required containment radius or 95-percent accuracy, select65 the covering category with nic_for_radius(required_radius_m) or66 nacp_for_accuracy(required_95_m); a returned 0 flags that no67 category bound covers the requirement.684. Compute the reception coverage with69 adsb_range_km(alt_ft_own, alt_ft_other), passing 0 ft for the70 altitude of a ground ADS-B receiver.715. Bundle the whole case with adsb_assessment(nic, nacp, sil,72 alt_ft_own, alt_ft_other) and read containment_radius_m,73 accuracy_95_m, integrity_prob and range_km.746. Confirm the deterministic checks with the contract test75 scripts/test_ads_b_surveillance.py.7677## Worked example7879Own ship at 10 000 ft receiving an ADS-B In target at 30 000 ft, with80the source reporting NIC 8, NACp 9, SIL 2.8182- nic_containment_radius(8) = 185.2 m: the position source guarantees83 containment within 185.2 m.84- nacp_accuracy(9) = 30.0 m: the 95-percent horizontal position error85 stays within 30 m.86- sil_probability(2) = 1e-5: at most one undetected failure per87 100 000 flight hours.88- nic_for_radius(100.0) = 8: NIC 9 bounds only 75 m, too small for the89 100 m required containment radius; NIC 8 bounds 185.2 m and covers90 it, so NIC 8 is the chosen category.91- nacp_for_accuracy(50.0) = 8: NACp 9 bounds only 30 m, too small for92 the 50 m required accuracy; NACp 8 bounds 92.6 m and covers it.93- adsb_range_km(10000, 30000) = 621.4 km: sqrt(3048) = 55.21,94 sqrt(9144) = 95.62, sum 150.83 times 4.12 gives 621.4 km, inside the95 600 to 650 km band for the altitude pair.96- adsb_assessment(8, 9, 2, 10000, 30000) returns {containment_radius_m:97 185.2, accuracy_95_m: 30.0, integrity_prob: 1e-5, range_km: 621.4}.9899## Verification100101- nic_containment_radius(8) is 185.2 m and nacp_accuracy(9) is 30.0 m,102 exactly the table entries (equal within 1e-9 relative).103- nic_for_radius(7.5) is 11 and nic_for_radius(1e6) is 0, the104 exact-bound and no-coverage ends of the selection rule;105 nacp_for_accuracy(50.0) is 8.106- adsb_range_km(0, 0) is 0.0 and the 10 000/30 000 ft case sits inside107 the 600 to 650 km bound; SIL 3 gives the stricter probability (1e-7108 below the 1e-5 of SIL 2).109- Every out-of-range category (NIC or NACp outside 0 to 11, SIL110 outside 0 to 3), every negative altitude and every non-positive111 required radius or accuracy raises ValueError.112- Run the contract test offline: python3113 scripts/test_ads_b_surveillance.py (34 tests, deterministic).114115## Related leaves116117- avionics/surveillance/tcas-resolution-advisory: the sibling leaf in118 the surveillance pack; it owns the TCAS II sense logic on measured119 range and altitude state, this leaf owns the surveillance120 performance categories.121- gnc-autonomy/navigation/gnss-pseudorange-positioning: the position122 solution whose accuracy and integrity feed the NACp and NIC claims.123- gnc-autonomy/navigation/gnss-raim-fde: fault detection that backs a124 source integrity level claim.125- avionics/flight-management/radio-navigation-aids: navaid sensing126 context for the airborne navigation suite.127128## Pitfalls129130- Treating NIC, NACp, and SIL as one quality number: NIC bounds131 containment radius, NACp bounds the 95-percent horizontal position132 error, and SIL is an integrity probability per flight hour - NIC 8133 at 185.2 m and NACp 9 at 30.0 m describe different guarantees, and134 neither is comparable with a SIL 2 probability of 1e-5.135- Choosing a category that does not cover the requirement: the136 selection walks from the tightest bound down and returns the first137 category whose bound is >= the required value - for a 100 m138 containment radius NIC 9 (75 m) is too small and NIC 8 (185.2 m)139 is chosen, so never pick the category whose bound merely comes140 closest from below.141- Reading the selection result 0 as the unknown category: a returned 0142 from nic_for_radius or nacp_for_accuracy means no category bound143 covers the requirement at all (not even category 1's 37040 m or144 18520 m), while an input category of 0 maps to None for an unknown145 value - the two zeros are different verdicts.146- Forgetting the feet-to-metres conversion in the range law: the radio147 horizon uses sqrt(h_ft * FT_TO_M), so 10 000 ft enters as148 sqrt(3048) = 55.21 and the 10 000/30 000 ft pair reaches 621.4 km -149 feeding feet straight into the square root without the 0.3048150 factor inflates the coverage estimate.151- Assigning coverage without altitudes: a zero altitude (a ground152 ADS-B receiver at 0 ft) contributes zero horizon and the pair range153 is 0.0 km - the own/other altitude pair is part of the input, and154 negative altitudes raise ValueError.155- Quoting the category bounds as MOPS tables: the NIC/NACp/SIL values156 are paraphrased summary data in the module constants used for157 equipage assessment, stated as module data and never as reproduced158 rtca-do-260b tables - confirm against the current MOPS before a159 formal claim.160161## Behavior contract (gate 3)162163Run the deterministic contract test (stdlib unittest, offline):164165 python3 scripts/test_ads_b_surveillance.py166167The test covers the exact table anchors (NIC 8 at 185.2 m, NACp 9 at16830.0 m, SIL 2 at 1e-5), table spot checks with unknown-category None169returns, the selection rule for required containment radii and170accuracies including the exact-bound and no-coverage cases, the17110 000/30 000 ft range worked example (621.4 km inside the 600 to172650 km bound), the zero-altitude range, the assessment bundle,173ValueError rejection of out-of-range categories, negative altitudes174and non-positive requirements, and determinism of the repeated calls.175176## Compliance177178- Standards referenced, not reproduced: rtca-do-260b (DO-260B) is a179 gated RTCA standard; the category bounds above are paraphrased180 summary values used in equipage assessments, stated as module data,181 never as reproduced MOPS tables.182- compliance: STANDARDS-REF, gated: false.