bds08
This commit is contained in:
parent
c804cd876c
commit
b503beb3fd
235
pyModeS/c_decoder/adsb.pyx
Normal file
235
pyModeS/c_decoder/adsb.pyx
Normal file
@ -0,0 +1,235 @@
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
# cython: language_level=3
|
||||
|
||||
"""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 libc.math cimport NAN as nan
|
||||
|
||||
# from pyModeS.decoder.bds import bds05, bds06, bds09
|
||||
from .common cimport typecode, icao as c_icao, df, hex2bin, bin2int, char_to_int
|
||||
|
||||
from .bds.bds05 import (
|
||||
airborne_position,
|
||||
airborne_position_with_ref,
|
||||
altitude,
|
||||
)
|
||||
from .bds.bds06 import (
|
||||
surface_position,
|
||||
surface_position_with_ref,
|
||||
surface_velocity,
|
||||
)
|
||||
from .bds.bds08 import category, callsign
|
||||
from pyModeS.decoder.bds.bds09 import airborne_velocity, altitude_diff
|
||||
|
||||
def icao(bytes msg):
|
||||
return c_icao(msg)
|
||||
|
||||
def position(bytes msg0 not None, bytes msg1 not None, int t0, int t1, double lat_ref=nan, double lon_ref=nan):
|
||||
"""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
|
||||
"""
|
||||
cdef int tc0 = typecode(msg0)
|
||||
cdef int tc1 = typecode(msg1)
|
||||
|
||||
if 5 <= tc0 <= 8 and 5 <= tc1 <= 8:
|
||||
if (lat_ref != lat_ref) or (lon_ref != 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(bytes msg not None, double lat_ref, double 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
|
||||
"""
|
||||
|
||||
cdef int 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(bytes msg):
|
||||
"""Decode aircraft altitude
|
||||
|
||||
Args:
|
||||
msg (string): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
int: altitude in feet
|
||||
"""
|
||||
|
||||
cdef int 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
|
||||
|
||||
cdef bytearray msgbin = hex2bin(msg)
|
||||
cdef int q = char_to_int(msgbin[47])
|
||||
cdef int n
|
||||
cdef double alt
|
||||
if q:
|
||||
n = bin2int(msgbin[40:47] + msgbin[48:52])
|
||||
alt = n * 25 - 1000
|
||||
return alt
|
||||
else:
|
||||
return nan
|
||||
|
||||
|
||||
def velocity(bytes msg, bint 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.
|
||||
"""
|
||||
|
||||
cdef int tc = typecode(msg)
|
||||
|
||||
if 5 <= tc <= 8:
|
||||
return surface_velocity(msg, rtn_sources)
|
||||
|
||||
elif tc == 19:
|
||||
return airborne_velocity(msg, rtn_sources)
|
||||
|
||||
else:
|
||||
raise RuntimeError(
|
||||
"incorrect or inconsistant message types, expecting 4<TC<9 or TC=19"
|
||||
)
|
||||
|
||||
|
||||
def speed_heading(bytes msg):
|
||||
"""Get speed and ground track (or heading) from the velocity message
|
||||
(handles both airborne or surface message)
|
||||
|
||||
Args:
|
||||
msg (string): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
(int, float): speed (kt), ground track or heading (degree)
|
||||
"""
|
||||
spd, trk_or_hdg, rocd, tag = velocity(msg)
|
||||
return spd, trk_or_hdg
|
||||
|
||||
|
||||
def oe_flag(bytes msg):
|
||||
"""Check the odd/even flag. Bit 54, 0 for even, 1 for odd.
|
||||
Args:
|
||||
msg (string): 28 bytes hexadecimal message string
|
||||
Returns:
|
||||
int: 0 or 1, for even or odd frame
|
||||
"""
|
||||
cdef bytearray msgbin = hex2bin(msg.encode())
|
||||
return char_to_int(msgbin[53])
|
||||
|
||||
|
||||
def version(bytes msg):
|
||||
"""ADS-B Version
|
||||
|
||||
Args:
|
||||
msg (string): 28 bytes hexadecimal message string, TC = 31
|
||||
|
||||
Returns:
|
||||
int: version number
|
||||
"""
|
||||
cdef int tc = typecode(msg)
|
||||
|
||||
if tc != 31:
|
||||
raise RuntimeError(
|
||||
"%s: Not a status operation message, expecting TC = 31" % msg
|
||||
)
|
||||
|
||||
cdef bytearray msgbin = hex2bin(msg)
|
||||
cdef int version = bin2int(msgbin[72:75])
|
||||
|
||||
return version
|
@ -25,7 +25,7 @@
|
||||
cimport cython
|
||||
|
||||
from .. cimport common
|
||||
from libc.math cimport NAN as nan, remainder
|
||||
from libc.math cimport NAN as nan
|
||||
|
||||
|
||||
@cython.cdivision(True)
|
||||
|
@ -26,7 +26,7 @@ cimport cython
|
||||
|
||||
from .. cimport common
|
||||
from cpython cimport array
|
||||
from libc.math cimport NAN as nan, remainder
|
||||
from libc.math cimport NAN as nan
|
||||
|
||||
import math
|
||||
|
||||
|
61
pyModeS/c_decoder/bds/bds08.pyx
Normal file
61
pyModeS/c_decoder/bds/bds08.pyx
Normal file
@ -0,0 +1,61 @@
|
||||
# cython: language_level=3
|
||||
|
||||
cimport cython
|
||||
|
||||
from .. cimport common
|
||||
|
||||
|
||||
def category(bytes msg):
|
||||
"""Aircraft category number
|
||||
|
||||
Args:
|
||||
msg (string): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
int: category number
|
||||
"""
|
||||
|
||||
cdef int tc = common.typecode(msg)
|
||||
if tc < 1 or tc > 4:
|
||||
raise RuntimeError("%s: Not a identification message" % msg)
|
||||
|
||||
cdef bytearray msgbin = common.hex2bin(msg)
|
||||
mebin = msgbin[32:87]
|
||||
return common.bin2int(mebin[5:8])
|
||||
|
||||
|
||||
def callsign(bytes msg):
|
||||
"""Aircraft callsign
|
||||
|
||||
Args:
|
||||
msg (string): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
string: callsign
|
||||
"""
|
||||
|
||||
cdef int tc = common.typecode(msg)
|
||||
if tc < 1 or tc > 4:
|
||||
raise RuntimeError("%s: Not a identification message" % msg)
|
||||
|
||||
cdef bytearray _chars = bytearray(
|
||||
b"#ABCDEFGHIJKLMNOPQRSTUVWXYZ#####_###############0123456789######"
|
||||
)
|
||||
cdef unsigned char[:] chars = _chars
|
||||
cdef bytearray msgbin = common.hex2bin(msg)
|
||||
cdef bytearray csbin = msgbin[40:96]
|
||||
|
||||
cdef bytearray _cs = bytearray(8)
|
||||
cdef unsigned char[:] cs = _cs
|
||||
cs[0] = chars[common.bin2int(csbin[0:6])]
|
||||
cs[1] = chars[common.bin2int(csbin[6:12])]
|
||||
cs[2] = chars[common.bin2int(csbin[12:18])]
|
||||
cs[3] = chars[common.bin2int(csbin[18:24])]
|
||||
cs[4] = chars[common.bin2int(csbin[24:30])]
|
||||
cs[5] = chars[common.bin2int(csbin[30:36])]
|
||||
cs[6] = chars[common.bin2int(csbin[36:42])]
|
||||
cs[7] = chars[common.bin2int(csbin[42:48])]
|
||||
|
||||
# clean string, remove spaces and marks, if any.
|
||||
# cs = cs.replace('_', '')
|
||||
return _cs.decode().replace("#", "")
|
1
setup.py
1
setup.py
@ -24,6 +24,7 @@ extensions = [
|
||||
Extension("pyModeS.c_decoder.adsb", ["pyModeS/c_decoder/adsb.pyx"]),
|
||||
Extension("pyModeS.c_decoder.bds.bds05", ["pyModeS/c_decoder/bds/bds05.pyx"]),
|
||||
Extension("pyModeS.c_decoder.bds.bds06", ["pyModeS/c_decoder/bds/bds06.pyx"]),
|
||||
Extension("pyModeS.c_decoder.bds.bds08", ["pyModeS/c_decoder/bds/bds08.pyx"]),
|
||||
]
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user