reformat code with Black
This commit is contained in:
@@ -12,4 +12,5 @@ from .extra import tcpclient
|
|||||||
# from .decoder import ehs # depricated
|
# from .decoder import ehs # depricated
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
dirpath = os.path.dirname(os.path.realpath(__file__))
|
dirpath = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|||||||
+80
-45
@@ -35,20 +35,32 @@ from pyModeS.decoder import common
|
|||||||
from pyModeS.decoder import uncertainty
|
from pyModeS.decoder import uncertainty
|
||||||
|
|
||||||
# from pyModeS.decoder.bds import bds05, bds06, bds09
|
# 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.bds05 import (
|
||||||
from pyModeS.decoder.bds.bds06 import surface_position, surface_position_with_ref, surface_velocity
|
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.bds08 import category, callsign
|
||||||
from pyModeS.decoder.bds.bds09 import airborne_velocity, altitude_diff
|
from pyModeS.decoder.bds.bds09 import airborne_velocity, altitude_diff
|
||||||
|
|
||||||
|
|
||||||
def df(msg):
|
def df(msg):
|
||||||
return common.df(msg)
|
return common.df(msg)
|
||||||
|
|
||||||
|
|
||||||
def icao(msg):
|
def icao(msg):
|
||||||
return common.icao(msg)
|
return common.icao(msg)
|
||||||
|
|
||||||
|
|
||||||
def typecode(msg):
|
def typecode(msg):
|
||||||
return common.typecode(msg)
|
return common.typecode(msg)
|
||||||
|
|
||||||
|
|
||||||
def position(msg0, msg1, t0, t1, lat_ref=None, lon_ref=None):
|
def position(msg0, msg1, t0, t1, lat_ref=None, lon_ref=None):
|
||||||
"""Decode position from a pair of even and odd position message
|
"""Decode position from a pair of even and odd position message
|
||||||
(works with both airborne and surface position messages)
|
(works with both airborne and surface position messages)
|
||||||
@@ -65,19 +77,21 @@ def position(msg0, msg1, t0, t1, lat_ref=None, lon_ref=None):
|
|||||||
tc0 = typecode(msg0)
|
tc0 = typecode(msg0)
|
||||||
tc1 = typecode(msg1)
|
tc1 = typecode(msg1)
|
||||||
|
|
||||||
if (5<=tc0<=8 and 5<=tc1<=8):
|
if 5 <= tc0 <= 8 and 5 <= tc1 <= 8:
|
||||||
if (not lat_ref) or (not lon_ref):
|
if (not lat_ref) or (not lon_ref):
|
||||||
raise RuntimeError("Surface position encountered, a reference \
|
raise RuntimeError(
|
||||||
|
"Surface position encountered, a reference \
|
||||||
position lat/lon required. Location of \
|
position lat/lon required. Location of \
|
||||||
receiver can be used.")
|
receiver can be used."
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return surface_position(msg0, msg1, t0, t1, lat_ref, lon_ref)
|
return surface_position(msg0, msg1, t0, t1, lat_ref, lon_ref)
|
||||||
|
|
||||||
elif (9<=tc0<=18 and 9<=tc1<=18):
|
elif 9 <= tc0 <= 18 and 9 <= tc1 <= 18:
|
||||||
# Airborne position with barometric height
|
# Airborne position with barometric height
|
||||||
return airborne_position(msg0, msg1, t0, t1)
|
return airborne_position(msg0, msg1, t0, t1)
|
||||||
|
|
||||||
elif (20<=tc0<=22 and 20<=tc1<=22):
|
elif 20 <= tc0 <= 22 and 20 <= tc1 <= 22:
|
||||||
# Airborne position with GNSS height
|
# Airborne position with GNSS height
|
||||||
return airborne_position(msg0, msg1, t0, t1)
|
return airborne_position(msg0, msg1, t0, t1)
|
||||||
|
|
||||||
@@ -104,10 +118,10 @@ def position_with_ref(msg, lat_ref, lon_ref):
|
|||||||
|
|
||||||
tc = typecode(msg)
|
tc = typecode(msg)
|
||||||
|
|
||||||
if 5<=tc<=8:
|
if 5 <= tc <= 8:
|
||||||
return surface_position_with_ref(msg, lat_ref, lon_ref)
|
return surface_position_with_ref(msg, lat_ref, lon_ref)
|
||||||
|
|
||||||
elif 9<=tc<=18 or 20<=tc<=22:
|
elif 9 <= tc <= 18 or 20 <= tc <= 22:
|
||||||
return airborne_position_with_ref(msg, lat_ref, lon_ref)
|
return airborne_position_with_ref(msg, lat_ref, lon_ref)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@@ -126,17 +140,17 @@ def altitude(msg):
|
|||||||
|
|
||||||
tc = typecode(msg)
|
tc = typecode(msg)
|
||||||
|
|
||||||
if tc<5 or tc==19 or tc>22:
|
if tc < 5 or tc == 19 or tc > 22:
|
||||||
raise RuntimeError("%s: Not a position message" % msg)
|
raise RuntimeError("%s: Not a position message" % msg)
|
||||||
|
|
||||||
if tc>=5 and tc<=8:
|
if tc >= 5 and tc <= 8:
|
||||||
# surface position, altitude 0
|
# surface position, altitude 0
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
q = msgbin[47]
|
q = msgbin[47]
|
||||||
if q:
|
if q:
|
||||||
n = common.bin2int(msgbin[40:47]+msgbin[48:52])
|
n = common.bin2int(msgbin[40:47] + msgbin[48:52])
|
||||||
alt = n * 25 - 1000
|
alt = n * 25 - 1000
|
||||||
return alt
|
return alt
|
||||||
else:
|
else:
|
||||||
@@ -175,7 +189,9 @@ def velocity(msg, rtn_sources=False):
|
|||||||
return airborne_velocity(msg, rtn_sources)
|
return airborne_velocity(msg, rtn_sources)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("incorrect or inconsistant message types, expecting 4<TC<9 or TC=19")
|
raise RuntimeError(
|
||||||
|
"incorrect or inconsistant message types, expecting 4<TC<9 or TC=19"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def speed_heading(msg):
|
def speed_heading(msg):
|
||||||
@@ -215,7 +231,9 @@ def version(msg):
|
|||||||
tc = typecode(msg)
|
tc = typecode(msg)
|
||||||
|
|
||||||
if tc != 31:
|
if tc != 31:
|
||||||
raise RuntimeError("%s: Not a status operation message, expecting TC = 31" % msg)
|
raise RuntimeError(
|
||||||
|
"%s: Not a status operation message, expecting TC = 31" % msg
|
||||||
|
)
|
||||||
|
|
||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
version = common.bin2int(msgbin[72:75])
|
version = common.bin2int(msgbin[72:75])
|
||||||
@@ -241,18 +259,18 @@ def nuc_p(msg):
|
|||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"%s: Not a surface position message (5<TC<8), \
|
"%s: Not a surface position message (5<TC<8), \
|
||||||
airborne position message (8<TC<19), \
|
airborne position message (8<TC<19), \
|
||||||
or airborne position with GNSS height (20<TC<22)" % msg
|
or airborne position with GNSS height (20<TC<22)"
|
||||||
|
% msg
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
NUCp = uncertainty.TC_NUCp_lookup[tc]
|
NUCp = uncertainty.TC_NUCp_lookup[tc]
|
||||||
HPL = uncertainty.NUCp[NUCp]['HPL']
|
HPL = uncertainty.NUCp[NUCp]["HPL"]
|
||||||
RCu = uncertainty.NUCp[NUCp]['RCu']
|
RCu = uncertainty.NUCp[NUCp]["RCu"]
|
||||||
RCv = uncertainty.NUCp[NUCp]['RCv']
|
RCv = uncertainty.NUCp[NUCp]["RCv"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
HPL, RCu, RCv = uncertainty.NA, uncertainty.NA, uncertainty.NA
|
HPL, RCu, RCv = uncertainty.NA, uncertainty.NA, uncertainty.NA
|
||||||
|
|
||||||
|
|
||||||
if tc in [20, 21]:
|
if tc in [20, 21]:
|
||||||
RCv = uncertainty.NA
|
RCv = uncertainty.NA
|
||||||
|
|
||||||
@@ -272,15 +290,16 @@ def nuc_v(msg):
|
|||||||
tc = typecode(msg)
|
tc = typecode(msg)
|
||||||
|
|
||||||
if tc != 19:
|
if tc != 19:
|
||||||
raise RuntimeError("%s: Not an airborne velocity message, expecting TC = 19" % msg)
|
raise RuntimeError(
|
||||||
|
"%s: Not an airborne velocity message, expecting TC = 19" % msg
|
||||||
|
)
|
||||||
|
|
||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
NUCv = common.bin2int(msgbin[42:45])
|
NUCv = common.bin2int(msgbin[42:45])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
HVE = uncertainty.NUCv[NUCv]['HVE']
|
HVE = uncertainty.NUCv[NUCv]["HVE"]
|
||||||
VVE = uncertainty.NUCv[NUCv]['VVE']
|
VVE = uncertainty.NUCv[NUCv]["VVE"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
HVE, VVE = uncertainty.NA, uncertainty.NA
|
HVE, VVE = uncertainty.NA, uncertainty.NA
|
||||||
|
|
||||||
@@ -302,7 +321,8 @@ def nic_v1(msg, NICs):
|
|||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"%s: Not a surface position message (5<TC<8), \
|
"%s: Not a surface position message (5<TC<8), \
|
||||||
airborne position message (8<TC<19), \
|
airborne position message (8<TC<19), \
|
||||||
or airborne position with GNSS height (20<TC<22)" % msg
|
or airborne position with GNSS height (20<TC<22)"
|
||||||
|
% msg
|
||||||
)
|
)
|
||||||
|
|
||||||
tc = typecode(msg)
|
tc = typecode(msg)
|
||||||
@@ -312,8 +332,8 @@ def nic_v1(msg, NICs):
|
|||||||
NIC = NIC[NICs]
|
NIC = NIC[NICs]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
Rc = uncertainty.NICv1[NIC][NICs]['Rc']
|
Rc = uncertainty.NICv1[NIC][NICs]["Rc"]
|
||||||
VPL = uncertainty.NICv1[NIC][NICs]['VPL']
|
VPL = uncertainty.NICv1[NIC][NICs]["VPL"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
Rc, VPL = uncertainty.NA, uncertainty.NA
|
Rc, VPL = uncertainty.NA, uncertainty.NA
|
||||||
|
|
||||||
@@ -335,22 +355,23 @@ def nic_v2(msg, NICa, NICbc):
|
|||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"%s: Not a surface position message (5<TC<8), \
|
"%s: Not a surface position message (5<TC<8), \
|
||||||
airborne position message (8<TC<19), \
|
airborne position message (8<TC<19), \
|
||||||
or airborne position with GNSS height (20<TC<22)" % msg
|
or airborne position with GNSS height (20<TC<22)"
|
||||||
|
% msg
|
||||||
)
|
)
|
||||||
|
|
||||||
tc = typecode(msg)
|
tc = typecode(msg)
|
||||||
NIC = uncertainty.TC_NICv2_lookup[tc]
|
NIC = uncertainty.TC_NICv2_lookup[tc]
|
||||||
|
|
||||||
if 20<=tc<=22:
|
if 20 <= tc <= 22:
|
||||||
NICs = 0
|
NICs = 0
|
||||||
else:
|
else:
|
||||||
NICs = NICa*2 + NICbc
|
NICs = NICa * 2 + NICbc
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if isinstance(NIC, dict):
|
if isinstance(NIC, dict):
|
||||||
NIC = NIC[NICs]
|
NIC = NIC[NICs]
|
||||||
|
|
||||||
Rc = uncertainty.NICv2[NIC][NICs]['Rc']
|
Rc = uncertainty.NICv2[NIC][NICs]["Rc"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
Rc = uncertainty.NA
|
Rc = uncertainty.NA
|
||||||
|
|
||||||
@@ -369,7 +390,9 @@ def nic_s(msg):
|
|||||||
tc = typecode(msg)
|
tc = typecode(msg)
|
||||||
|
|
||||||
if tc != 31:
|
if tc != 31:
|
||||||
raise RuntimeError("%s: Not a status operation message, expecting TC = 31" % msg)
|
raise RuntimeError(
|
||||||
|
"%s: Not a status operation message, expecting TC = 31" % msg
|
||||||
|
)
|
||||||
|
|
||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
nic_s = int(msgbin[75])
|
nic_s = int(msgbin[75])
|
||||||
@@ -389,7 +412,9 @@ def nic_a_c(msg):
|
|||||||
tc = typecode(msg)
|
tc = typecode(msg)
|
||||||
|
|
||||||
if tc != 31:
|
if tc != 31:
|
||||||
raise RuntimeError("%s: Not a status operation message, expecting TC = 31" % msg)
|
raise RuntimeError(
|
||||||
|
"%s: Not a status operation message, expecting TC = 31" % msg
|
||||||
|
)
|
||||||
|
|
||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
nic_a = int(msgbin[75])
|
nic_a = int(msgbin[75])
|
||||||
@@ -410,7 +435,9 @@ def nic_b(msg):
|
|||||||
tc = typecode(msg)
|
tc = typecode(msg)
|
||||||
|
|
||||||
if tc < 9 or tc > 18:
|
if tc < 9 or tc > 18:
|
||||||
raise RuntimeError("%s: Not a airborne position message, expecting 8<TC<19" % msg)
|
raise RuntimeError(
|
||||||
|
"%s: Not a airborne position message, expecting 8<TC<19" % msg
|
||||||
|
)
|
||||||
|
|
||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
nic_b = int(msgbin[39])
|
nic_b = int(msgbin[39])
|
||||||
@@ -431,8 +458,11 @@ def nac_p(msg):
|
|||||||
tc = typecode(msg)
|
tc = typecode(msg)
|
||||||
|
|
||||||
if tc not in [29, 31]:
|
if tc not in [29, 31]:
|
||||||
raise RuntimeError("%s: Not a target state and status message, \
|
raise RuntimeError(
|
||||||
or operation status message, expecting TC = 29 or 31" % msg)
|
"%s: Not a target state and status message, \
|
||||||
|
or operation status message, expecting TC = 29 or 31"
|
||||||
|
% msg
|
||||||
|
)
|
||||||
|
|
||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
|
|
||||||
@@ -442,8 +472,8 @@ def nac_p(msg):
|
|||||||
NACp = common.bin2int(msgbin[76:80])
|
NACp = common.bin2int(msgbin[76:80])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
EPU = uncertainty.NACp[NACp]['EPU']
|
EPU = uncertainty.NACp[NACp]["EPU"]
|
||||||
VEPU = uncertainty.NACp[NACp]['VEPU']
|
VEPU = uncertainty.NACp[NACp]["VEPU"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
EPU, VEPU = uncertainty.NA, uncertainty.NA
|
EPU, VEPU = uncertainty.NA, uncertainty.NA
|
||||||
|
|
||||||
@@ -463,14 +493,16 @@ def nac_v(msg):
|
|||||||
tc = typecode(msg)
|
tc = typecode(msg)
|
||||||
|
|
||||||
if tc != 19:
|
if tc != 19:
|
||||||
raise RuntimeError("%s: Not an airborne velocity message, expecting TC = 19" % msg)
|
raise RuntimeError(
|
||||||
|
"%s: Not an airborne velocity message, expecting TC = 19" % msg
|
||||||
|
)
|
||||||
|
|
||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
NACv = common.bin2int(msgbin[42:45])
|
NACv = common.bin2int(msgbin[42:45])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
HFOMr = uncertainty.NACv[NACv]['HFOMr']
|
HFOMr = uncertainty.NACv[NACv]["HFOMr"]
|
||||||
VFOMr = uncertainty.NACv[NACv]['VFOMr']
|
VFOMr = uncertainty.NACv[NACv]["VFOMr"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
HFOMr, VFOMr = uncertainty.NA, uncertainty.NA
|
HFOMr, VFOMr = uncertainty.NA, uncertainty.NA
|
||||||
|
|
||||||
@@ -491,8 +523,11 @@ def sil(msg, version):
|
|||||||
tc = typecode(msg)
|
tc = typecode(msg)
|
||||||
|
|
||||||
if tc not in [29, 31]:
|
if tc not in [29, 31]:
|
||||||
raise RuntimeError("%s: Not a target state and status messag, \
|
raise RuntimeError(
|
||||||
or operation status message, expecting TC = 29 or 31" % msg)
|
"%s: Not a target state and status messag, \
|
||||||
|
or operation status message, expecting TC = 29 or 31"
|
||||||
|
% msg
|
||||||
|
)
|
||||||
|
|
||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
|
|
||||||
@@ -502,12 +537,12 @@ def sil(msg, version):
|
|||||||
SIL = common.bin2int(msgbin[82:84])
|
SIL = common.bin2int(msgbin[82:84])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
PE_RCu = uncertainty.SIL[SIL]['PE_RCu']
|
PE_RCu = uncertainty.SIL[SIL]["PE_RCu"]
|
||||||
PE_VPL = uncertainty.SIL[SIL]['PE_VPL']
|
PE_VPL = uncertainty.SIL[SIL]["PE_VPL"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
PE_RCu, PE_VPL = uncertainty.NA, uncertainty.NA
|
PE_RCu, PE_VPL = uncertainty.NA, uncertainty.NA
|
||||||
|
|
||||||
base = 'unknown'
|
base = "unknown"
|
||||||
|
|
||||||
if version == 2:
|
if version == 2:
|
||||||
if tc == 29:
|
if tc == 29:
|
||||||
|
|||||||
@@ -23,8 +23,22 @@ import numpy as np
|
|||||||
|
|
||||||
from pyModeS.extra import aero
|
from pyModeS.extra import aero
|
||||||
from pyModeS.decoder import common
|
from pyModeS.decoder import common
|
||||||
from pyModeS.decoder.bds import bds05, bds06, bds08, bds09, \
|
from pyModeS.decoder.bds import (
|
||||||
bds10, bds17, bds20, bds30, bds40, bds44, bds45, bds50, bds53, bds60
|
bds05,
|
||||||
|
bds06,
|
||||||
|
bds08,
|
||||||
|
bds09,
|
||||||
|
bds10,
|
||||||
|
bds17,
|
||||||
|
bds20,
|
||||||
|
bds30,
|
||||||
|
bds40,
|
||||||
|
bds44,
|
||||||
|
bds45,
|
||||||
|
bds50,
|
||||||
|
bds53,
|
||||||
|
bds60,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def is50or60(msg, spd_ref, trk_ref, alt_ref):
|
def is50or60(msg, spd_ref, trk_ref, alt_ref):
|
||||||
@@ -40,6 +54,7 @@ def is50or60(msg, spd_ref, trk_ref, alt_ref):
|
|||||||
String or None: BDS version, or possible versions, or None if nothing matches.
|
String or None: BDS version, or possible versions, or None if nothing matches.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def vxy(v, angle):
|
def vxy(v, angle):
|
||||||
vx = v * np.sin(np.radians(angle))
|
vx = v * np.sin(np.radians(angle))
|
||||||
vy = v * np.cos(np.radians(angle))
|
vy = v * np.cos(np.radians(angle))
|
||||||
@@ -52,26 +67,26 @@ def is50or60(msg, spd_ref, trk_ref, alt_ref):
|
|||||||
v50 = bds50.gs50(msg)
|
v50 = bds50.gs50(msg)
|
||||||
|
|
||||||
if h50 is None or v50 is None:
|
if h50 is None or v50 is None:
|
||||||
return 'BDS50,BDS60'
|
return "BDS50,BDS60"
|
||||||
|
|
||||||
h60 = bds60.hdg60(msg)
|
h60 = bds60.hdg60(msg)
|
||||||
m60 = bds60.mach60(msg)
|
m60 = bds60.mach60(msg)
|
||||||
i60 = bds60.ias60(msg)
|
i60 = bds60.ias60(msg)
|
||||||
|
|
||||||
if h60 is None or (m60 is None and i60 is None):
|
if h60 is None or (m60 is None and i60 is None):
|
||||||
return 'BDS50,BDS60'
|
return "BDS50,BDS60"
|
||||||
|
|
||||||
m60 = np.nan if m60 is None else m60
|
m60 = np.nan if m60 is None else m60
|
||||||
i60 = np.nan if i60 is None else i60
|
i60 = np.nan if i60 is None else i60
|
||||||
|
|
||||||
XY5 = vxy(v50*aero.kts, h50)
|
XY5 = vxy(v50 * aero.kts, h50)
|
||||||
XY6m = vxy(aero.mach2tas(m60, alt_ref*aero.ft), h60)
|
XY6m = vxy(aero.mach2tas(m60, alt_ref * aero.ft), h60)
|
||||||
XY6i = vxy(aero.cas2tas(i60*aero.kts, alt_ref*aero.ft), h60)
|
XY6i = vxy(aero.cas2tas(i60 * aero.kts, alt_ref * aero.ft), h60)
|
||||||
|
|
||||||
allbds = ['BDS50', 'BDS60', 'BDS60']
|
allbds = ["BDS50", "BDS60", "BDS60"]
|
||||||
|
|
||||||
X = np.array([XY5, XY6m, XY6i])
|
X = np.array([XY5, XY6m, XY6i])
|
||||||
Mu = np.array(vxy(spd_ref*aero.kts, trk_ref))
|
Mu = np.array(vxy(spd_ref * aero.kts, trk_ref))
|
||||||
|
|
||||||
# compute Mahalanobis distance matrix
|
# compute Mahalanobis distance matrix
|
||||||
# Cov = [[20**2, 0], [0, 20**2]]
|
# Cov = [[20**2, 0], [0, 20**2]]
|
||||||
@@ -81,10 +96,10 @@ def is50or60(msg, spd_ref, trk_ref, alt_ref):
|
|||||||
# since the covariance matrix is identity matrix,
|
# since the covariance matrix is identity matrix,
|
||||||
# M-dist is same as eculidian distance
|
# M-dist is same as eculidian distance
|
||||||
try:
|
try:
|
||||||
dist = np.linalg.norm(X-Mu, axis=1)
|
dist = np.linalg.norm(X - Mu, axis=1)
|
||||||
BDS = allbds[np.nanargmin(dist)]
|
BDS = allbds[np.nanargmin(dist)]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return 'BDS50,BDS60'
|
return "BDS50,BDS60"
|
||||||
|
|
||||||
return BDS
|
return BDS
|
||||||
|
|
||||||
@@ -103,28 +118,28 @@ def infer(msg, mrar=False):
|
|||||||
df = common.df(msg)
|
df = common.df(msg)
|
||||||
|
|
||||||
if common.allzeros(msg):
|
if common.allzeros(msg):
|
||||||
return 'EMPTY'
|
return "EMPTY"
|
||||||
|
|
||||||
# For ADS-B / Mode-S extended squitter
|
# For ADS-B / Mode-S extended squitter
|
||||||
if df == 17:
|
if df == 17:
|
||||||
tc = common.typecode(msg)
|
tc = common.typecode(msg)
|
||||||
|
|
||||||
if 1 <= tc <= 4:
|
if 1 <= tc <= 4:
|
||||||
return 'BDS08' # indentification and category
|
return "BDS08" # indentification and category
|
||||||
if 5 <= tc <= 8:
|
if 5 <= tc <= 8:
|
||||||
return 'BDS06' # surface movement
|
return "BDS06" # surface movement
|
||||||
if 9 <= tc <= 18:
|
if 9 <= tc <= 18:
|
||||||
return 'BDS05' # airborne position, baro-alt
|
return "BDS05" # airborne position, baro-alt
|
||||||
if tc == 19:
|
if tc == 19:
|
||||||
return 'BDS09' # airborne velocity
|
return "BDS09" # airborne velocity
|
||||||
if 20 <= tc <= 22:
|
if 20 <= tc <= 22:
|
||||||
return 'BDS05' # airborne position, gnss-alt
|
return "BDS05" # airborne position, gnss-alt
|
||||||
if tc == 28:
|
if tc == 28:
|
||||||
return 'BDS61' # aircraft status
|
return "BDS61" # aircraft status
|
||||||
if tc == 29:
|
if tc == 29:
|
||||||
return 'BDS62' # target state and status
|
return "BDS62" # target state and status
|
||||||
if tc == 31:
|
if tc == 31:
|
||||||
return 'BDS65' # operational status
|
return "BDS65" # operational status
|
||||||
|
|
||||||
# For Comm-B replies
|
# For Comm-B replies
|
||||||
IS10 = bds10.is10(msg)
|
IS10 = bds10.is10(msg)
|
||||||
@@ -138,15 +153,27 @@ def infer(msg, mrar=False):
|
|||||||
IS45 = bds45.is45(msg)
|
IS45 = bds45.is45(msg)
|
||||||
|
|
||||||
if mrar:
|
if mrar:
|
||||||
allbds = np.array(["BDS10", "BDS17", "BDS20", "BDS30", "BDS40",
|
allbds = np.array(
|
||||||
"BDS44", "BDS45", "BDS50", "BDS60"])
|
[
|
||||||
|
"BDS10",
|
||||||
|
"BDS17",
|
||||||
|
"BDS20",
|
||||||
|
"BDS30",
|
||||||
|
"BDS40",
|
||||||
|
"BDS44",
|
||||||
|
"BDS45",
|
||||||
|
"BDS50",
|
||||||
|
"BDS60",
|
||||||
|
]
|
||||||
|
)
|
||||||
mask = [IS10, IS17, IS20, IS30, IS40, IS44, IS45, IS50, IS60]
|
mask = [IS10, IS17, IS20, IS30, IS40, IS44, IS45, IS50, IS60]
|
||||||
else:
|
else:
|
||||||
allbds = np.array(["BDS10", "BDS17", "BDS20", "BDS30", "BDS40",
|
allbds = np.array(
|
||||||
"BDS50", "BDS60"])
|
["BDS10", "BDS17", "BDS20", "BDS30", "BDS40", "BDS50", "BDS60"]
|
||||||
|
)
|
||||||
mask = [IS10, IS17, IS20, IS30, IS40, IS50, IS60]
|
mask = [IS10, IS17, IS20, IS30, IS40, IS50, IS60]
|
||||||
|
|
||||||
bds = ','.join(sorted(allbds[mask]))
|
bds = ",".join(sorted(allbds[mask]))
|
||||||
|
|
||||||
if len(bds) == 0:
|
if len(bds) == 0:
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -73,17 +73,17 @@ def surface_position(msg0, msg1, t0, t1, lat_ref, lon_ref):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
# compute ni, longitude index m, and longitude
|
# compute ni, longitude index m, and longitude
|
||||||
if (t0 > t1):
|
if t0 > t1:
|
||||||
lat = lat_even
|
lat = lat_even
|
||||||
nl = common.cprNL(lat_even)
|
nl = common.cprNL(lat_even)
|
||||||
ni = max(common.cprNL(lat_even) - 0, 1)
|
ni = max(common.cprNL(lat_even) - 0, 1)
|
||||||
m = common.floor(cprlon_even * (nl-1) - cprlon_odd * nl + 0.5)
|
m = common.floor(cprlon_even * (nl - 1) - cprlon_odd * nl + 0.5)
|
||||||
lon = (90.0 / ni) * (m % ni + cprlon_even)
|
lon = (90.0 / ni) * (m % ni + cprlon_even)
|
||||||
else:
|
else:
|
||||||
lat = lat_odd
|
lat = lat_odd
|
||||||
nl = common.cprNL(lat_odd)
|
nl = common.cprNL(lat_odd)
|
||||||
ni = max(common.cprNL(lat_odd) - 1, 1)
|
ni = max(common.cprNL(lat_odd) - 1, 1)
|
||||||
m = common.floor(cprlon_even * (nl-1) - cprlon_odd * nl + 0.5)
|
m = common.floor(cprlon_even * (nl - 1) - cprlon_odd * nl + 0.5)
|
||||||
lon = (90.0 / ni) * (m % ni + cprlon_odd)
|
lon = (90.0 / ni) * (m % ni + cprlon_odd)
|
||||||
|
|
||||||
# four possible longitude solutions
|
# four possible longitude solutions
|
||||||
@@ -112,17 +112,17 @@ def surface_position_with_ref(msg, lat_ref, lon_ref):
|
|||||||
(float, float): (latitude, longitude) of the aircraft
|
(float, float): (latitude, longitude) of the aircraft
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
mb = common.hex2bin(msg)[32:]
|
mb = common.hex2bin(msg)[32:]
|
||||||
|
|
||||||
cprlat = common.bin2int(mb[22:39]) / 131072.0
|
cprlat = common.bin2int(mb[22:39]) / 131072.0
|
||||||
cprlon = common.bin2int(mb[39:56]) / 131072.0
|
cprlon = common.bin2int(mb[39:56]) / 131072.0
|
||||||
|
|
||||||
i = int(mb[21])
|
i = int(mb[21])
|
||||||
d_lat = 90.0/59 if i else 90.0/60
|
d_lat = 90.0 / 59 if i else 90.0 / 60
|
||||||
|
|
||||||
j = common.floor(lat_ref / d_lat) \
|
j = common.floor(lat_ref / d_lat) + common.floor(
|
||||||
+ common.floor(0.5 + ((lat_ref % d_lat) / d_lat) - cprlat)
|
0.5 + ((lat_ref % d_lat) / d_lat) - cprlat
|
||||||
|
)
|
||||||
|
|
||||||
lat = d_lat * (j + cprlat)
|
lat = d_lat * (j + cprlat)
|
||||||
|
|
||||||
@@ -133,8 +133,9 @@ def surface_position_with_ref(msg, lat_ref, lon_ref):
|
|||||||
else:
|
else:
|
||||||
d_lon = 90.0
|
d_lon = 90.0
|
||||||
|
|
||||||
m = common.floor(lon_ref / d_lon) \
|
m = common.floor(lon_ref / d_lon) + common.floor(
|
||||||
+ common.floor(0.5 + ((lon_ref % d_lon) / d_lon) - cprlon)
|
0.5 + ((lon_ref % d_lon) / d_lon) - cprlon
|
||||||
|
)
|
||||||
|
|
||||||
lon = d_lon * (m + cprlon)
|
lon = d_lon * (m + cprlon)
|
||||||
|
|
||||||
@@ -184,11 +185,11 @@ def surface_velocity(msg, rtn_sources=False):
|
|||||||
movs = [2, 9, 13, 39, 94, 109, 124]
|
movs = [2, 9, 13, 39, 94, 109, 124]
|
||||||
kts = [0.125, 1, 2, 15, 70, 100, 175]
|
kts = [0.125, 1, 2, 15, 70, 100, 175]
|
||||||
i = next(m[0] for m in enumerate(movs) if m[1] > mov)
|
i = next(m[0] for m in enumerate(movs) if m[1] > mov)
|
||||||
step = (kts[i] - kts[i-1]) * 1.0 / (movs[i]-movs[i-1])
|
step = (kts[i] - kts[i - 1]) * 1.0 / (movs[i] - movs[i - 1])
|
||||||
spd = kts[i-1] + (mov-movs[i-1]) * step
|
spd = kts[i - 1] + (mov - movs[i - 1]) * step
|
||||||
spd = round(spd, 2)
|
spd = round(spd, 2)
|
||||||
|
|
||||||
if rtn_sources:
|
if rtn_sources:
|
||||||
return spd, trk, 0, 'GS', 'true_north', None
|
return spd, trk, 0, "GS", "true_north", None
|
||||||
else:
|
else:
|
||||||
return spd, trk, 0, 'GS'
|
return spd, trk, 0, "GS"
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
from __future__ import absolute_import, print_function, division
|
from __future__ import absolute_import, print_function, division
|
||||||
from pyModeS.decoder import common
|
from pyModeS.decoder import common
|
||||||
|
|
||||||
|
|
||||||
def category(msg):
|
def category(msg):
|
||||||
"""Aircraft category number
|
"""Aircraft category number
|
||||||
|
|
||||||
@@ -36,8 +37,8 @@ def category(msg):
|
|||||||
if common.typecode(msg) < 1 or common.typecode(msg) > 4:
|
if common.typecode(msg) < 1 or common.typecode(msg) > 4:
|
||||||
raise RuntimeError("%s: Not a identification message" % msg)
|
raise RuntimeError("%s: Not a identification message" % msg)
|
||||||
|
|
||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
mebin = msgbin[32:87]
|
mebin = msgbin[32:87]
|
||||||
return common.bin2int(mebin[5:8])
|
return common.bin2int(mebin[5:8])
|
||||||
|
|
||||||
|
|
||||||
@@ -54,11 +55,11 @@ def callsign(msg):
|
|||||||
if common.typecode(msg) < 1 or common.typecode(msg) > 4:
|
if common.typecode(msg) < 1 or common.typecode(msg) > 4:
|
||||||
raise RuntimeError("%s: Not a identification message" % msg)
|
raise RuntimeError("%s: Not a identification message" % msg)
|
||||||
|
|
||||||
chars = '#ABCDEFGHIJKLMNOPQRSTUVWXYZ#####_###############0123456789######'
|
chars = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ#####_###############0123456789######"
|
||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
csbin = msgbin[40:96]
|
csbin = msgbin[40:96]
|
||||||
|
|
||||||
cs = ''
|
cs = ""
|
||||||
cs += chars[common.bin2int(csbin[0:6])]
|
cs += chars[common.bin2int(csbin[0:6])]
|
||||||
cs += chars[common.bin2int(csbin[6:12])]
|
cs += chars[common.bin2int(csbin[6:12])]
|
||||||
cs += chars[common.bin2int(csbin[12:18])]
|
cs += chars[common.bin2int(csbin[12:18])]
|
||||||
@@ -70,5 +71,5 @@ def callsign(msg):
|
|||||||
|
|
||||||
# clean string, remove spaces and marks, if any.
|
# clean string, remove spaces and marks, if any.
|
||||||
# cs = cs.replace('_', '')
|
# cs = cs.replace('_', '')
|
||||||
cs = cs.replace('#', '')
|
cs = cs.replace("#", "")
|
||||||
return cs
|
return cs
|
||||||
|
|||||||
@@ -57,32 +57,32 @@ def airborne_velocity(msg, rtn_sources=False):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
if subtype in (1, 2):
|
if subtype in (1, 2):
|
||||||
v_ew_sign = -1 if mb[13]=='1' else 1
|
v_ew_sign = -1 if mb[13] == "1" else 1
|
||||||
v_ew = common.bin2int(mb[14:24]) - 1 # east-west velocity
|
v_ew = common.bin2int(mb[14:24]) - 1 # east-west velocity
|
||||||
if subtype == 2: # Supersonic
|
if subtype == 2: # Supersonic
|
||||||
v_ew *= 4
|
v_ew *= 4
|
||||||
|
|
||||||
v_ns_sign = -1 if mb[24]=='1' else 1
|
v_ns_sign = -1 if mb[24] == "1" else 1
|
||||||
v_ns = common.bin2int(mb[25:35]) - 1 # north-south velocity
|
v_ns = common.bin2int(mb[25:35]) - 1 # north-south velocity
|
||||||
if subtype == 2: # Supersonic
|
if subtype == 2: # Supersonic
|
||||||
v_ns *= 4
|
v_ns *= 4
|
||||||
|
|
||||||
v_we = v_ew_sign * v_ew
|
v_we = v_ew_sign * v_ew
|
||||||
v_sn = v_ns_sign * v_ns
|
v_sn = v_ns_sign * v_ns
|
||||||
|
|
||||||
spd = math.sqrt(v_sn*v_sn + v_we*v_we) # unit in kts
|
spd = math.sqrt(v_sn * v_sn + v_we * v_we) # unit in kts
|
||||||
spd = int(spd)
|
spd = int(spd)
|
||||||
|
|
||||||
trk = math.atan2(v_we, v_sn)
|
trk = math.atan2(v_we, v_sn)
|
||||||
trk = math.degrees(trk) # convert to degrees
|
trk = math.degrees(trk) # convert to degrees
|
||||||
trk = trk if trk >= 0 else trk + 360 # no negative val
|
trk = trk if trk >= 0 else trk + 360 # no negative val
|
||||||
|
|
||||||
tag = 'GS'
|
tag = "GS"
|
||||||
trk_or_hdg = round(trk, 2)
|
trk_or_hdg = round(trk, 2)
|
||||||
dir_type = 'true_north'
|
dir_type = "true_north"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if mb[13] == '0':
|
if mb[13] == "0":
|
||||||
hdg = None
|
hdg = None
|
||||||
else:
|
else:
|
||||||
hdg = common.bin2int(mb[14:24]) / 1024.0 * 360.0
|
hdg = common.bin2int(mb[14:24]) / 1024.0 * 360.0
|
||||||
@@ -91,27 +91,27 @@ def airborne_velocity(msg, rtn_sources=False):
|
|||||||
trk_or_hdg = hdg
|
trk_or_hdg = hdg
|
||||||
|
|
||||||
spd = common.bin2int(mb[25:35])
|
spd = common.bin2int(mb[25:35])
|
||||||
spd = None if spd==0 else spd-1
|
spd = None if spd == 0 else spd - 1
|
||||||
if subtype == 4: # Supersonic
|
if subtype == 4: # Supersonic
|
||||||
spd *= 4
|
spd *= 4
|
||||||
|
|
||||||
if mb[24]=='0':
|
if mb[24] == "0":
|
||||||
tag = 'IAS'
|
tag = "IAS"
|
||||||
else:
|
else:
|
||||||
tag = 'TAS'
|
tag = "TAS"
|
||||||
|
|
||||||
dir_type = 'mag_north'
|
|
||||||
|
|
||||||
vr_source = 'GNSS' if mb[35]=='0' else 'Baro'
|
dir_type = "mag_north"
|
||||||
vr_sign = -1 if mb[36]=='1' else 1
|
|
||||||
|
vr_source = "GNSS" if mb[35] == "0" else "Baro"
|
||||||
|
vr_sign = -1 if mb[36] == "1" else 1
|
||||||
vr = common.bin2int(mb[37:46])
|
vr = common.bin2int(mb[37:46])
|
||||||
rocd = None if vr==0 else int(vr_sign*(vr-1)*64)
|
rocd = None if vr == 0 else int(vr_sign * (vr - 1) * 64)
|
||||||
|
|
||||||
if rtn_sources:
|
if rtn_sources:
|
||||||
return spd, trk_or_hdg, rocd, tag, dir_type, vr_source
|
return spd, trk_or_hdg, rocd, tag, dir_type, vr_source
|
||||||
else:
|
else:
|
||||||
return spd, trk_or_hdg, rocd, tag
|
return spd, trk_or_hdg, rocd, tag
|
||||||
|
|
||||||
|
|
||||||
def altitude_diff(msg):
|
def altitude_diff(msg):
|
||||||
"""Decode the differece between GNSS and barometric altitude
|
"""Decode the differece between GNSS and barometric altitude
|
||||||
@@ -135,4 +135,4 @@ def altitude_diff(msg):
|
|||||||
if value == 0 or value == 127:
|
if value == 0 or value == 127:
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
return sign * (value - 1) * 25 # in ft.
|
return sign * (value - 1) * 25 # in ft.
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
from __future__ import absolute_import, print_function, division
|
from __future__ import absolute_import, print_function, division
|
||||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros
|
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros
|
||||||
|
|
||||||
|
|
||||||
def is10(msg):
|
def is10(msg):
|
||||||
"""Check if a message is likely to be BDS code 1,0
|
"""Check if a message is likely to be BDS code 1,0
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ def is10(msg):
|
|||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
# first 8 bits must be 0x10
|
# first 8 bits must be 0x10
|
||||||
if d[0:8] != '00010000':
|
if d[0:8] != "00010000":
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# bit 10 to 14 are reserved
|
# bit 10 to 14 are reserved
|
||||||
@@ -45,13 +46,14 @@ def is10(msg):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# overlay capabilty conflict
|
# overlay capabilty conflict
|
||||||
if d[14] == '1' and bin2int(d[16:23]) < 5:
|
if d[14] == "1" and bin2int(d[16:23]) < 5:
|
||||||
return False
|
return False
|
||||||
if d[14] == '0' and bin2int(d[16:23]) > 4:
|
if d[14] == "0" and bin2int(d[16:23]) > 4:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def ovc10(msg):
|
def ovc10(msg):
|
||||||
"""Return the overlay control capability
|
"""Return the overlay control capability
|
||||||
|
|
||||||
|
|||||||
@@ -50,11 +50,12 @@ def is17(msg):
|
|||||||
# return False
|
# return False
|
||||||
|
|
||||||
# at least you can respond who you are
|
# at least you can respond who you are
|
||||||
if 'BDS20' not in caps:
|
if "BDS20" not in caps:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def cap17(msg):
|
def cap17(msg):
|
||||||
"""Extract capacities from BDS 1,7 message
|
"""Extract capacities from BDS 1,7 message
|
||||||
|
|
||||||
@@ -64,12 +65,39 @@ def cap17(msg):
|
|||||||
Returns:
|
Returns:
|
||||||
list: list of suport BDS codes
|
list: list of suport BDS codes
|
||||||
"""
|
"""
|
||||||
allbds = ['05', '06', '07', '08', '09', '0A', '20', '21', '40', '41',
|
allbds = [
|
||||||
'42', '43', '44', '45', '48', '50', '51', '52', '53', '54',
|
"05",
|
||||||
'55', '56', '5F', '60', 'NA', 'NA', 'E1', 'E2']
|
"06",
|
||||||
|
"07",
|
||||||
|
"08",
|
||||||
|
"09",
|
||||||
|
"0A",
|
||||||
|
"20",
|
||||||
|
"21",
|
||||||
|
"40",
|
||||||
|
"41",
|
||||||
|
"42",
|
||||||
|
"43",
|
||||||
|
"44",
|
||||||
|
"45",
|
||||||
|
"48",
|
||||||
|
"50",
|
||||||
|
"51",
|
||||||
|
"52",
|
||||||
|
"53",
|
||||||
|
"54",
|
||||||
|
"55",
|
||||||
|
"56",
|
||||||
|
"5F",
|
||||||
|
"60",
|
||||||
|
"NA",
|
||||||
|
"NA",
|
||||||
|
"E1",
|
||||||
|
"E2",
|
||||||
|
]
|
||||||
|
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
idx = [i for i, v in enumerate(d[:28]) if v=='1']
|
idx = [i for i, v in enumerate(d[:28]) if v == "1"]
|
||||||
capacity = ['BDS'+allbds[i] for i in idx if allbds[i] is not 'NA']
|
capacity = ["BDS" + allbds[i] for i in idx if allbds[i] is not "NA"]
|
||||||
|
|
||||||
return capacity
|
return capacity
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
from __future__ import absolute_import, print_function, division
|
from __future__ import absolute_import, print_function, division
|
||||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros
|
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros
|
||||||
|
|
||||||
|
|
||||||
def is20(msg):
|
def is20(msg):
|
||||||
"""Check if a message is likely to be BDS code 2,0
|
"""Check if a message is likely to be BDS code 2,0
|
||||||
|
|
||||||
@@ -36,12 +37,12 @@ def is20(msg):
|
|||||||
|
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
if d[0:8] != '00100000':
|
if d[0:8] != "00100000":
|
||||||
return False
|
return False
|
||||||
|
|
||||||
cs = cs20(msg)
|
cs = cs20(msg)
|
||||||
|
|
||||||
if '#' in cs:
|
if "#" in cs:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@@ -56,11 +57,11 @@ def cs20(msg):
|
|||||||
Returns:
|
Returns:
|
||||||
string: callsign, max. 8 chars
|
string: callsign, max. 8 chars
|
||||||
"""
|
"""
|
||||||
chars = '#ABCDEFGHIJKLMNOPQRSTUVWXYZ#####_###############0123456789######'
|
chars = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ#####_###############0123456789######"
|
||||||
|
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
cs = ''
|
cs = ""
|
||||||
cs += chars[bin2int(d[8:14])]
|
cs += chars[bin2int(d[8:14])]
|
||||||
cs += chars[bin2int(d[14:20])]
|
cs += chars[bin2int(d[14:20])]
|
||||||
cs += chars[bin2int(d[20:26])]
|
cs += chars[bin2int(d[20:26])]
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
from __future__ import absolute_import, print_function, division
|
from __future__ import absolute_import, print_function, division
|
||||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros
|
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros
|
||||||
|
|
||||||
|
|
||||||
def is30(msg):
|
def is30(msg):
|
||||||
"""Check if a message is likely to be BDS code 2,0
|
"""Check if a message is likely to be BDS code 2,0
|
||||||
|
|
||||||
@@ -36,11 +37,11 @@ def is30(msg):
|
|||||||
|
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
if d[0:8] != '00110000':
|
if d[0:8] != "00110000":
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# threat type 3 not assigned
|
# threat type 3 not assigned
|
||||||
if d[28:30] == '11':
|
if d[28:30] == "11":
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# reserved for ACAS III, in far future
|
# reserved for ACAS III, in far future
|
||||||
|
|||||||
@@ -19,13 +19,7 @@
|
|||||||
# ------------------------------------------
|
# ------------------------------------------
|
||||||
|
|
||||||
from __future__ import absolute_import, print_function, division
|
from __future__ import absolute_import, print_function, division
|
||||||
from pyModeS.decoder.common import (
|
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros, wrongstatus
|
||||||
hex2bin,
|
|
||||||
bin2int,
|
|
||||||
data,
|
|
||||||
allzeros,
|
|
||||||
wrongstatus,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def is44(msg):
|
def is44(msg):
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ def turb45(msg):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
if d[0] == '0':
|
if d[0] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
turb = bin2int(d[1:3])
|
turb = bin2int(d[1:3])
|
||||||
@@ -105,7 +105,7 @@ def ws45(msg):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
if d[3] == '0':
|
if d[3] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
ws = bin2int(d[4:6])
|
ws = bin2int(d[4:6])
|
||||||
@@ -123,7 +123,7 @@ def mb45(msg):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
if d[6] == '0':
|
if d[6] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
mb = bin2int(d[7:9])
|
mb = bin2int(d[7:9])
|
||||||
@@ -141,7 +141,7 @@ def ic45(msg):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
if d[9] == '0':
|
if d[9] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
ic = bin2int(d[10:12])
|
ic = bin2int(d[10:12])
|
||||||
@@ -159,7 +159,7 @@ def wv45(msg):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
if d[12] == '0':
|
if d[12] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
ws = bin2int(d[13:15])
|
ws = bin2int(d[13:15])
|
||||||
@@ -184,7 +184,7 @@ def temp45(msg):
|
|||||||
if sign:
|
if sign:
|
||||||
value = value - 512
|
value = value - 512
|
||||||
|
|
||||||
temp = value * 0.25 # celsius
|
temp = value * 0.25 # celsius
|
||||||
temp = round(temp, 1)
|
temp = round(temp, 1)
|
||||||
|
|
||||||
return temp
|
return temp
|
||||||
@@ -201,9 +201,9 @@ def p45(msg):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
if d[26] == '0':
|
if d[26] == "0":
|
||||||
return None
|
return None
|
||||||
p = bin2int(d[27:38]) # hPa
|
p = bin2int(d[27:38]) # hPa
|
||||||
return p
|
return p
|
||||||
|
|
||||||
|
|
||||||
@@ -218,7 +218,7 @@ def rh45(msg):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
if d[38] == '0':
|
if d[38] == "0":
|
||||||
return None
|
return None
|
||||||
rh = bin2int(d[39:51]) * 16
|
rh = bin2int(d[39:51]) * 16
|
||||||
return rh
|
return rh
|
||||||
|
|||||||
@@ -85,16 +85,16 @@ def roll50(msg):
|
|||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
if d[0] == '0':
|
if d[0] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
sign = int(d[1]) # 1 -> left wing down
|
sign = int(d[1]) # 1 -> left wing down
|
||||||
value = bin2int(d[2:11])
|
value = bin2int(d[2:11])
|
||||||
|
|
||||||
if sign:
|
if sign:
|
||||||
value = value - 512
|
value = value - 512
|
||||||
|
|
||||||
angle = value * 45.0 / 256.0 # degree
|
angle = value * 45.0 / 256.0 # degree
|
||||||
return round(angle, 1)
|
return round(angle, 1)
|
||||||
|
|
||||||
|
|
||||||
@@ -109,10 +109,10 @@ def trk50(msg):
|
|||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
if d[11] == '0':
|
if d[11] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
sign = int(d[12]) # 1 -> west
|
sign = int(d[12]) # 1 -> west
|
||||||
value = bin2int(d[13:23])
|
value = bin2int(d[13:23])
|
||||||
|
|
||||||
if sign:
|
if sign:
|
||||||
@@ -138,10 +138,10 @@ def gs50(msg):
|
|||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
if d[23] == '0':
|
if d[23] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
spd = bin2int(d[24:34]) * 2 # kts
|
spd = bin2int(d[24:34]) * 2 # kts
|
||||||
return spd
|
return spd
|
||||||
|
|
||||||
|
|
||||||
@@ -156,18 +156,18 @@ def rtrk50(msg):
|
|||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
if d[34] == '0':
|
if d[34] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if d[36:45] == "111111111":
|
if d[36:45] == "111111111":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
sign = int(d[35]) # 1 -> negative value, two's complement
|
sign = int(d[35]) # 1 -> negative value, two's complement
|
||||||
value = bin2int(d[36:45])
|
value = bin2int(d[36:45])
|
||||||
if sign:
|
if sign:
|
||||||
value = value - 512
|
value = value - 512
|
||||||
|
|
||||||
angle = value * 8.0 / 256.0 # degree / sec
|
angle = value * 8.0 / 256.0 # degree / sec
|
||||||
return round(angle, 3)
|
return round(angle, 3)
|
||||||
|
|
||||||
|
|
||||||
@@ -182,8 +182,8 @@ def tas50(msg):
|
|||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
if d[45] == '0':
|
if d[45] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
tas = bin2int(d[46:56]) * 2 # kts
|
tas = bin2int(d[46:56]) * 2 # kts
|
||||||
return tas
|
return tas
|
||||||
|
|||||||
@@ -85,16 +85,16 @@ def hdg53(msg):
|
|||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
if d[0] == '0':
|
if d[0] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
sign = int(d[1]) # 1 -> west
|
sign = int(d[1]) # 1 -> west
|
||||||
value = bin2int(d[2:12])
|
value = bin2int(d[2:12])
|
||||||
|
|
||||||
if sign:
|
if sign:
|
||||||
value = value - 1024
|
value = value - 1024
|
||||||
|
|
||||||
hdg = value * 90.0 / 512.0 # degree
|
hdg = value * 90.0 / 512.0 # degree
|
||||||
|
|
||||||
# convert from [-180, 180] to [0, 360]
|
# convert from [-180, 180] to [0, 360]
|
||||||
if hdg < 0:
|
if hdg < 0:
|
||||||
@@ -114,10 +114,10 @@ def ias53(msg):
|
|||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
if d[12] == '0':
|
if d[12] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
ias = bin2int(d[13:23]) # knots
|
ias = bin2int(d[13:23]) # knots
|
||||||
return ias
|
return ias
|
||||||
|
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ def mach53(msg):
|
|||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
if d[23] == '0':
|
if d[23] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
mach = bin2int(d[24:33]) * 0.008
|
mach = bin2int(d[24:33]) * 0.008
|
||||||
@@ -150,12 +150,13 @@ def tas53(msg):
|
|||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
if d[33] == '0':
|
if d[33] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
tas = bin2int(d[34:46]) * 0.5 # kts
|
tas = bin2int(d[34:46]) * 0.5 # kts
|
||||||
return round(tas, 1)
|
return round(tas, 1)
|
||||||
|
|
||||||
|
|
||||||
def vr53(msg):
|
def vr53(msg):
|
||||||
"""Vertical rate
|
"""Vertical rate
|
||||||
|
|
||||||
@@ -167,16 +168,16 @@ def vr53(msg):
|
|||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
if d[46] == '0':
|
if d[46] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
sign = int(d[47]) # 1 -> negative value, two's complement
|
sign = int(d[47]) # 1 -> negative value, two's complement
|
||||||
value = bin2int(d[48:56])
|
value = bin2int(d[48:56])
|
||||||
|
|
||||||
if value == 0 or value == 255: # all zeros or all ones
|
if value == 0 or value == 255: # all zeros or all ones
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
value = value - 256 if sign else value
|
value = value - 256 if sign else value
|
||||||
roc = value * 64 # feet/min
|
roc = value * 64 # feet/min
|
||||||
|
|
||||||
return roc
|
return roc
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
from __future__ import absolute_import, print_function, division
|
from __future__ import absolute_import, print_function, division
|
||||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros, wrongstatus
|
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros, wrongstatus
|
||||||
|
|
||||||
|
|
||||||
def is60(msg):
|
def is60(msg):
|
||||||
"""Check if a message is likely to be BDS code 6,0
|
"""Check if a message is likely to be BDS code 6,0
|
||||||
|
|
||||||
@@ -83,10 +84,10 @@ def hdg60(msg):
|
|||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
if d[0] == '0':
|
if d[0] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
sign = int(d[1]) # 1 -> west
|
sign = int(d[1]) # 1 -> west
|
||||||
value = bin2int(d[2:12])
|
value = bin2int(d[2:12])
|
||||||
|
|
||||||
if sign:
|
if sign:
|
||||||
@@ -112,10 +113,10 @@ def ias60(msg):
|
|||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
if d[12] == '0':
|
if d[12] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
ias = bin2int(d[13:23]) # kts
|
ias = bin2int(d[13:23]) # kts
|
||||||
return ias
|
return ias
|
||||||
|
|
||||||
|
|
||||||
@@ -130,7 +131,7 @@ def mach60(msg):
|
|||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
if d[23] == '0':
|
if d[23] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
mach = bin2int(d[24:34]) * 2.048 / 512.0
|
mach = bin2int(d[24:34]) * 2.048 / 512.0
|
||||||
@@ -148,10 +149,10 @@ def vr60baro(msg):
|
|||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
if d[34] == '0':
|
if d[34] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
sign = int(d[35]) # 1 -> negative value, two's complement
|
sign = int(d[35]) # 1 -> negative value, two's complement
|
||||||
value = bin2int(d[36:45])
|
value = bin2int(d[36:45])
|
||||||
|
|
||||||
if value == 0 or value == 511: # all zeros or all ones
|
if value == 0 or value == 511: # all zeros or all ones
|
||||||
@@ -159,7 +160,7 @@ def vr60baro(msg):
|
|||||||
|
|
||||||
value = value - 512 if sign else value
|
value = value - 512 if sign else value
|
||||||
|
|
||||||
roc = value * 32 # feet/min
|
roc = value * 32 # feet/min
|
||||||
return roc
|
return roc
|
||||||
|
|
||||||
|
|
||||||
@@ -174,10 +175,10 @@ def vr60ins(msg):
|
|||||||
"""
|
"""
|
||||||
d = hex2bin(data(msg))
|
d = hex2bin(data(msg))
|
||||||
|
|
||||||
if d[45] == '0':
|
if d[45] == "0":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
sign = int(d[46]) # 1 -> negative value, two's complement
|
sign = int(d[46]) # 1 -> negative value, two's complement
|
||||||
value = bin2int(d[47:56])
|
value = bin2int(d[47:56])
|
||||||
|
|
||||||
if value == 0 or value == 511: # all zeros or all ones
|
if value == 0 or value == 511: # all zeros or all ones
|
||||||
@@ -185,5 +186,5 @@ def vr60ins(msg):
|
|||||||
|
|
||||||
value = value - 512 if sign else value
|
value = value - 512 if sign else value
|
||||||
|
|
||||||
roc = value * 32 # feet/min
|
roc = value * 32 # feet/min
|
||||||
return roc
|
return roc
|
||||||
|
|||||||
@@ -61,12 +61,7 @@ def crc(msg, encode=False):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
# the CRC generator
|
# the CRC generator
|
||||||
G = [
|
G = [int("11111111", 2), int("11111010", 2), int("00000100", 2), int("10000000", 2)]
|
||||||
int("11111111", 2),
|
|
||||||
int("11111010", 2),
|
|
||||||
int("00000100", 2),
|
|
||||||
int("10000000", 2),
|
|
||||||
]
|
|
||||||
|
|
||||||
if encode:
|
if encode:
|
||||||
msg = msg[:-6] + "000000"
|
msg = msg[:-6] + "000000"
|
||||||
@@ -101,33 +96,7 @@ def crc_legacy(msg, encode=False):
|
|||||||
"""Mode-S Cyclic Redundancy Check. (Legacy code, 2x slow)."""
|
"""Mode-S Cyclic Redundancy Check. (Legacy code, 2x slow)."""
|
||||||
# the polynominal generattor code for CRC [1111111111111010000001001]
|
# the polynominal generattor code for CRC [1111111111111010000001001]
|
||||||
generator = np.array(
|
generator = np.array(
|
||||||
[
|
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1]
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
ng = len(generator)
|
ng = len(generator)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
import pyModeS as pms
|
||||||
+10
-3
@@ -17,13 +17,20 @@ from pyModeS.decoder.bds.bds50 import *
|
|||||||
from pyModeS.decoder.bds.bds60 import *
|
from pyModeS.decoder.bds.bds60 import *
|
||||||
from pyModeS.decoder.bds import infer
|
from pyModeS.decoder.bds import infer
|
||||||
|
|
||||||
warnings.simplefilter('once', DeprecationWarning)
|
warnings.simplefilter("once", DeprecationWarning)
|
||||||
warnings.warn("pms.ehs module is deprecated. Please use pms.commb instead.", DeprecationWarning)
|
warnings.warn(
|
||||||
|
"pms.ehs module is deprecated. Please use pms.commb instead.", DeprecationWarning
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def BDS(msg):
|
def BDS(msg):
|
||||||
warnings.warn("pms.ehs.BDS() is deprecated, use pms.bds.infer() instead.", DeprecationWarning)
|
warnings.warn(
|
||||||
|
"pms.ehs.BDS() is deprecated, use pms.bds.infer() instead.", DeprecationWarning
|
||||||
|
)
|
||||||
return infer(msg)
|
return infer(msg)
|
||||||
|
|
||||||
|
|
||||||
def icao(msg):
|
def icao(msg):
|
||||||
from pyModeS.decoder.common import icao
|
from pyModeS.decoder.common import icao
|
||||||
|
|
||||||
return icao(msg)
|
return icao(msg)
|
||||||
|
|||||||
@@ -18,5 +18,8 @@ from pyModeS.decoder.bds.bds20 import *
|
|||||||
from pyModeS.decoder.bds.bds30 import *
|
from pyModeS.decoder.bds.bds30 import *
|
||||||
|
|
||||||
import warnings
|
import warnings
|
||||||
warnings.simplefilter('once', DeprecationWarning)
|
|
||||||
warnings.warn("pms.els module is deprecated. Please use pms.commb instead.", DeprecationWarning)
|
warnings.simplefilter("once", DeprecationWarning)
|
||||||
|
warnings.warn(
|
||||||
|
"pms.els module is deprecated. Please use pms.commb instead.", DeprecationWarning
|
||||||
|
)
|
||||||
|
|||||||
+112
-85
@@ -6,120 +6,147 @@ See source code at: https://github.com/junzis/pyModeS/blob/master/pyModeS/decode
|
|||||||
NA = None
|
NA = None
|
||||||
|
|
||||||
TC_NUCp_lookup = {
|
TC_NUCp_lookup = {
|
||||||
0:0, 5:9, 6:8, 7:7, 8:6,
|
0: 0,
|
||||||
9:9, 10:8, 11:7, 12:6, 13:5, 14:4, 15:3, 16:2, 17:1, 18:0,
|
5: 9,
|
||||||
20:9, 21:8, 22:0
|
6: 8,
|
||||||
|
7: 7,
|
||||||
|
8: 6,
|
||||||
|
9: 9,
|
||||||
|
10: 8,
|
||||||
|
11: 7,
|
||||||
|
12: 6,
|
||||||
|
13: 5,
|
||||||
|
14: 4,
|
||||||
|
15: 3,
|
||||||
|
16: 2,
|
||||||
|
17: 1,
|
||||||
|
18: 0,
|
||||||
|
20: 9,
|
||||||
|
21: 8,
|
||||||
|
22: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
TC_NICv1_lookup = {
|
TC_NICv1_lookup = {
|
||||||
5:11, 6:10, 7:9, 8:0,
|
5: 11,
|
||||||
9:11, 10:10, 11:{1:9, 0:8}, 12:7, 13:6, 14:5, 15:4, 16:{1:3, 0:2}, 17:1, 18:0,
|
6: 10,
|
||||||
20:11, 21:10, 22:0
|
7: 9,
|
||||||
|
8: 0,
|
||||||
|
9: 11,
|
||||||
|
10: 10,
|
||||||
|
11: {1: 9, 0: 8},
|
||||||
|
12: 7,
|
||||||
|
13: 6,
|
||||||
|
14: 5,
|
||||||
|
15: 4,
|
||||||
|
16: {1: 3, 0: 2},
|
||||||
|
17: 1,
|
||||||
|
18: 0,
|
||||||
|
20: 11,
|
||||||
|
21: 10,
|
||||||
|
22: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
TC_NICv2_lookup = {
|
TC_NICv2_lookup = {
|
||||||
5:11, 6:10, 7:{2:9, 0:8}, 8:{3:7, 2:6, 1:6, 0:0},
|
5: 11,
|
||||||
9:11, 10:10, 11:{3:9, 0:8}, 12:7, 13:6, 14:5, 15:4, 16:{3:3, 0:2}, 17:1, 18:0,
|
6: 10,
|
||||||
20:11, 21:10, 22:0
|
7: {2: 9, 0: 8},
|
||||||
|
8: {3: 7, 2: 6, 1: 6, 0: 0},
|
||||||
|
9: 11,
|
||||||
|
10: 10,
|
||||||
|
11: {3: 9, 0: 8},
|
||||||
|
12: 7,
|
||||||
|
13: 6,
|
||||||
|
14: 5,
|
||||||
|
15: 4,
|
||||||
|
16: {3: 3, 0: 2},
|
||||||
|
17: 1,
|
||||||
|
18: 0,
|
||||||
|
20: 11,
|
||||||
|
21: 10,
|
||||||
|
22: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NUCp = {
|
NUCp = {
|
||||||
9: {'HPL':7.5, 'RCu':3, 'RCv':4},
|
9: {"HPL": 7.5, "RCu": 3, "RCv": 4},
|
||||||
8: {'HPL':25, 'RCu':10, 'RCv':15},
|
8: {"HPL": 25, "RCu": 10, "RCv": 15},
|
||||||
7: {'HPL':185, 'RCu':93, 'RCv':NA},
|
7: {"HPL": 185, "RCu": 93, "RCv": NA},
|
||||||
6: {'HPL':370, 'RCu':185, 'RCv':NA},
|
6: {"HPL": 370, "RCu": 185, "RCv": NA},
|
||||||
5: {'HPL':926, 'RCu':463, 'RCv':NA},
|
5: {"HPL": 926, "RCu": 463, "RCv": NA},
|
||||||
4: {'HPL':1852, 'RCu':926, 'RCv':NA},
|
4: {"HPL": 1852, "RCu": 926, "RCv": NA},
|
||||||
3: {'HPL':3704, 'RCu':1852, 'RCv':NA},
|
3: {"HPL": 3704, "RCu": 1852, "RCv": NA},
|
||||||
2: {'HPL':18520, 'RCu':9260, 'RCv':NA},
|
2: {"HPL": 18520, "RCu": 9260, "RCv": NA},
|
||||||
1: {'HPL':37040, 'RCu':18520, 'RCv':NA},
|
1: {"HPL": 37040, "RCu": 18520, "RCv": NA},
|
||||||
0: {'HPL':NA, 'RCu':NA, 'RCv':NA},
|
0: {"HPL": NA, "RCu": NA, "RCv": NA},
|
||||||
}
|
}
|
||||||
|
|
||||||
NUCv = {
|
NUCv = {
|
||||||
0: {'HVE':NA, 'VVE':NA},
|
0: {"HVE": NA, "VVE": NA},
|
||||||
1: {'HVE':10, 'VVE':15.2},
|
1: {"HVE": 10, "VVE": 15.2},
|
||||||
2: {'HVE':3, 'VVE':4.5},
|
2: {"HVE": 3, "VVE": 4.5},
|
||||||
3: {'HVE':1, 'VVE':1.5},
|
3: {"HVE": 1, "VVE": 1.5},
|
||||||
4: {'HVE':0.3, 'VVE':0.46},
|
4: {"HVE": 0.3, "VVE": 0.46},
|
||||||
}
|
}
|
||||||
|
|
||||||
NACp = {
|
NACp = {
|
||||||
11: {'EPU': 3, 'VEPU': 4},
|
11: {"EPU": 3, "VEPU": 4},
|
||||||
10: {'EPU': 10, 'VEPU': 15},
|
10: {"EPU": 10, "VEPU": 15},
|
||||||
9: {'EPU': 30, 'VEPU': 45},
|
9: {"EPU": 30, "VEPU": 45},
|
||||||
8: {'EPU': 93, 'VEPU': NA},
|
8: {"EPU": 93, "VEPU": NA},
|
||||||
7: {'EPU': 185, 'VEPU': NA},
|
7: {"EPU": 185, "VEPU": NA},
|
||||||
6: {'EPU': 556, 'VEPU': NA},
|
6: {"EPU": 556, "VEPU": NA},
|
||||||
5: {'EPU': 926, 'VEPU': NA},
|
5: {"EPU": 926, "VEPU": NA},
|
||||||
4: {'EPU': 1852, 'VEPU': NA},
|
4: {"EPU": 1852, "VEPU": NA},
|
||||||
3: {'EPU': 3704, 'VEPU': NA},
|
3: {"EPU": 3704, "VEPU": NA},
|
||||||
2: {'EPU': 7408, 'VEPU': NA},
|
2: {"EPU": 7408, "VEPU": NA},
|
||||||
1: {'EPU': 18520, 'VEPU': NA},
|
1: {"EPU": 18520, "VEPU": NA},
|
||||||
0: {'EPU': NA, 'VEPU': NA},
|
0: {"EPU": NA, "VEPU": NA},
|
||||||
}
|
}
|
||||||
|
|
||||||
NACv = {
|
NACv = {
|
||||||
0: {'HFOMr':NA, 'VFOMr':NA},
|
0: {"HFOMr": NA, "VFOMr": NA},
|
||||||
1: {'HFOMr':10, 'VFOMr':15.2},
|
1: {"HFOMr": 10, "VFOMr": 15.2},
|
||||||
2: {'HFOMr':3, 'VFOMr':4.5},
|
2: {"HFOMr": 3, "VFOMr": 4.5},
|
||||||
3: {'HFOMr':1, 'VFOMr':1.5},
|
3: {"HFOMr": 1, "VFOMr": 1.5},
|
||||||
4: {'HFOMr':0.3, 'VFOMr':0.46},
|
4: {"HFOMr": 0.3, "VFOMr": 0.46},
|
||||||
}
|
}
|
||||||
|
|
||||||
SIL = {
|
SIL = {
|
||||||
3: {'PE_RCu': 1e-7, 'PE_VPL': 2e-7},
|
3: {"PE_RCu": 1e-7, "PE_VPL": 2e-7},
|
||||||
2: {'PE_RCu': 1e-5, 'PE_VPL': 1e-5},
|
2: {"PE_RCu": 1e-5, "PE_VPL": 1e-5},
|
||||||
1: {'PE_RCu': 1e-3, 'PE_VPL': 1e-3},
|
1: {"PE_RCu": 1e-3, "PE_VPL": 1e-3},
|
||||||
0: {'PE_RCu': NA, 'PE_VPL': NA},
|
0: {"PE_RCu": NA, "PE_VPL": NA},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NICv1 = {
|
NICv1 = {
|
||||||
# NIC is used as the index at second Level
|
# NIC is used as the index at second Level
|
||||||
|
11: {0: {"Rc": 7.5, "VPL": 11}},
|
||||||
11: {0: {'Rc': 7.5, 'VPL': 11}},
|
10: {0: {"Rc": 25, "VPL": 37.5}},
|
||||||
10: {0: {'Rc': 25, 'VPL': 37.5}},
|
9: {1: {"Rc": 75, "VPL": 112}},
|
||||||
9: {1: {'Rc': 75, 'VPL': 112}},
|
8: {0: {"Rc": 185, "VPL": NA}},
|
||||||
8: {0: {'Rc': 185, 'VPL': NA}},
|
7: {0: {"Rc": 370, "VPL": NA}},
|
||||||
7: {0: {'Rc': 370, 'VPL': NA}},
|
6: {0: {"Rc": 926, "VPL": NA}, 1: {"Rc": 1111, "VPL": NA}},
|
||||||
6: {
|
5: {0: {"Rc": 1852, "VPL": NA}},
|
||||||
0: {'Rc': 926, 'VPL': NA},
|
4: {0: {"Rc": 3702, "VPL": NA}},
|
||||||
1: {'Rc': 1111, 'VPL': NA},
|
3: {1: {"Rc": 7408, "VPL": NA}},
|
||||||
},
|
2: {0: {"Rc": 14008, "VPL": NA}},
|
||||||
5: {0: {'Rc': 1852, 'VPL': NA}},
|
1: {0: {"Rc": 37000, "VPL": NA}},
|
||||||
4: {0: {'Rc': 3702, 'VPL': NA}},
|
0: {0: {"Rc": NA, "VPL": NA}},
|
||||||
3: {1: {'Rc': 7408, 'VPL': NA}},
|
|
||||||
2: {0: {'Rc': 14008, 'VPL': NA}},
|
|
||||||
1: {0: {'Rc': 37000, 'VPL': NA}},
|
|
||||||
0: {0: {'Rc': NA, 'VPL': NA}},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NICv2 = {
|
NICv2 = {
|
||||||
# Decimal value of [NICa NICb/NICc] is used as the index at second Level
|
# Decimal value of [NICa NICb/NICc] is used as the index at second Level
|
||||||
|
11: {0: {"Rc": 7.5}},
|
||||||
11: {0: {'Rc': 7.5}},
|
10: {0: {"Rc": 25}},
|
||||||
10: {0: {'Rc': 25}},
|
9: {2: {"Rc": 75}, 3: {"Rc": 75}},
|
||||||
9: {
|
8: {0: {"Rc": 185}},
|
||||||
2: {'Rc': 75},
|
7: {0: {"Rc": 370}, 3: {"Rc": 370}},
|
||||||
3: {'Rc': 75},
|
6: {0: {"Rc": 926}, 1: {"Rc": 556}, 2: {"Rc": 556}, 3: {"Rc": 1111}},
|
||||||
},
|
5: {0: {"Rc": 1852}},
|
||||||
8: {0: {'Rc': 185}},
|
4: {0: {"Rc": 3702}},
|
||||||
7: {
|
3: {3: {"Rc": 7408}},
|
||||||
0: {'Rc': 370},
|
2: {0: {"Rc": 14008}},
|
||||||
3: {'Rc': 370},
|
1: {0: {"Rc": 37000}},
|
||||||
},
|
0: {0: {"Rc": NA}},
|
||||||
6: {
|
|
||||||
0: {'Rc': 926},
|
|
||||||
1: {'Rc': 556},
|
|
||||||
2: {'Rc': 556},
|
|
||||||
3: {'Rc': 1111},
|
|
||||||
},
|
|
||||||
5: {0: {'Rc': 1852}},
|
|
||||||
4: {0: {'Rc': 3702}},
|
|
||||||
3: {3: {'Rc': 7408}},
|
|
||||||
2: {0: {'Rc': 14008}},
|
|
||||||
1: {0: {'Rc': 37000}},
|
|
||||||
0: {0: {'Rc': NA}},
|
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-34
@@ -30,31 +30,31 @@ Speed conversion at altitude H[m] in ISA
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
"""Aero and geo Constants """
|
"""Aero and geo Constants """
|
||||||
kts = 0.514444 # knot -> m/s
|
kts = 0.514444 # knot -> m/s
|
||||||
ft = 0.3048 # ft -> m
|
ft = 0.3048 # ft -> m
|
||||||
fpm = 0.00508 # ft/min -> m/s
|
fpm = 0.00508 # ft/min -> m/s
|
||||||
inch = 0.0254 # inch -> m
|
inch = 0.0254 # inch -> m
|
||||||
sqft = 0.09290304 # 1 square foot
|
sqft = 0.09290304 # 1 square foot
|
||||||
nm = 1852. # nautical mile -> m
|
nm = 1852.0 # nautical mile -> m
|
||||||
lbs = 0.453592 # pound -> kg
|
lbs = 0.453592 # pound -> kg
|
||||||
g0 = 9.80665 # m/s2, Sea level gravity constant
|
g0 = 9.80665 # m/s2, Sea level gravity constant
|
||||||
R = 287.05287 # m2/(s2 x K), gas constant, sea level ISA
|
R = 287.05287 # m2/(s2 x K), gas constant, sea level ISA
|
||||||
p0 = 101325. # Pa, air pressure, sea level ISA
|
p0 = 101325.0 # Pa, air pressure, sea level ISA
|
||||||
rho0 = 1.225 # kg/m3, air density, sea level ISA
|
rho0 = 1.225 # kg/m3, air density, sea level ISA
|
||||||
T0 = 288.15 # K, temperature, sea level ISA
|
T0 = 288.15 # K, temperature, sea level ISA
|
||||||
gamma = 1.40 # cp/cv for air
|
gamma = 1.40 # cp/cv for air
|
||||||
gamma1 = 0.2 # (gamma-1)/2 for air
|
gamma1 = 0.2 # (gamma-1)/2 for air
|
||||||
gamma2 = 3.5 # gamma/(gamma-1) for air
|
gamma2 = 3.5 # gamma/(gamma-1) for air
|
||||||
beta = -0.0065 # [K/m] ISA temp gradient below tropopause
|
beta = -0.0065 # [K/m] ISA temp gradient below tropopause
|
||||||
r_earth = 6371000. # m, average earth radius
|
r_earth = 6371000.0 # m, average earth radius
|
||||||
a0 = 340.293988 # m/s, sea level speed of sound ISA, sqrt(gamma*R*T0)
|
a0 = 340.293988 # m/s, sea level speed of sound ISA, sqrt(gamma*R*T0)
|
||||||
|
|
||||||
|
|
||||||
def atmos(H):
|
def atmos(H):
|
||||||
# H in metres
|
# H in metres
|
||||||
T = np.maximum(288.15 - 0.0065 * H, 216.65)
|
T = np.maximum(288.15 - 0.0065 * H, 216.65)
|
||||||
rhotrop = 1.225 * (T / 288.15)**4.256848030018761
|
rhotrop = 1.225 * (T / 288.15) ** 4.256848030018761
|
||||||
dhstrat = np.maximum(0., H - 11000.0)
|
dhstrat = np.maximum(0.0, H - 11000.0)
|
||||||
rho = rhotrop * np.exp(-dhstrat / 6341.552161)
|
rho = rhotrop * np.exp(-dhstrat / 6341.552161)
|
||||||
p = rho * R * T
|
p = rho * R * T
|
||||||
return p, rho, T
|
return p, rho, T
|
||||||
@@ -101,11 +101,13 @@ def distance(lat1, lon1, lat2, lon2, H=0):
|
|||||||
theta1 = np.radians(lon1)
|
theta1 = np.radians(lon1)
|
||||||
theta2 = np.radians(lon2)
|
theta2 = np.radians(lon2)
|
||||||
|
|
||||||
cos = np.sin(phi1) * np.sin(phi2) * np.cos(theta1 - theta2) + np.cos(phi1) * np.cos(phi2)
|
cos = np.sin(phi1) * np.sin(phi2) * np.cos(theta1 - theta2) + np.cos(phi1) * np.cos(
|
||||||
cos = np.where(cos>1, 1, cos)
|
phi2
|
||||||
|
)
|
||||||
|
cos = np.where(cos > 1, 1, cos)
|
||||||
|
|
||||||
arc = np.arccos(cos)
|
arc = np.arccos(cos)
|
||||||
dist = arc * (r_earth + H) # meters, radius of earth
|
dist = arc * (r_earth + H) # meters, radius of earth
|
||||||
return dist
|
return dist
|
||||||
|
|
||||||
|
|
||||||
@@ -114,9 +116,8 @@ def bearing(lat1, lon1, lat2, lon2):
|
|||||||
lon1 = np.radians(lon1)
|
lon1 = np.radians(lon1)
|
||||||
lat2 = np.radians(lat2)
|
lat2 = np.radians(lat2)
|
||||||
lon2 = np.radians(lon2)
|
lon2 = np.radians(lon2)
|
||||||
x = np.sin(lon2-lon1) * np.cos(lat2)
|
x = np.sin(lon2 - lon1) * np.cos(lat2)
|
||||||
y = np.cos(lat1) * np.sin(lat2) \
|
y = np.cos(lat1) * np.sin(lat2) - np.sin(lat1) * np.cos(lat2) * np.cos(lon2 - lon1)
|
||||||
- np.sin(lat1) * np.cos(lat2) * np.cos(lon2-lon1)
|
|
||||||
initial_bearing = np.arctan2(x, y)
|
initial_bearing = np.arctan2(x, y)
|
||||||
initial_bearing = np.degrees(initial_bearing)
|
initial_bearing = np.degrees(initial_bearing)
|
||||||
bearing = (initial_bearing + 360) % 360
|
bearing = (initial_bearing + 360) % 360
|
||||||
@@ -129,44 +130,44 @@ def bearing(lat1, lon1, lat2, lon2):
|
|||||||
def tas2mach(Vtas, H):
|
def tas2mach(Vtas, H):
|
||||||
"""True Airspeed to Mach number"""
|
"""True Airspeed to Mach number"""
|
||||||
a = vsound(H)
|
a = vsound(H)
|
||||||
Mach = Vtas/a
|
Mach = Vtas / a
|
||||||
return Mach
|
return Mach
|
||||||
|
|
||||||
|
|
||||||
def mach2tas(Mach, H):
|
def mach2tas(Mach, H):
|
||||||
"""Mach number to True Airspeed"""
|
"""Mach number to True Airspeed"""
|
||||||
a = vsound(H)
|
a = vsound(H)
|
||||||
Vtas = Mach*a
|
Vtas = Mach * a
|
||||||
return Vtas
|
return Vtas
|
||||||
|
|
||||||
|
|
||||||
def eas2tas(Veas, H):
|
def eas2tas(Veas, H):
|
||||||
"""Equivalent Airspeed to True Airspeed"""
|
"""Equivalent Airspeed to True Airspeed"""
|
||||||
rho = density(H)
|
rho = density(H)
|
||||||
Vtas = Veas * np.sqrt(rho0/rho)
|
Vtas = Veas * np.sqrt(rho0 / rho)
|
||||||
return Vtas
|
return Vtas
|
||||||
|
|
||||||
|
|
||||||
def tas2eas(Vtas, H):
|
def tas2eas(Vtas, H):
|
||||||
"""True Airspeed to Equivalent Airspeed"""
|
"""True Airspeed to Equivalent Airspeed"""
|
||||||
rho = density(H)
|
rho = density(H)
|
||||||
Veas = Vtas * np.sqrt(rho/rho0)
|
Veas = Vtas * np.sqrt(rho / rho0)
|
||||||
return Veas
|
return Veas
|
||||||
|
|
||||||
|
|
||||||
def cas2tas(Vcas, H):
|
def cas2tas(Vcas, H):
|
||||||
"""Calibrated Airspeed to True Airspeed"""
|
"""Calibrated Airspeed to True Airspeed"""
|
||||||
p, rho, T = atmos(H)
|
p, rho, T = atmos(H)
|
||||||
qdyn = p0*((1.+rho0*Vcas*Vcas/(7.*p0))**3.5-1.)
|
qdyn = p0 * ((1.0 + rho0 * Vcas * Vcas / (7.0 * p0)) ** 3.5 - 1.0)
|
||||||
Vtas = np.sqrt(7.*p/rho*((1.+qdyn/p)**(2./7.)-1.))
|
Vtas = np.sqrt(7.0 * p / rho * ((1.0 + qdyn / p) ** (2.0 / 7.0) - 1.0))
|
||||||
return Vtas
|
return Vtas
|
||||||
|
|
||||||
|
|
||||||
def tas2cas(Vtas, H):
|
def tas2cas(Vtas, H):
|
||||||
"""True Airspeed to Calibrated Airspeed"""
|
"""True Airspeed to Calibrated Airspeed"""
|
||||||
p, rho, T = atmos(H)
|
p, rho, T = atmos(H)
|
||||||
qdyn = p*((1.+rho*Vtas*Vtas/(7.*p))**3.5-1.)
|
qdyn = p * ((1.0 + rho * Vtas * Vtas / (7.0 * p)) ** 3.5 - 1.0)
|
||||||
Vcas = np.sqrt(7.*p0/rho0*((qdyn/p0+1.)**(2./7.)-1.))
|
Vcas = np.sqrt(7.0 * p0 / rho0 * ((qdyn / p0 + 1.0) ** (2.0 / 7.0) - 1.0))
|
||||||
return Vcas
|
return Vcas
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -59,9 +59,7 @@ class TcpClient(object):
|
|||||||
msg_stop = False
|
msg_stop = False
|
||||||
self.current_msg = ""
|
self.current_msg = ""
|
||||||
|
|
||||||
if (not msg_stop) and (
|
if (not msg_stop) and (48 <= b <= 57 or 65 <= b <= 70 or 97 <= b <= 102):
|
||||||
48 <= b <= 57 or 65 <= b <= 70 or 97 <= b <= 102
|
|
||||||
):
|
|
||||||
self.current_msg = self.current_msg + chr(b)
|
self.current_msg = self.current_msg + chr(b)
|
||||||
|
|
||||||
self.buffer = []
|
self.buffer = []
|
||||||
@@ -234,11 +232,7 @@ class TcpClient(object):
|
|||||||
msg = "".join("%02X" % j for j in payload)
|
msg = "".join("%02X" % j for j in payload)
|
||||||
i += 14 # Both message types use 14 bytes
|
i += 14 # Both message types use 14 bytes
|
||||||
tsbin = self.buffer[i : i + 6]
|
tsbin = self.buffer[i : i + 6]
|
||||||
sec = (
|
sec = ((tsbin[0] & 0x7F) << 10) | (tsbin[1] << 2) | (tsbin[2] >> 6)
|
||||||
((tsbin[0] & 0x7F) << 10)
|
|
||||||
| (tsbin[1] << 2)
|
|
||||||
| (tsbin[2] >> 6)
|
|
||||||
)
|
|
||||||
nano = (
|
nano = (
|
||||||
((tsbin[2] & 0x3F) << 24)
|
((tsbin[2] & 0x3F) << 24)
|
||||||
| (tsbin[3] << 16)
|
| (tsbin[3] << 16)
|
||||||
|
|||||||
@@ -108,9 +108,7 @@ class Decode:
|
|||||||
self.acs[icao][oe] = msg
|
self.acs[icao][oe] = msg
|
||||||
self.acs[icao]["t" + str(oe)] = t
|
self.acs[icao]["t" + str(oe)] = t
|
||||||
|
|
||||||
if ("tpos" in self.acs[icao]) and (
|
if ("tpos" in self.acs[icao]) and (t - self.acs[icao]["tpos"] < 180):
|
||||||
t - self.acs[icao]["tpos"] < 180
|
|
||||||
):
|
|
||||||
# use single message decoding
|
# use single message decoding
|
||||||
rlat = self.acs[icao]["lat"]
|
rlat = self.acs[icao]["lat"]
|
||||||
rlon = self.acs[icao]["lon"]
|
rlon = self.acs[icao]["lon"]
|
||||||
@@ -174,9 +172,7 @@ class Decode:
|
|||||||
ac["HFOMr"], ac["VFOMr"] = pms.adsb.nac_v(msg)
|
ac["HFOMr"], ac["VFOMr"] = pms.adsb.nac_v(msg)
|
||||||
|
|
||||||
if tc == 29:
|
if tc == 29:
|
||||||
ac["PE_RCu"], ac["PE_VPL"], ac["base"] = pms.adsb.sil(
|
ac["PE_RCu"], ac["PE_VPL"], ac["base"] = pms.adsb.sil(msg, ac["ver"])
|
||||||
msg, ac["ver"]
|
|
||||||
)
|
|
||||||
ac["EPU"], ac["VEPU"] = pms.adsb.nac_p(msg)
|
ac["EPU"], ac["VEPU"] = pms.adsb.nac_p(msg)
|
||||||
|
|
||||||
if tc == 31:
|
if tc == 31:
|
||||||
|
|||||||
@@ -147,9 +147,7 @@ class Screen(object):
|
|||||||
|
|
||||||
total_page = len(icaos) // (self.scr_h - 4) + 1
|
total_page = len(icaos) // (self.scr_h - 4) + 1
|
||||||
current_page = self.offset // (self.scr_h - 4) + 1
|
current_page = self.offset // (self.scr_h - 4) + 1
|
||||||
self.screen.addstr(
|
self.screen.addstr(self.scr_h - 2, 1, "(%d / %d)" % (current_page, total_page))
|
||||||
self.scr_h - 2, 1, "(%d / %d)" % (current_page, total_page)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.reset_cursor_pos()
|
self.reset_cursor_pos()
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ from pyModeS import adsb, ehs
|
|||||||
|
|
||||||
# === Decode sample data file ===
|
# === Decode sample data file ===
|
||||||
|
|
||||||
|
|
||||||
def adsb_decode_all(n=None):
|
def adsb_decode_all(n=None):
|
||||||
print("===== Decode ADS-B sample data=====")
|
print("===== Decode ADS-B sample data=====")
|
||||||
import csv
|
import csv
|
||||||
f = open('tests/data/sample_data_adsb.csv', 'rt')
|
|
||||||
|
f = open("tests/data/sample_data_adsb.csv", "rt")
|
||||||
|
|
||||||
msg0 = None
|
msg0 = None
|
||||||
msg1 = None
|
msg1 = None
|
||||||
@@ -37,5 +39,6 @@ def adsb_decode_all(n=None):
|
|||||||
alt = adsb.altitude(m)
|
alt = adsb.altitude(m)
|
||||||
print(ts, m, icao, tc, pos, alt)
|
print(ts, m, icao, tc, pos, alt)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
if __name__ == "__main__":
|
||||||
adsb_decode_all(n=100)
|
adsb_decode_all(n=100)
|
||||||
|
|||||||
+28
-11
@@ -3,12 +3,13 @@ from pyModeS import commb, common, bds
|
|||||||
|
|
||||||
# === Decode sample data file ===
|
# === Decode sample data file ===
|
||||||
|
|
||||||
|
|
||||||
def bds_info(BDS, m):
|
def bds_info(BDS, m):
|
||||||
if BDS == "BDS10":
|
if BDS == "BDS10":
|
||||||
info = [commb.ovc10(m)]
|
info = [commb.ovc10(m)]
|
||||||
|
|
||||||
elif BDS == "BDS17":
|
elif BDS == "BDS17":
|
||||||
info = ([i[-2:] for i in commb.cap17(m)])
|
info = [i[-2:] for i in commb.cap17(m)]
|
||||||
|
|
||||||
elif BDS == "BDS20":
|
elif BDS == "BDS20":
|
||||||
info = [commb.cs20(m)]
|
info = [commb.cs20(m)]
|
||||||
@@ -20,13 +21,30 @@ def bds_info(BDS, m):
|
|||||||
info = (commb.wind44(m), commb.temp44(m), commb.p44(m), commb.hum44(m))
|
info = (commb.wind44(m), commb.temp44(m), commb.p44(m), commb.hum44(m))
|
||||||
|
|
||||||
elif BDS == "BDS44REV":
|
elif BDS == "BDS44REV":
|
||||||
info = (commb.wind44(m, rev=True), commb.temp44(m, rev=True), commb.p44(m, rev=True), commb.hum44(m, rev=True))
|
info = (
|
||||||
|
commb.wind44(m, rev=True),
|
||||||
|
commb.temp44(m, rev=True),
|
||||||
|
commb.p44(m, rev=True),
|
||||||
|
commb.hum44(m, rev=True),
|
||||||
|
)
|
||||||
|
|
||||||
elif BDS == "BDS50":
|
elif BDS == "BDS50":
|
||||||
info = (commb.roll50(m), commb.trk50(m), commb.gs50(m), commb.rtrk50(m), commb.tas50(m))
|
info = (
|
||||||
|
commb.roll50(m),
|
||||||
|
commb.trk50(m),
|
||||||
|
commb.gs50(m),
|
||||||
|
commb.rtrk50(m),
|
||||||
|
commb.tas50(m),
|
||||||
|
)
|
||||||
|
|
||||||
elif BDS == "BDS60":
|
elif BDS == "BDS60":
|
||||||
info = (commb.hdg60(m), commb.ias60(m), commb.mach60(m), commb.vr60baro(m), commb.vr60ins(m))
|
info = (
|
||||||
|
commb.hdg60(m),
|
||||||
|
commb.ias60(m),
|
||||||
|
commb.mach60(m),
|
||||||
|
commb.vr60baro(m),
|
||||||
|
commb.vr60ins(m),
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
info = None
|
info = None
|
||||||
@@ -39,8 +57,7 @@ def commb_decode_all(df, n=None):
|
|||||||
|
|
||||||
print("===== Decode Comm-B sample data (DF=%s)=====" % df)
|
print("===== Decode Comm-B sample data (DF=%s)=====" % df)
|
||||||
|
|
||||||
f = open('tests/data/sample_data_commb_df%s.csv' % df, 'rt')
|
f = open("tests/data/sample_data_commb_df%s.csv" % df, "rt")
|
||||||
|
|
||||||
|
|
||||||
for i, r in enumerate(csv.reader(f)):
|
for i, r in enumerate(csv.reader(f)):
|
||||||
if n and i > n:
|
if n and i > n:
|
||||||
@@ -55,21 +72,21 @@ def commb_decode_all(df, n=None):
|
|||||||
code = common.altcode(m) if df == 20 else common.idcode(m)
|
code = common.altcode(m) if df == 20 else common.idcode(m)
|
||||||
|
|
||||||
if not BDS:
|
if not BDS:
|
||||||
print(ts, m, icao, df, '%5s'%code, 'UNKNOWN')
|
print(ts, m, icao, df, "%5s" % code, "UNKNOWN")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if len(BDS.split(",")) > 1:
|
if len(BDS.split(",")) > 1:
|
||||||
print(ts, m, icao, df, '%5s' % code, end=' ')
|
print(ts, m, icao, df, "%5s" % code, end=" ")
|
||||||
for i, _bds in enumerate(BDS.split(",")):
|
for i, _bds in enumerate(BDS.split(",")):
|
||||||
if i == 0:
|
if i == 0:
|
||||||
print(_bds, *bds_info(_bds, m))
|
print(_bds, *bds_info(_bds, m))
|
||||||
else:
|
else:
|
||||||
print(' ' * 55, _bds, *bds_info(_bds, m))
|
print(" " * 55, _bds, *bds_info(_bds, m))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(ts, m, icao, df, '%5s'%code, BDS, *bds_info(BDS, m))
|
print(ts, m, icao, df, "%5s" % code, BDS, *bds_info(BDS, m))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
commb_decode_all(df=20, n=100)
|
commb_decode_all(df=20, n=100)
|
||||||
commb_decode_all(df=21, n=100)
|
commb_decode_all(df=21, n=100)
|
||||||
|
|||||||
+14
-13
@@ -1,20 +1,21 @@
|
|||||||
from pyModeS import bds
|
from pyModeS import bds
|
||||||
|
|
||||||
def test_bds_infer():
|
|
||||||
assert bds.infer("8D406B902015A678D4D220AA4BDA") == 'BDS08'
|
|
||||||
assert bds.infer("8FC8200A3AB8F5F893096B000000") == 'BDS06'
|
|
||||||
assert bds.infer("8D40058B58C901375147EFD09357") == 'BDS05'
|
|
||||||
assert bds.infer("8D485020994409940838175B284F") == 'BDS09'
|
|
||||||
|
|
||||||
assert bds.infer("A800178D10010080F50000D5893C") == 'BDS10'
|
def test_bds_infer():
|
||||||
assert bds.infer("A0000638FA81C10000000081A92F") == 'BDS17'
|
assert bds.infer("8D406B902015A678D4D220AA4BDA") == "BDS08"
|
||||||
assert bds.infer("A0001838201584F23468207CDFA5") == 'BDS20'
|
assert bds.infer("8FC8200A3AB8F5F893096B000000") == "BDS06"
|
||||||
assert bds.infer("A0001839CA3800315800007448D9") == 'BDS40'
|
assert bds.infer("8D40058B58C901375147EFD09357") == "BDS05"
|
||||||
assert bds.infer("A000139381951536E024D4CCF6B5") == 'BDS50'
|
assert bds.infer("8D485020994409940838175B284F") == "BDS09"
|
||||||
assert bds.infer("A00004128F39F91A7E27C46ADC21") == 'BDS60'
|
|
||||||
|
assert bds.infer("A800178D10010080F50000D5893C") == "BDS10"
|
||||||
|
assert bds.infer("A0000638FA81C10000000081A92F") == "BDS17"
|
||||||
|
assert bds.infer("A0001838201584F23468207CDFA5") == "BDS20"
|
||||||
|
assert bds.infer("A0001839CA3800315800007448D9") == "BDS40"
|
||||||
|
assert bds.infer("A000139381951536E024D4CCF6B5") == "BDS50"
|
||||||
|
assert bds.infer("A00004128F39F91A7E27C46ADC21") == "BDS60"
|
||||||
|
|
||||||
|
|
||||||
def test_bds_is50or60():
|
def test_bds_is50or60():
|
||||||
assert bds.is50or60("A0001838201584F23468207CDFA5", 0, 0, 0) == None
|
assert bds.is50or60("A0001838201584F23468207CDFA5", 0, 0, 0) == None
|
||||||
assert bds.is50or60("A0000000FFDA9517000464000000", 182, 237, 1250) == 'BDS50'
|
assert bds.is50or60("A0000000FFDA9517000464000000", 182, 237, 1250) == "BDS50"
|
||||||
assert bds.is50or60("A0000000919A5927E23444000000", 413, 54, 18700) == 'BDS60'
|
assert bds.is50or60("A0000000919A5927E23444000000", 413, 54, 18700) == "BDS60"
|
||||||
|
|||||||
+9
-7
@@ -1,12 +1,14 @@
|
|||||||
from pyModeS import bds, commb
|
from pyModeS import bds, commb
|
||||||
|
|
||||||
# from pyModeS import ehs, els # deprecated
|
# from pyModeS import ehs, els # deprecated
|
||||||
|
|
||||||
def test_bds20_callsign():
|
|
||||||
assert bds.bds20.cs20("A000083E202CC371C31DE0AA1CCF") == 'KLM1017_'
|
|
||||||
assert bds.bds20.cs20("A0001993202422F2E37CE038738E") == 'IBK2873_'
|
|
||||||
|
|
||||||
assert commb.cs20("A000083E202CC371C31DE0AA1CCF") == 'KLM1017_'
|
def test_bds20_callsign():
|
||||||
assert commb.cs20("A0001993202422F2E37CE038738E") == 'IBK2873_'
|
assert bds.bds20.cs20("A000083E202CC371C31DE0AA1CCF") == "KLM1017_"
|
||||||
|
assert bds.bds20.cs20("A0001993202422F2E37CE038738E") == "IBK2873_"
|
||||||
|
|
||||||
|
assert commb.cs20("A000083E202CC371C31DE0AA1CCF") == "KLM1017_"
|
||||||
|
assert commb.cs20("A0001993202422F2E37CE038738E") == "IBK2873_"
|
||||||
|
|
||||||
|
|
||||||
def test_bds40_functions():
|
def test_bds40_functions():
|
||||||
@@ -21,14 +23,14 @@ def test_bds40_functions():
|
|||||||
|
|
||||||
def test_bds50_functions():
|
def test_bds50_functions():
|
||||||
assert bds.bds50.roll50("A000139381951536E024D4CCF6B5") == 2.1
|
assert bds.bds50.roll50("A000139381951536E024D4CCF6B5") == 2.1
|
||||||
assert bds.bds50.roll50("A0001691FFD263377FFCE02B2BF9") == -0.4 # signed value
|
assert bds.bds50.roll50("A0001691FFD263377FFCE02B2BF9") == -0.4 # signed value
|
||||||
assert bds.bds50.trk50("A000139381951536E024D4CCF6B5") == 114.258
|
assert bds.bds50.trk50("A000139381951536E024D4CCF6B5") == 114.258
|
||||||
assert bds.bds50.gs50("A000139381951536E024D4CCF6B5") == 438
|
assert bds.bds50.gs50("A000139381951536E024D4CCF6B5") == 438
|
||||||
assert bds.bds50.rtrk50("A000139381951536E024D4CCF6B5") == 0.125
|
assert bds.bds50.rtrk50("A000139381951536E024D4CCF6B5") == 0.125
|
||||||
assert bds.bds50.tas50("A000139381951536E024D4CCF6B5") == 424
|
assert bds.bds50.tas50("A000139381951536E024D4CCF6B5") == 424
|
||||||
|
|
||||||
assert commb.roll50("A000139381951536E024D4CCF6B5") == 2.1
|
assert commb.roll50("A000139381951536E024D4CCF6B5") == 2.1
|
||||||
assert commb.roll50("A0001691FFD263377FFCE02B2BF9") == -0.4 # signed value
|
assert commb.roll50("A0001691FFD263377FFCE02B2BF9") == -0.4 # signed value
|
||||||
assert commb.trk50("A000139381951536E024D4CCF6B5") == 114.258
|
assert commb.trk50("A000139381951536E024D4CCF6B5") == 114.258
|
||||||
assert commb.gs50("A000139381951536E024D4CCF6B5") == 438
|
assert commb.gs50("A000139381951536E024D4CCF6B5") == 438
|
||||||
assert commb.rtrk50("A000139381951536E024D4CCF6B5") == 0.125
|
assert commb.rtrk50("A000139381951536E024D4CCF6B5") == 0.125
|
||||||
|
|||||||
+39
-33
@@ -2,57 +2,63 @@ from pyModeS import common
|
|||||||
|
|
||||||
|
|
||||||
def test_conversions():
|
def test_conversions():
|
||||||
assert common.hex2bin('6E406B') == "011011100100000001101011"
|
assert common.hex2bin("6E406B") == "011011100100000001101011"
|
||||||
assert common.bin2hex('011011100100000001101011') == "6E406B"
|
assert common.bin2hex("011011100100000001101011") == "6E406B"
|
||||||
assert common.int2hex(11160538) == "AA4BDA"
|
assert common.int2hex(11160538) == "AA4BDA"
|
||||||
|
|
||||||
|
|
||||||
def test_crc_decode():
|
def test_crc_decode():
|
||||||
assert common.crc_legacy("8D406B902015A678D4D220AA4BDA") == 0
|
assert common.crc_legacy("8D406B902015A678D4D220AA4BDA") == 0
|
||||||
|
|
||||||
assert common.crc("8D406B902015A678D4D220AA4BDA") == 0
|
assert common.crc("8D406B902015A678D4D220AA4BDA") == 0
|
||||||
assert common.crc('8d8960ed58bf053cf11bc5932b7d') == 0
|
assert common.crc("8d8960ed58bf053cf11bc5932b7d") == 0
|
||||||
assert common.crc('8d45cab390c39509496ca9a32912') == 0
|
assert common.crc("8d45cab390c39509496ca9a32912") == 0
|
||||||
assert common.crc('8d49d3d4e1089d00000000744c3b') == 0
|
assert common.crc("8d49d3d4e1089d00000000744c3b") == 0
|
||||||
assert common.crc('8d74802958c904e6ef4ba0184d5c') == 0
|
assert common.crc("8d74802958c904e6ef4ba0184d5c") == 0
|
||||||
assert common.crc('8d4400cd9b0000b4f87000e71a10') == 0
|
assert common.crc("8d4400cd9b0000b4f87000e71a10") == 0
|
||||||
assert common.crc('8d4065de58a1054a7ef0218e226a') == 0
|
assert common.crc("8d4065de58a1054a7ef0218e226a") == 0
|
||||||
|
|
||||||
|
assert common.crc("c80b2dca34aa21dd821a04cb64d4") == 10719924
|
||||||
|
assert common.crc("a800089d8094e33a6004e4b8a522") == 4805588
|
||||||
|
assert common.crc("a8000614a50b6d32bed000bbe0ed") == 5659991
|
||||||
|
assert common.crc("a0000410bc900010a40000f5f477") == 11727682
|
||||||
|
assert common.crc("8d4ca251204994b1c36e60a5343d") == 16
|
||||||
|
assert common.crc("b0001718c65632b0a82040715b65") == 353333
|
||||||
|
|
||||||
assert common.crc('c80b2dca34aa21dd821a04cb64d4') == 10719924
|
|
||||||
assert common.crc('a800089d8094e33a6004e4b8a522') == 4805588
|
|
||||||
assert common.crc('a8000614a50b6d32bed000bbe0ed') == 5659991
|
|
||||||
assert common.crc('a0000410bc900010a40000f5f477') == 11727682
|
|
||||||
assert common.crc('8d4ca251204994b1c36e60a5343d') == 16
|
|
||||||
assert common.crc('b0001718c65632b0a82040715b65') == 353333
|
|
||||||
|
|
||||||
def test_crc_encode():
|
def test_crc_encode():
|
||||||
parity = common.crc("8D406B902015A678D4D220AA4BDA", encode=True)
|
parity = common.crc("8D406B902015A678D4D220AA4BDA", encode=True)
|
||||||
assert common.int2hex(parity) == "AA4BDA"
|
assert common.int2hex(parity) == "AA4BDA"
|
||||||
|
|
||||||
|
|
||||||
def test_icao():
|
def test_icao():
|
||||||
assert common.icao("8D406B902015A678D4D220AA4BDA") == "406B90"
|
assert common.icao("8D406B902015A678D4D220AA4BDA") == "406B90"
|
||||||
assert common.icao("A0001839CA3800315800007448D9") == '400940'
|
assert common.icao("A0001839CA3800315800007448D9") == "400940"
|
||||||
assert common.icao("A000139381951536E024D4CCF6B5") == '3C4DD2'
|
assert common.icao("A000139381951536E024D4CCF6B5") == "3C4DD2"
|
||||||
assert common.icao("A000029CFFBAA11E2004727281F1") == '4243D0'
|
assert common.icao("A000029CFFBAA11E2004727281F1") == "4243D0"
|
||||||
|
|
||||||
|
|
||||||
def test_modes_altcode():
|
def test_modes_altcode():
|
||||||
assert common.altcode("A02014B400000000000000F9D514") == 32300
|
assert common.altcode("A02014B400000000000000F9D514") == 32300
|
||||||
|
|
||||||
|
|
||||||
def test_modes_idcode():
|
def test_modes_idcode():
|
||||||
assert common.idcode("A800292DFFBBA9383FFCEB903D01") == '1346'
|
assert common.idcode("A800292DFFBBA9383FFCEB903D01") == "1346"
|
||||||
|
|
||||||
|
|
||||||
def test_graycode_to_altitude():
|
def test_graycode_to_altitude():
|
||||||
assert common.gray2alt('00000000010') == -1000
|
assert common.gray2alt("00000000010") == -1000
|
||||||
assert common.gray2alt('00000001010') == -500
|
assert common.gray2alt("00000001010") == -500
|
||||||
assert common.gray2alt('00000011011') == -100
|
assert common.gray2alt("00000011011") == -100
|
||||||
assert common.gray2alt('00000011010') == 0
|
assert common.gray2alt("00000011010") == 0
|
||||||
assert common.gray2alt('00000011110') == 100
|
assert common.gray2alt("00000011110") == 100
|
||||||
assert common.gray2alt('00000010011') == 600
|
assert common.gray2alt("00000010011") == 600
|
||||||
assert common.gray2alt('00000110010') == 1000
|
assert common.gray2alt("00000110010") == 1000
|
||||||
assert common.gray2alt('00001001001') == 5800
|
assert common.gray2alt("00001001001") == 5800
|
||||||
assert common.gray2alt('00011100100') == 10300
|
assert common.gray2alt("00011100100") == 10300
|
||||||
assert common.gray2alt('01100011010') == 32000
|
assert common.gray2alt("01100011010") == 32000
|
||||||
assert common.gray2alt('01110000100') == 46300
|
assert common.gray2alt("01110000100") == 46300
|
||||||
assert common.gray2alt('01010101100') == 50200
|
assert common.gray2alt("01010101100") == 50200
|
||||||
assert common.gray2alt('11011110100') == 73200
|
assert common.gray2alt("11011110100") == 73200
|
||||||
assert common.gray2alt('10000000011') == 126600
|
assert common.gray2alt("10000000011") == 126600
|
||||||
assert common.gray2alt('10000000001') == 126700
|
assert common.gray2alt("10000000001") == 126700
|
||||||
|
|||||||
Reference in New Issue
Block a user