# Copyright (C) 2015 Junzi Sun (TU Delft) # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program 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 . """ADS-B Wrapper. The ADS-B wrapper also imports functions from the following modules: - pyModeS.decoder.bds.bds05 Functions: ``airborne_position``, ``airborne_position_with_ref``, ``altitude`` - pyModeS.decoder.bds.bds06 Functions: ``surface_position``, ``surface_position_with_ref``, ``surface_velocity`` - pyModeS.decoder.bds.bds08 Functions: ``category``, ``callsign`` - pyModeS.decoder.bds.bds09 Functions: ``airborne_velocity``, ``altitude_diff`` """ from __future__ import absolute_import, print_function, division import pyModeS as pms from pyModeS.decoder import common from pyModeS.decoder import uncertainty # from pyModeS.decoder.bds import bds05, bds06, bds09 from pyModeS.decoder.bds.bds05 import airborne_position, airborne_position_with_ref, altitude from pyModeS.decoder.bds.bds06 import surface_position, surface_position_with_ref, surface_velocity from pyModeS.decoder.bds.bds08 import category, callsign from pyModeS.decoder.bds.bds09 import airborne_velocity, altitude_diff def df(msg): return common.df(msg) def icao(msg): return common.icao(msg) def typecode(msg): return common.typecode(msg) def position(msg0, msg1, t0, t1, lat_ref=None, lon_ref=None): """Decode position from a pair of even and odd position message (works with both airborne and surface position messages) Args: msg0 (string): even message (28 bytes hexadecimal string) msg1 (string): odd message (28 bytes hexadecimal string) t0 (int): timestamps for the even message t1 (int): timestamps for the odd message Returns: (float, float): (latitude, longitude) of the aircraft """ tc0 = typecode(msg0) tc1 = typecode(msg1) if (5<=tc0<=8 and 5<=tc1<=8): if (not lat_ref) or (not lon_ref): raise RuntimeError("Surface position encountered, a reference \ position lat/lon required. Location of \ receiver can be used.") else: return surface_position(msg0, msg1, t0, t1, lat_ref, lon_ref) elif (9<=tc0<=18 and 9<=tc1<=18): # Airborne position with barometric height return airborne_position(msg0, msg1, t0, t1) elif (20<=tc0<=22 and 20<=tc1<=22): # Airborne position with GNSS height return airborne_position(msg0, msg1, t0, t1) else: raise RuntimeError("incorrect or inconsistant message types") def position_with_ref(msg, lat_ref, lon_ref): """Decode position with only one message, knowing reference nearby location, such as previously calculated location, ground station, or airport location, etc. Works with both airborne and surface position messages. The reference position shall be with in 180NM (airborne) or 45NM (surface) of the true position. Args: msg (string): even message (28 bytes hexadecimal string) lat_ref: previous known latitude lon_ref: previous known longitude Returns: (float, float): (latitude, longitude) of the aircraft """ tc = typecode(msg) if 5<=tc<=8: return surface_position_with_ref(msg, lat_ref, lon_ref) elif 9<=tc<=18 or 20<=tc<=22: return airborne_position_with_ref(msg, lat_ref, lon_ref) else: raise RuntimeError("incorrect or inconsistant message types") def altitude(msg): """Decode aircraft altitude Args: msg (string): 28 bytes hexadecimal message string Returns: int: altitude in feet """ tc = typecode(msg) if tc<5 or tc==19 or tc>22: raise RuntimeError("%s: Not a position message" % msg) if tc>=5 and tc<=8: # surface position, altitude 0 return 0 msgbin = common.hex2bin(msg) q = msgbin[47] if q: n = common.bin2int(msgbin[40:47]+msgbin[48:52]) alt = n * 25 - 1000 return alt else: return None def velocity(msg, rtn_sources=False): """Calculate the speed, heading, and vertical rate (handles both airborne or surface message) Args: msg (string): 28 bytes hexadecimal message string rtn_source (boolean): If the function will return the sources for direction of travel and vertical rate. This will change the return value from a four element array to a six element array. Returns: (int, float, int, string, string, string): speed (kt), ground track or heading (degree), rate of climb/descent (ft/min), speed type ('GS' for ground speed, 'AS' for airspeed), direction source ('true_north' for ground track / true north as refrence, 'mag_north' for magnetic north as reference), rate of climb/descent source ('Baro' for barometer, 'GNSS' for GNSS constellation). In the case of surface messages, None will be put in place for vertical rate and its respective sources. """ if 5 <= typecode(msg) <= 8: return surface_velocity(msg, rtn_sources) elif typecode(msg) == 19: return airborne_velocity(msg, rtn_sources) else: raise RuntimeError("incorrect or inconsistant message types, expecting 4 22: raise RuntimeError( "%s: Not a surface position message (5 22: raise RuntimeError( "%s: Not a surface position message (5 22: raise RuntimeError( "%s: Not a surface position message (5 18: raise RuntimeError("%s: Not a airborne position message, expecting 8