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
|
cimport cython
|
||||||
|
|
||||||
from .. cimport common
|
from .. cimport common
|
||||||
from libc.math cimport NAN as nan, remainder
|
from libc.math cimport NAN as nan
|
||||||
|
|
||||||
|
|
||||||
@cython.cdivision(True)
|
@cython.cdivision(True)
|
||||||
|
@ -26,7 +26,7 @@ cimport cython
|
|||||||
|
|
||||||
from .. cimport common
|
from .. cimport common
|
||||||
from cpython cimport array
|
from cpython cimport array
|
||||||
from libc.math cimport NAN as nan, remainder
|
from libc.math cimport NAN as nan
|
||||||
|
|
||||||
import math
|
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.adsb", ["pyModeS/c_decoder/adsb.pyx"]),
|
||||||
Extension("pyModeS.c_decoder.bds.bds05", ["pyModeS/c_decoder/bds/bds05.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.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