Radio Navigation Aids (avionics/flight-management/radio-navigation-aids)
Use when the task is the receiver level geometry of conventional radio
navigation aids for the aircraft navigation solution: turning the
planar station and aircraft coordinates into the VOR bearing and
reciprocal radial, the DME slant range that the distance measuring
equipment reports, and the ILS localizer and glideslope deviation
angles that the approach receivers display against the runway
centerline and the nominal glidepath. This leaf implements that
geometry in pure Python, stdlib only, on the local tangent plane with
x east, y north and z up. It pairs with the sibling lateral-navigation
leaf, the FMS downstream consumer of the nav geometry, with
flight-planning for the route context, and with the gnc navigation
leaf that owns the position fix feeding the coordinates.
Domain quick reference
- Coordinate convention: local tangent plane, x east (m), y north (m),
z up (m). The VOR/DME station sits at the origin; the aircraft is at
(x_ac, y_ac, altitude_m). Planar geometry is a documented
simplification for short ranges; great-circle corrections are out of
scope.
- Bearing from the station to the aircraft, clockwise from north:
bearing = deg(atan2(x_ac, y_ac)) normalized to [0, 360). Due east
gives 90 deg, due north 0 deg.
- VOR radial FROM the station: radial = (bearing + 180) mod 360, the
reciprocal of the bearing the aircraft flies toward the station.
- DME slant range: d = sqrt(x_ac^2 + y_ac^2 + altitude_m^2). The DME
measures the straight line from the station at ground level to the
aircraft at altitude, so the slant range always exceeds the ground
distance once the altitude is above zero.
- Localizer deviation: dev_loc = deg(atan(lateral_offset_m /
distance_to_threshold_m)), positive when the aircraft is right of
the localizer centerline (lateral offset to the right of the
approach course is positive).
- Glideslope deviation: actual = deg(atan(height_agl_m /
distance_to_threshold_m)); dev_gs = actual - gs_angle_deg, with the
nominal glideslope default 3.0 deg and the deviation positive above
the glidepath.
- Units are SI throughout: m, deg.
- DO-178C frames the software context of the nav receivers; the
relations above are standard planar trigonometry, summary-only.
Workflow
- Take the aircraft position (x_ac, y_ac, altitude_m) in the local
tangent frame with the VOR/DME station at the origin; flight-
planning and the gnc position fix leaves provide the coordinates.
- Get the bearing from the station with bearing_deg and the radial
FROM the station with radial_deg of that bearing.
- Get the DME answer with dme_slant_range_m; compare it against the
ground distance to confirm the altitude contribution.
- For the ILS localizer, feed the lateral offset and the distance to
the runway threshold to loc_deviation_deg; a positive result means
the aircraft is right of the centerline.
- For the glideslope, feed the height above the threshold, the
distance to the threshold and the nominal path angle to
gs_deviation_deg; positive means above the glidepath.
- For a full solution call analyze once with all inputs and read the
dict of bearing, radial, slant range and both deviation angles.
- Confirm the deterministic checks with the contract test
scripts/test_radio_navigation_aids.py.
Worked example
Aircraft 10 km east and 17.32 km north of the VOR/DME at 1000 m.
- Bearing: atan2(10000, 17320) = 30.0007 deg, within 0.01 of 30.0 deg.
- Radial: 30.0007 + 180 = 210.0007 deg, within 0.01 of 210.0 deg.
- Slant range: sqrt(1e8 + 2.999824e8 + 1e6) = sqrt(4.009824e8) =
20024.5 m, within 1.0 m. The summary figure 20022.5 m in the wave-27
spec came from rounding 17320^2 to 2.999e8 before summing; the exact
value for the stated inputs is 20024.5 m (recorded assumption).
- Localizer: aircraft 100 m right of the centerline at 5000 m to the
threshold gives dev = atan(100 / 5000) = 1.1458 deg.
- Glideslope against the 3 deg path at 5724 m to the threshold:
at 300 m height the actual angle is 3.0002 deg and the deviation
0.0002 deg; at 400 m the actual is 3.9974 deg and the deviation
0.9974 deg, about 1 deg high.
Verification
- Confirm bearing_deg(10000, 17320) is within 0.01 of 30.0 deg and
radial_deg of it within 0.01 of 210.0 deg.
- Confirm dme_slant_range_m(10000, 17320, 1000) returns 20024.5 m and
that a 3-4-5 triangle at zero altitude returns 5000.0 m exactly.
- Confirm loc_deviation_deg(100, 5000) returns 1.1458 deg and the
zero-offset case returns 0.0 deg.
- Confirm gs_deviation_deg(300, 5724) is within 0.001 of 0.0002 deg,
gs_deviation_deg(400, 5724) within 0.01 of 0.9974 deg, and the
height on the nominal path returns near-zero deviation.
- Confirm the radial round trip: radial_deg applied twice returns the
original bearing.
- Confirm ValueError rejection of negative altitude, non-positive
distance to threshold, glideslope angle outside (0, 90) deg,
negative height above ground, and non-finite inputs.
- Run the contract test offline: python3
scripts/test_radio_navigation_aids.py (38 tests, deterministic).
Related leaves
- avionics/flight-management/lateral-navigation: the FMS lateral
guidance downstream of this nav geometry.
- avionics/flight-management/flight-planning: the route and leg
context for the navaid geometry checks.
- avionics/flight-management/vertical-navigation: the FMS vertical
profile that the glideslope intercept supports.
- gnc-autonomy/navigation/gnss-pseudorange-positioning: the position
fix boundary feeding the aircraft coordinates.
Pitfalls
- Confusing the bearing with the radial: bearing_deg is the direction
FROM the station to the aircraft, while the VOR radial is the
reciprocal (bearing + 180) mod 360 - a 030 bearing from the station
puts the aircraft on the 210 radial, and applying radial_deg twice
returns the original bearing.
- Using ground distance for the DME readout: the DME measures the
slant range sqrt(x^2 + y^2 + altitude^2), which always exceeds the
ground distance once the altitude is above zero (20024.5 m versus
20000.0 m at 1000 m over the worked example) - altitude is not a
second-order term in the DME answer.
- Reversing the deviation signs: localizer deviation is positive when
the aircraft is RIGHT of the centerline and glideslope deviation is
positive ABOVE the path - an aircraft below the glidepath carries a
negative deviation and must correct up, not down.
- Comparing height to the path instead of angle: gs_deviation_deg
computes the actual angle atan(height / distance) and subtracts the
nominal 3.0 deg path, so 300 m at 5724 m is on-path (0.0002 deg)
while 400 m is about 1 deg high - a fixed height error shrinks as
the aircraft nears the threshold.
- Applying the planar model at long range: the local tangent plane
with x east / y north is a documented simplification for short
ranges and great-circle corrections are out of scope - do not
stretch these station-local formulas across oceanic distances.
- Feeding non-physical geometry: negative altitude, non-positive
distance to the threshold, glideslope angle outside (0, 90) deg,
negative height above ground, and non-finite inputs raise ValueError
in every entry point.
Behavior contract (gate 3)
Run the deterministic contract test (stdlib unittest, offline):
python3 scripts/test_radio_navigation_aids.py
The test covers the worked-example contract (bearing 30 deg, radial
210 deg, slant range 20024.5 m, localizer deviation 1.1458 deg,
glideslope deviations 0.0002 deg and 0.9974 deg), the cardinal
bearings and the [0, 360) normalization, the radial reciprocal round
trip, the DME slant versus ground distance behavior, zero and
symmetric deviation cases, and ValueError rejection of negative
altitude, non-positive distance, out-of-range glideslope angle,
negative height and non-finite inputs.
Compliance
- Standards referenced, not reproduced: DO-178C frames the software
life cycle of the nav receivers; the planar geometry above is
standard engineering methodology, summary-only per standards-map.
- compliance: STANDARDS-REF, gated: false.
1---2name: radio-navigation-aids3description: Use when you must compute the radio navigation geometry of conventional navaids for the aircraft navigation solution: derive the VOR radial and the bearing from the aircraft to the station from the planar station and aircraft coordinates, compute the DME slant range from the ground distance and the aircraft altitude, compute the ILS localizer deviation angle from the lateral offset and the distance to the runway threshold, and compute the ILS glideslope deviation from the height above the threshold and the distance to the threshold against the nominal glideslope angle. Produces the VOR bearing and radial, the slant range, and the localizer and glideslope deviation angles that gate radio navigation geometry checks. Trigger: VOR radial, DME slant range, ILS localizer deviation, glideslope deviation, radio navigation geometry, bearing to the navaid station, approach course offset.4license: Apache-2.05---67# Radio Navigation Aids (avionics/flight-management/radio-navigation-aids)89Use when the task is the receiver level geometry of conventional radio10navigation aids for the aircraft navigation solution: turning the11planar station and aircraft coordinates into the VOR bearing and12reciprocal radial, the DME slant range that the distance measuring13equipment reports, and the ILS localizer and glideslope deviation14angles that the approach receivers display against the runway15centerline and the nominal glidepath. This leaf implements that16geometry in pure Python, stdlib only, on the local tangent plane with17x east, y north and z up. It pairs with the sibling lateral-navigation18leaf, the FMS downstream consumer of the nav geometry, with19flight-planning for the route context, and with the gnc navigation20leaf that owns the position fix feeding the coordinates.2122## Domain quick reference2324- Coordinate convention: local tangent plane, x east (m), y north (m),25 z up (m). The VOR/DME station sits at the origin; the aircraft is at26 (x_ac, y_ac, altitude_m). Planar geometry is a documented27 simplification for short ranges; great-circle corrections are out of28 scope.29- Bearing from the station to the aircraft, clockwise from north:30 bearing = deg(atan2(x_ac, y_ac)) normalized to [0, 360). Due east31 gives 90 deg, due north 0 deg.32- VOR radial FROM the station: radial = (bearing + 180) mod 360, the33 reciprocal of the bearing the aircraft flies toward the station.34- DME slant range: d = sqrt(x_ac^2 + y_ac^2 + altitude_m^2). The DME35 measures the straight line from the station at ground level to the36 aircraft at altitude, so the slant range always exceeds the ground37 distance once the altitude is above zero.38- Localizer deviation: dev_loc = deg(atan(lateral_offset_m /39 distance_to_threshold_m)), positive when the aircraft is right of40 the localizer centerline (lateral offset to the right of the41 approach course is positive).42- Glideslope deviation: actual = deg(atan(height_agl_m /43 distance_to_threshold_m)); dev_gs = actual - gs_angle_deg, with the44 nominal glideslope default 3.0 deg and the deviation positive above45 the glidepath.46- Units are SI throughout: m, deg.47- DO-178C frames the software context of the nav receivers; the48 relations above are standard planar trigonometry, summary-only.4950## Workflow51521. Take the aircraft position (x_ac, y_ac, altitude_m) in the local53 tangent frame with the VOR/DME station at the origin; flight-54 planning and the gnc position fix leaves provide the coordinates.552. Get the bearing from the station with bearing_deg and the radial56 FROM the station with radial_deg of that bearing.573. Get the DME answer with dme_slant_range_m; compare it against the58 ground distance to confirm the altitude contribution.594. For the ILS localizer, feed the lateral offset and the distance to60 the runway threshold to loc_deviation_deg; a positive result means61 the aircraft is right of the centerline.625. For the glideslope, feed the height above the threshold, the63 distance to the threshold and the nominal path angle to64 gs_deviation_deg; positive means above the glidepath.656. For a full solution call analyze once with all inputs and read the66 dict of bearing, radial, slant range and both deviation angles.677. Confirm the deterministic checks with the contract test68 scripts/test_radio_navigation_aids.py.6970## Worked example7172Aircraft 10 km east and 17.32 km north of the VOR/DME at 1000 m.7374- Bearing: atan2(10000, 17320) = 30.0007 deg, within 0.01 of 30.0 deg.75- Radial: 30.0007 + 180 = 210.0007 deg, within 0.01 of 210.0 deg.76- Slant range: sqrt(1e8 + 2.999824e8 + 1e6) = sqrt(4.009824e8) =77 20024.5 m, within 1.0 m. The summary figure 20022.5 m in the wave-2778 spec came from rounding 17320^2 to 2.999e8 before summing; the exact79 value for the stated inputs is 20024.5 m (recorded assumption).80- Localizer: aircraft 100 m right of the centerline at 5000 m to the81 threshold gives dev = atan(100 / 5000) = 1.1458 deg.82- Glideslope against the 3 deg path at 5724 m to the threshold:83 at 300 m height the actual angle is 3.0002 deg and the deviation84 0.0002 deg; at 400 m the actual is 3.9974 deg and the deviation85 0.9974 deg, about 1 deg high.8687## Verification8889- Confirm bearing_deg(10000, 17320) is within 0.01 of 30.0 deg and90 radial_deg of it within 0.01 of 210.0 deg.91- Confirm dme_slant_range_m(10000, 17320, 1000) returns 20024.5 m and92 that a 3-4-5 triangle at zero altitude returns 5000.0 m exactly.93- Confirm loc_deviation_deg(100, 5000) returns 1.1458 deg and the94 zero-offset case returns 0.0 deg.95- Confirm gs_deviation_deg(300, 5724) is within 0.001 of 0.0002 deg,96 gs_deviation_deg(400, 5724) within 0.01 of 0.9974 deg, and the97 height on the nominal path returns near-zero deviation.98- Confirm the radial round trip: radial_deg applied twice returns the99 original bearing.100- Confirm ValueError rejection of negative altitude, non-positive101 distance to threshold, glideslope angle outside (0, 90) deg,102 negative height above ground, and non-finite inputs.103- Run the contract test offline: python3104 scripts/test_radio_navigation_aids.py (38 tests, deterministic).105106## Related leaves107108- avionics/flight-management/lateral-navigation: the FMS lateral109 guidance downstream of this nav geometry.110- avionics/flight-management/flight-planning: the route and leg111 context for the navaid geometry checks.112- avionics/flight-management/vertical-navigation: the FMS vertical113 profile that the glideslope intercept supports.114- gnc-autonomy/navigation/gnss-pseudorange-positioning: the position115 fix boundary feeding the aircraft coordinates.116117## Pitfalls118119- Confusing the bearing with the radial: bearing_deg is the direction120 FROM the station to the aircraft, while the VOR radial is the121 reciprocal (bearing + 180) mod 360 - a 030 bearing from the station122 puts the aircraft on the 210 radial, and applying radial_deg twice123 returns the original bearing.124- Using ground distance for the DME readout: the DME measures the125 slant range sqrt(x^2 + y^2 + altitude^2), which always exceeds the126 ground distance once the altitude is above zero (20024.5 m versus127 20000.0 m at 1000 m over the worked example) - altitude is not a128 second-order term in the DME answer.129- Reversing the deviation signs: localizer deviation is positive when130 the aircraft is RIGHT of the centerline and glideslope deviation is131 positive ABOVE the path - an aircraft below the glidepath carries a132 negative deviation and must correct up, not down.133- Comparing height to the path instead of angle: gs_deviation_deg134 computes the actual angle atan(height / distance) and subtracts the135 nominal 3.0 deg path, so 300 m at 5724 m is on-path (0.0002 deg)136 while 400 m is about 1 deg high - a fixed height error shrinks as137 the aircraft nears the threshold.138- Applying the planar model at long range: the local tangent plane139 with x east / y north is a documented simplification for short140 ranges and great-circle corrections are out of scope - do not141 stretch these station-local formulas across oceanic distances.142- Feeding non-physical geometry: negative altitude, non-positive143 distance to the threshold, glideslope angle outside (0, 90) deg,144 negative height above ground, and non-finite inputs raise ValueError145 in every entry point.146147## Behavior contract (gate 3)148149Run the deterministic contract test (stdlib unittest, offline):150151 python3 scripts/test_radio_navigation_aids.py152153The test covers the worked-example contract (bearing 30 deg, radial154210 deg, slant range 20024.5 m, localizer deviation 1.1458 deg,155glideslope deviations 0.0002 deg and 0.9974 deg), the cardinal156bearings and the [0, 360) normalization, the radial reciprocal round157trip, the DME slant versus ground distance behavior, zero and158symmetric deviation cases, and ValueError rejection of negative159altitude, non-positive distance, out-of-range glideslope angle,160negative height and non-finite inputs.161162## Compliance163164- Standards referenced, not reproduced: DO-178C frames the software165 life cycle of the nav receivers; the planar geometry above is166 standard engineering methodology, summary-only per standards-map.167- compliance: STANDARDS-REF, gated: false.