.. raw:: html
.. 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 .. 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
F-HNAV C-GFIO