.. jupyter-execute::
# This trick only helps to trigger the proper Javascript library require queries.
from ipyleaflet import Map
Map()
.. raw:: html
.. raw:: html
Calibration flights
-------------------
*What is this plane doing?*
This was my first reaction after hitting on the following trajectory during an
analysis of approaches at Toulouse airport. After exchanges with ATC people, I
learned that these trajectories are flown by small aircraft working at
calibrating landing assistance systems, including ILS and VOR.
These trajectories mostly consist of many low passes over an airport and large
circles or arcs of circle. A small sample of such trajectories is included in
traffic.data.samples, and the following snippet of code will let you explore
those before an attempt of explanation.
.. raw:: html
Select a different area/airport:
You may click on trajectories for more information.
A short introduction to radio-navigation
========================================
A number of navigational systems emerged in the second half of the 20th century,
mainly based on VHF communications. Some of them were designed for surveillance,
like `Secondary surveillance radars
`_; other systems
also came to assist pilot in navigation and landing.
`VOR `_ (VHF
Omnidirectional Range) ground stations send an omnidirectional master signal
(on a predefined frequency determined for each station) and a second highly
directional signal. Aircraft measure the phase difference between the two
signals, which corresponds to the bearing from the station to the aircraft. [1]_
Historically, airways were laid out between VORs, which stand at the
intersections between those routes. Advances in GNSS (understand GPS) make these
stations less necessary.
VOR stations often host a `DME
`_ (Distance
Measuring Equipment). The principle is similar to radar ranging, except the
roles of the aircraft and of the ground station are reversed. The aircraft sends
a signal to the DME; the DME repeats the same signal 50 μs after reception. When
the aircraft receives a copy of the sent messages, it measures the time of
travel to the DME, subtracts 50 μs and divides the results by 2: speed of light
gives an estimation of the distance between the aircraft to the ground station.
`ILS `_ (Instrument
Landing Systems) consists of two guidance systems: a lateral one (the LOC, for
*localizer*) and a vertical one (the GS, for *glide slope*, also *glide path*).
The localizer usually consists of several pairs of directional antennas placed
beyond the departure end of the runway. [2]_
Local authorities define very strict thresholds for accuracy: internal
monitoring shall switch off the system if the accuracy of the signal is not
appropriate. All radio-navigation beacons (including VOR, DME and ILS) are
checked periodically by specially equipped aircraft. In particular, the VOR test
consists of flying around the beacon in circles at defined distances and along
several radials.
.. [1] Decoding VOR signals can be a fun exercice for the amateur software radio developper. (`link `_)
.. [2] Check for them next time you drive around an airport!
A basic analysis of VOR calibration trajectories
================================================
We can have a look at the first trajectory in the calibration dataset. The
aircraft takes off from Ajaccio airport before flying concentric circles and
radials. There must be a VOR around, we can search in the navaid database:
.. jupyter-execute::
from traffic.data.samples.calibration import ajaccio
from traffic.data import navaids
navaids.extent(ajaccio).query('type == "VOR"')
Next step is to compute for each point the distance and bearing from the VOR to
each point of the trajectory. The parts of the trajectory that are of interest
are the ones with little to no variation in the distance (circles) and in the
bearing (radials) to the VOR.
Then, we can write a simple .query() followed by a .split() method to select all
segments with a constant bearing and distance with respect to the selected VOR.
.. jupyter-execute::
from functools import reduce
from operator import or_
vor = navaids.extent(ajaccio)['AJO']
ajaccio = (
ajaccio.distance(vor) # add a distance column (in nm) w.r.t the VOR
.bearing(vor) # add a bearing column w.r.t the VOR
.assign(
distance_diff=lambda df: df.distance.diff().abs(), # large circles
bearing_diff=lambda df: df.bearing.diff().abs(), # long radials
)
)
constant_distance = list(
segment for segment in ajaccio.query('distance_diff < .02').split('1 min')
if segment.longer_than('5 minutes')
)
# trick to display many trajectories
reduce(or_, constant_distance)
We have all we need to enhance the interesting parts of the trajectory now:
.. jupyter-execute::
import matplotlib.pyplot as plt
from cartes.crs import Lambert93, EuroPP
from cartes.utils.features import countries
from traffic.data import airports
point_params = dict(zorder=5, text_kw=dict(fontname="Ubuntu", fontsize=15))
box_params = dict(boxstyle="round", facecolor="lightpink", alpha=0.7, zorder=5)
with plt.style.context("traffic"):
fig, ax = plt.subplots(subplot_kw=dict(projection=EuroPP()))
ax.add_feature(countries())
# airport information
airports["LFKJ"].point.plot(ax, **point_params)
# VOR information
shift_vor = dict(units="dots", x=20, y=10)
vor.plot(ax, marker="h", shift=shift_vor, **point_params)
# full trajectory in dashed lines
ajaccio.plot(ax, color="#aaaaaa", linestyle="--")
# constant distance segments
for segment in ajaccio.query("distance_diff < .02").split("1 minute"):
if segment.longer_than("3 minutes"):
segment.plot(ax, color="crimson")
# an annotation with the radius of the circle
distance_vor = segment.data.distance.mean()
segment.at().plot(
ax,
alpha=0, # We don't need the point, only the text
text_kw=dict(s=f"{distance_vor:.1f} nm", bbox=box_params),
)
# constant bearing segments
for segment in ajaccio.query("bearing_diff < .01").split("1 minute"):
if segment.longer_than("3 minutes"):
segment.plot(ax, color="forestgreen")
ax.set_extent((7.6, 9.9, 41.2, 43.3))
ax.spines["geo"].set_visible(False)
The following map displays the result of a similar processing on the other VOR
calibration trajectories from the sample dataset. [3]_
.. raw:: html
Select a different VOR:
.. [3] Time, distance and bearing thresholds may need further ajustments for a proper picture. Note the kiruna14 seems to circle around a position that is not referenced in the database. Any help or insight welcome!
Equipped aircraft for beacon calibration
========================================
This list only contains the equipped aircraft for the calibration in the sample
dataset. Apart from F-HNAV, registration numbers were found on social networks.
Two of the aircraft registrations were not in the provided database at the time
of the writing, so we added them manually.
.. raw:: html
Ever seen a Runway Calibration ? @Beechcraft#B300 VH-FIZ was out calibrating RWY16L @SydneyAirport this morning, making a number of approaches to calibrate and certify ILS precision 💯. The orbits in the track are done to fit in with regular arrivals and departures ✈️💙📷 pic.twitter.com/CRkXfsscHa
.. jupyter-execute::
from traffic.core import Traffic
from traffic.data import aircraft
from traffic.data.samples import calibration
(
Traffic.from_flights(
getattr(calibration, name).assign(
# create a flight_id which includes the date of the flight
flight_id=lambda df: f"{name} ({df.timestamp.min():%Y-%m-%d})"
)
for name in calibration.__all__
)
.summary(["flight_id", "icao24", "start"])
.eval()
.merge(aircraft.data)
.sort_values(["registration", "start"])
.groupby(["registration", "typecode", "icao24"])
.apply(lambda df: ", ".join(df.flight_id))
.to_frame()
)
.. raw:: html