dump1090-fa/track.h

351 lines
15 KiB
C
Raw Permalink Normal View History

// Part of dump1090, a Mode S message decoder for RTLSDR devices.
//
// track.h: aircraft state tracking prototypes
//
// Copyright (c) 2014-2016 Oliver Jowett <oliver@mutability.co.uk>
//
// This file is free software: you may copy, redistribute and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 2 of the License, or (at your
// option) any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// This file incorporates work covered by the following copyright and
// permission notice:
//
// Copyright (C) 2012 by Salvatore Sanfilippo <antirez@gmail.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef DUMP1090_TRACK_H
#define DUMP1090_TRACK_H
/* Maximum age of a reliable tracked aircraft in milliseconds */
#define TRACK_AIRCRAFT_TTL 300000
/* Maximum age of an unreliable tracked aircraft, in milliseconds */
#define TRACK_AIRCRAFT_UNRELIABLE_TTL 60000
/* Maximum validity of an aircraft position */
#define TRACK_AIRCRAFT_POSITION_TTL 60000
/* Minimum number of repeated Mode A/C replies with a particular Mode A code needed in a
* 1 second period before accepting that code.
*/
2016-10-11 20:29:39 +00:00
#define TRACK_MODEAC_MIN_MESSAGES 4
/* Minimum number of DF17 messages required to mark a track as reliable */
#define TRACK_RELIABLE_DF17_MESSAGES 2
/* Minimum number of DF11 messages required to mark a track as reliable */
#define TRACK_RELIABLE_DF11_MESSAGES 3
/* Minimum number of any sort of messages required to mark a track as reliable */
#define TRACK_RELIABLE_ANY_MESSAGES 5
/* Special value for Rc unknown */
#define RC_UNKNOWN 0
2017-12-07 16:34:08 +00:00
// data moves through three states:
// fresh: data is valid. Updates from a less reliable source are not accepted.
// stale: data is valid. Updates from a less reliable source are accepted.
// expired: data is not valid.
typedef struct {
uint64_t stale_interval; /* how long after an update until the data is stale */
2018-01-09 17:13:34 +00:00
uint64_t expire_interval; /* how long after an update until the data expires */
datasource_t source; /* where the data came from */
uint64_t updated; /* when it arrived */
uint64_t stale; /* when it goes stale */
uint64_t expires; /* when it expires */
} data_validity;
/* Structure used to describe the state of one tracked aircraft */
struct aircraft {
uint32_t addr; // ICAO address
addrtype_t addrtype; // highest priority address type seen for this aircraft
uint64_t seen; // Time (millis) at which the last packet was received
long messages; // Number of Mode S messages received
int reliable; // Do we think this is a real aircraft, not noise?
long reliableDF11; // Number of "reliable" DF11s (no CRC errors corrected, IID = 0) received
long reliableDF17; // Number of "reliable" DF17s (no CRC errors corrected) received
long discarded; // Number of messages discarded as possibly-noise
double signalLevel[8]; // Last 8 Signal Amplitudes
int signalNext; // next index of signalLevel to use
data_validity callsign_valid;
char callsign[9]; // Flight number
Interactive mode updates These updates were designed to assist those using interactive mode to tune antennas and SDR gain. * Add options to display distance and bearing in interactive mode Distance and bearing instead of latitude and longitude can now be displayed in interactive mode using the following options to dump1090-fa and view1090-fa. --interactive-show-distance Show aircraft distance and bearing instead of aircraft lat/lon (requires --lat and --lon) --interactive-distance-units Distance units ('km', 'sm', 'nm') (default: 'nm')" You have to specify a reference --lat and --lon for this to work of course. * A new line now shows at the top of the interactive display that has for the current sample: Total valid aircraft count Vidible aircraft count Will be less than total if the screen hasn't enough lines to show them all. Max RSSI Min RSSI Mean RSSI Max Distance Tot: 47 Vis: 47 RSSI: Max 25.4+ Mean -29.5 Min -36.9- MaxD: 197.3nm+ * Add max distance and min/max RSSI indicators A '+' after the distance in a row indicates it's the row with the maximum distance. A '+' after the RSSI in a row indicates it's the row with the highest RSSI. A '-' after the RSSI in a row indicates it's the row with the lowest RSSI. The summary line at the top of the screen always shows the values for ALL aircraft, even those not visible. The row indicators only mark visible rows though. In this example, the first aircraft is both the farthest away and has the weakest RSSI. The second aircraft has the strongest RSSI. Tot: 47 Vis: 47 RSSI: Max 25.4+ Mean -29.5 Min -36.9- MaxD: 197.3nm+ - Hex Mode Sqwk Flight Alt Spd Hdg Dist(nm) Bearing RSSI Msgs Ti ──────────────────────────────────────────────────────────────────────────────── A8D5A4 S2 34000 438 252 197.3+ 85 -36.1- 26 2 A39A13 S2ac 5740 FFT525 30750 439 256 98.8 68 -25.4+ 123 0 A70B23 S2ac 2744 LXJ553 43000 419 258 136.1 39 -33.6 174 0 * Finally, a new option '--interactive-callsign-filter' has been added to allow filtering interactive by callsign. The value can be a simple string, in which case aircraft with that string anywhere in its callsign will be displayed, or a regular expression should you want a more precise match. Examples: --interactive-callsign-filter UAL will match all aircraft with UAL anywhere in its callsign. --interactive-callsign-filter "^UAL" will match only those callsigns that start with UAL. --interactive-callsign-filter "^(UAL|AAL)" will match only those callsigns that start with UAL or AAL. --interactive-callsign-filter "^N[0-9]" or "^N[[:digit:]]" will match only those callsigns that start with "N" and a number If you need more info on regular expressions, see this link: https://en.wikipedia.org/wiki/Regular_expression
2020-09-21 22:00:44 +00:00
int callsign_matched; // Interactive callsign filter matched
2017-12-07 16:34:08 +00:00
data_validity altitude_baro_valid;
int altitude_baro; // Altitude (Baro)
2017-06-15 17:07:40 +00:00
data_validity altitude_geom_valid;
int altitude_geom; // Altitude (Geometric)
2017-06-15 17:07:40 +00:00
data_validity geom_delta_valid;
int geom_delta; // Difference between Geometric and Baro altitudes
2017-06-15 17:07:40 +00:00
data_validity gs_valid;
2017-12-07 16:34:08 +00:00
float gs;
2017-06-15 17:07:40 +00:00
data_validity ias_valid;
unsigned ias;
2017-06-15 17:07:40 +00:00
data_validity tas_valid;
unsigned tas;
2017-06-15 17:07:40 +00:00
data_validity mach_valid;
float mach;
2017-06-15 17:07:40 +00:00
data_validity track_valid;
float track; // Ground track
2017-06-15 17:07:40 +00:00
data_validity track_rate_valid;
float track_rate; // Rate of change of ground track, degrees/second
data_validity roll_valid;
float roll; // Roll angle, degrees right
data_validity mag_heading_valid;
float mag_heading; // Magnetic heading
data_validity true_heading_valid;
float true_heading; // True heading
2017-06-15 17:07:40 +00:00
data_validity baro_rate_valid;
int baro_rate; // Vertical rate (barometric)
data_validity geom_rate_valid;
int geom_rate; // Vertical rate (geometric)
data_validity squawk_valid;
unsigned squawk; // Squawk
2018-01-09 14:43:58 +00:00
data_validity emergency_valid;
emergency_t emergency; // Emergency/priority status
2018-01-09 14:49:16 +00:00
unsigned category; // Aircraft category A0 - D7 encoded as a single hex byte. 00 = unset
data_validity airground_valid;
airground_t airground; // air/ground status
2017-12-07 16:34:08 +00:00
data_validity nav_qnh_valid;
float nav_qnh; // Altimeter setting (QNH/QFE), millibars
2017-06-15 17:07:40 +00:00
data_validity nav_altitude_mcp_valid;
unsigned nav_altitude_mcp; // FCU/MCP selected altitude
data_validity nav_altitude_fms_valid;
unsigned nav_altitude_fms; // FMS selected altitude
data_validity nav_altitude_src_valid;
nav_altitude_source_t nav_altitude_src; // source of altitude used by automation
2017-06-15 17:07:40 +00:00
2017-12-07 16:34:08 +00:00
data_validity nav_heading_valid;
float nav_heading; // target heading, degrees (0-359)
2017-06-15 17:07:40 +00:00
2017-12-07 16:34:08 +00:00
data_validity nav_modes_valid;
nav_modes_t nav_modes; // enabled modes (autopilot, vnav, etc)
data_validity cpr_odd_valid; // Last seen even CPR message
cpr_type_t cpr_odd_type;
unsigned cpr_odd_lat;
unsigned cpr_odd_lon;
2017-12-07 16:34:08 +00:00
unsigned cpr_odd_nic;
unsigned cpr_odd_rc;
data_validity cpr_even_valid; // Last seen odd CPR message
cpr_type_t cpr_even_type;
unsigned cpr_even_lat;
unsigned cpr_even_lon;
2017-12-07 16:34:08 +00:00
unsigned cpr_even_nic;
unsigned cpr_even_rc;
data_validity position_valid;
double lat, lon; // Coordinates obtained from CPR encoded data
2017-12-07 16:34:08 +00:00
unsigned pos_nic; // NIC of last computed position
unsigned pos_rc; // Rc of last computed position
2017-12-07 16:34:08 +00:00
// data extracted from opstatus etc
int adsb_version; // ADS-B version (from ADS-B operational status); -1 means no ADS-B messages seen
int adsr_version; // As above, for ADS-R messages
int tisb_version; // As above, for TIS-B messages
heading_type_t adsb_hrd; // Heading Reference Direction setting (from ADS-B operational status)
heading_type_t adsb_tah; // Track Angle / Heading setting (from ADS-B operational status)
2017-12-07 16:34:08 +00:00
data_validity nic_a_valid;
data_validity nic_c_valid;
data_validity nic_baro_valid;
data_validity nac_p_valid;
data_validity nac_v_valid;
data_validity sil_valid;
data_validity gva_valid;
data_validity sda_valid;
unsigned nic_a : 1; // NIC supplement A from opstatus
unsigned nic_c : 1; // NIC supplement C from opstatus
unsigned nic_baro : 1; // NIC baro supplement from TSS or opstatus
unsigned nac_p : 4; // NACp from TSS or opstatus
2018-01-09 14:46:33 +00:00
unsigned nac_v : 3; // NACv from airborne velocity or opstatus
unsigned sil : 2; // SIL from TSS or opstatus
sil_type_t sil_type; // SIL supplement from TSS or opstatus
2018-02-22 07:45:00 +00:00
unsigned gva : 2; // GVA from opstatus
unsigned sda : 2; // SDA from opstatus
2017-12-07 16:34:08 +00:00
// data extracted from MRAR
data_validity mrar_source_valid;
data_validity wind_valid; // speed and direction
data_validity pressure_valid;
data_validity temperature_valid;
data_validity turbulence_valid;
data_validity humidity_valid;
mrar_source_t mrar_source;
float wind_speed;
float wind_dir;
float pressure;
float temperature;
hazard_t turbulence;
float humidity;
int modeA_hit; // did our squawk match a possible mode A reply in the last check period?
int modeC_hit; // did our altitude match a possible mode C reply in the last check period?
2017-12-07 16:34:08 +00:00
int fatsv_emitted_altitude_baro; // last FA emitted altitude
int fatsv_emitted_altitude_geom; // -"- GNSS altitude
2017-06-15 17:07:40 +00:00
int fatsv_emitted_baro_rate; // -"- barometric rate
int fatsv_emitted_geom_rate; // -"- geometric rate
float fatsv_emitted_track; // -"- true track
2017-06-15 17:07:40 +00:00
float fatsv_emitted_track_rate; // -"- track rate of change
float fatsv_emitted_mag_heading; // -"- magnetic heading
float fatsv_emitted_true_heading; // -"- true heading
2017-06-15 17:07:40 +00:00
float fatsv_emitted_roll; // -"- roll angle
2017-12-07 16:34:08 +00:00
float fatsv_emitted_gs; // -"- groundspeed
unsigned fatsv_emitted_ias; // -"- IAS
unsigned fatsv_emitted_tas; // -"- TAS
2017-06-15 17:07:40 +00:00
float fatsv_emitted_mach; // -"- Mach number
airground_t fatsv_emitted_airground; // -"- air/ground state
unsigned fatsv_emitted_nav_altitude_mcp; // -"- MCP altitude
unsigned fatsv_emitted_nav_altitude_fms; // -"- FMS altitude
unsigned fatsv_emitted_nav_altitude_src; // -"- automation altitude source
2017-12-07 16:34:08 +00:00
float fatsv_emitted_nav_heading; // -"- target heading
nav_modes_t fatsv_emitted_nav_modes; // -"- enabled navigation modes
float fatsv_emitted_nav_qnh; // -"- altimeter setting
unsigned char fatsv_emitted_bds_10[7]; // -"- BDS 1,0 message
2021-07-29 11:04:53 +00:00
unsigned char fatsv_emitted_bds_17[7]; // -"- BDS 1,7 message
unsigned char fatsv_emitted_bds_30[7]; // -"- BDS 3,0 message
unsigned char fatsv_emitted_unknown_commb[7]; // -"- unrecognized Comm-B message
unsigned char fatsv_emitted_es_status[7]; // -"- ES operational status message
unsigned char fatsv_emitted_es_acas_ra[7]; // -"- ES ACAS RA report message
char fatsv_emitted_callsign[9]; // -"- callsign
2017-12-07 16:34:08 +00:00
addrtype_t fatsv_emitted_addrtype; // -"- address type (assumed ADSB_ICAO initially)
int fatsv_emitted_adsb_version; // -"- ADS-B version (assumed non-ADS-B initially)
unsigned fatsv_emitted_category; // -"- ADS-B emitter category (assumed A0 initially)
unsigned fatsv_emitted_squawk; // -"- squawk
2018-01-09 14:46:33 +00:00
unsigned fatsv_emitted_nac_p; // -"- NACp
unsigned fatsv_emitted_nac_v; // -"- NACv
unsigned fatsv_emitted_sil; // -"- SIL
sil_type_t fatsv_emitted_sil_type; // -"- SIL supplement
unsigned fatsv_emitted_nic_baro; // -"- NICbaro
emergency_t fatsv_emitted_emergency; // -"- emergency/priority status
uint64_t fatsv_last_emitted; // time (millis) aircraft was last FA emitted
2017-12-07 16:34:08 +00:00
uint64_t fatsv_last_force_emit; // time (millis) we last emitted only-on-change data
struct aircraft *next; // Next aircraft in our linked list
};
/* Mode A/C tracking is done separately, not via the aircraft list,
* and via a flat array rather than a list since there are only 4k possible values
* (nb: we ignore the ident/SPI bit when tracking)
*/
extern uint32_t modeAC_count[4096];
extern uint32_t modeAC_match[4096];
2016-10-11 20:29:39 +00:00
extern uint32_t modeAC_age[4096];
/* is this bit of data valid? */
static inline int trackDataValid(const data_validity *v)
{
return (v->source != SOURCE_INVALID && messageNow() < v->expires);
}
/* is this bit of data fresh? */
static inline int trackDataFresh(const data_validity *v)
{
return (v->source != SOURCE_INVALID && messageNow() < v->stale);
}
/* what's the age of this data, in milliseconds? */
static inline uint64_t trackDataAge(const data_validity *v)
{
if (v->source == SOURCE_INVALID)
return ~(uint64_t)0;
if (v->updated >= messageNow())
return 0;
return (messageNow() - v->updated);
}
/* Update aircraft state from data in the provided mesage.
* Return the tracked aircraft.
*/
struct modesMessage;
struct aircraft *trackUpdateFromMessage(struct modesMessage *mm);
/* Call periodically */
void trackPeriodicUpdate();
/* Convert from a (hex) mode A value to a 0-4095 index */
static inline unsigned modeAToIndex(unsigned modeA)
{
return (modeA & 0x0007) | ((modeA & 0x0070) >> 1) | ((modeA & 0x0700) >> 2) | ((modeA & 0x7000) >> 3);
}
/* Convert from a 0-4095 index to a (hex) mode A value */
static inline unsigned indexToModeA(unsigned index)
{
return (index & 0007) | ((index & 0070) << 1) | ((index & 0700) << 2) | ((index & 07000) << 3);
}
Interactive mode updates These updates were designed to assist those using interactive mode to tune antennas and SDR gain. * Add options to display distance and bearing in interactive mode Distance and bearing instead of latitude and longitude can now be displayed in interactive mode using the following options to dump1090-fa and view1090-fa. --interactive-show-distance Show aircraft distance and bearing instead of aircraft lat/lon (requires --lat and --lon) --interactive-distance-units Distance units ('km', 'sm', 'nm') (default: 'nm')" You have to specify a reference --lat and --lon for this to work of course. * A new line now shows at the top of the interactive display that has for the current sample: Total valid aircraft count Vidible aircraft count Will be less than total if the screen hasn't enough lines to show them all. Max RSSI Min RSSI Mean RSSI Max Distance Tot: 47 Vis: 47 RSSI: Max 25.4+ Mean -29.5 Min -36.9- MaxD: 197.3nm+ * Add max distance and min/max RSSI indicators A '+' after the distance in a row indicates it's the row with the maximum distance. A '+' after the RSSI in a row indicates it's the row with the highest RSSI. A '-' after the RSSI in a row indicates it's the row with the lowest RSSI. The summary line at the top of the screen always shows the values for ALL aircraft, even those not visible. The row indicators only mark visible rows though. In this example, the first aircraft is both the farthest away and has the weakest RSSI. The second aircraft has the strongest RSSI. Tot: 47 Vis: 47 RSSI: Max 25.4+ Mean -29.5 Min -36.9- MaxD: 197.3nm+ - Hex Mode Sqwk Flight Alt Spd Hdg Dist(nm) Bearing RSSI Msgs Ti ──────────────────────────────────────────────────────────────────────────────── A8D5A4 S2 34000 438 252 197.3+ 85 -36.1- 26 2 A39A13 S2ac 5740 FFT525 30750 439 256 98.8 68 -25.4+ 123 0 A70B23 S2ac 2744 LXJ553 43000 419 258 136.1 39 -33.6 174 0 * Finally, a new option '--interactive-callsign-filter' has been added to allow filtering interactive by callsign. The value can be a simple string, in which case aircraft with that string anywhere in its callsign will be displayed, or a regular expression should you want a more precise match. Examples: --interactive-callsign-filter UAL will match all aircraft with UAL anywhere in its callsign. --interactive-callsign-filter "^UAL" will match only those callsigns that start with UAL. --interactive-callsign-filter "^(UAL|AAL)" will match only those callsigns that start with UAL or AAL. --interactive-callsign-filter "^N[0-9]" or "^N[[:digit:]]" will match only those callsigns that start with "N" and a number If you need more info on regular expressions, see this link: https://en.wikipedia.org/wiki/Regular_expression
2020-09-21 22:00:44 +00:00
/* Great Circle distance in m */
double greatcircle(double lat0, double lon0, double lat1, double lon1);
/* Get bearing from 2 points */
double get_bearing(double lat0, double lon0, double lat1, double lon1);
#endif