Merge branch 'JoseAndresMR-master', add ADS-B uncertainties

This commit is contained in:
Junzi Sun 2018-06-22 22:52:36 +02:00
commit bbe6e50fb2
2 changed files with 317 additions and 14 deletions

View File

@ -166,23 +166,47 @@ def speed_heading(msg):
return spd, trk_or_hdg return spd, trk_or_hdg
def nic(msg): def oe_flag(msg):
"""Calculate NIC, navigation integrity category """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
"""
msgbin = common.hex2bin(msg)
return int(msgbin[53])
# Uncertainty & accuracy
def nic(msg, *argv):
if len(argv) == 1:
# assume ads-b v1, only one supplement bit
return nic_v1(msg, *argv)
elif len(argv) == 3:
# assume ads-b v2, three supplement bits
return nic_v2(msg, *argv)
def nic_v1(msg, nic_sup_b):
"""Calculate NIC, navigation integrity category for ADS-B version 1
Args: Args:
msg (string): 28 bytes hexadecimal message string msg (string): 28 bytes hexadecimal message string
nic_sup_b (int or string): NIC supplement
Returns: Returns:
int: NIC number (from 0 to 11), -1 if not applicable int: NIC number (from 0 to 11), -1 if not applicable
""" """
if typecode(msg) < 9 or typecode(msg) > 18: if typecode(msg) < 5 or typecode(msg) > 22:
raise RuntimeError("%s: Not a airborne position message, expecting 8<TC<19" % msg) raise RuntimeError("%s: Not a surface position message (5<TC<8), \
airborne position message (8<TC<19), \
or airborne position with GNSS height (20<TC<22)" % msg)
msgbin = common.hex2bin(msg)
tc = typecode(msg) tc = typecode(msg)
nic_sup_b = common.bin2int(msgbin[39])
if tc in [0, 18, 22]: if nic_sup_b in ['0', '1']:
nic_sup_b = int(nic_sup_b)
if tc in [0, 8, 18, 22]:
nic = 0 nic = 0
elif tc == 17: elif tc == 17:
nic = 1 nic = 1
@ -196,7 +220,10 @@ def nic(msg):
elif tc == 14: elif tc == 14:
nic = 5 nic = 5
elif tc == 13: elif tc == 13:
nic = 6 if nic_sup_b:
nic = 6
else:
nic = 6
elif tc == 12: elif tc == 12:
nic = 7 nic = 7
elif tc == 11: elif tc == 11:
@ -204,21 +231,251 @@ def nic(msg):
nic = 9 nic = 9
else: else:
nic = 8 nic = 8
elif tc in [10, 21]: elif tc in [6, 10, 21]:
nic = 10 nic = 10
elif tc in [9, 20]: elif tc in [5, 9, 20]:
nic = 11 nic = 11
elif tc == 7:
if nic_sup_b:
nic = 9
else:
nic = 8
else: else:
nic = -1 nic = -1
return nic return nic
def oe_flag(msg): def nic_v2(msg, nic_a, nic_b, nic_c):
"""Check the odd/even flag. Bit 54, 0 for even, 1 for odd. """Calculate NIC, navigation integrity category, for ADS-B version 2
Args: Args:
msg (string): 28 bytes hexadecimal message string msg (string): 28 bytes hexadecimal message string
nic_a (int or string): NIC supplement
nic_b (int or srting): NIC supplement
nic_c (int or string): NIC supplement
Returns: Returns:
int: 0 or 1, for even or odd frame int: NIC number (from 0 to 11), -1 if not applicable
""" """
if typecode(msg) < 5 or typecode(msg) > 22:
raise RuntimeError("%s: Not a surface position message (5<TC<8) \
airborne position message (8<TC<19), \
or airborne position with GNSS height (20<TC<22)" % msg)
tc = typecode(msg)
if nic_a in ['0', '1']:
nic_a = int(nic_a)
if nic_b in ['0', '1']:
nic_b = int(nic_b)
if nic_c in ['0', '1']:
nic_c = int(nic_c)
if tc in [0, 18, 22]:
nic = 0
elif tc == 17:
nic = 1
elif tc == 16:
if nic_a:
nic = 3
else:
nic = 2
elif tc == 15:
nic = 4
elif tc == 14:
nic = 5
elif tc == 13:
if nic_a:
nic = 6
else:
if nic_b:
nic = 6
else:
nic = 6
elif tc == 12:
nic = 7
elif tc == 11:
if nic_a:
nic = 9
else:
nic = 8
elif tc in [6, 10, 21]:
nic = 10
elif tc in [5, 9, 20]:
nic = 11
elif tc == 8:
if nic_a:
if nic_c:
nic = 7
else:
nic = 6
else:
if nic_c:
nic = 6
else:
nic = 0
elif tc == 7:
if nic_a:
nic = 9
else:
nic = 8
else:
nic = -1
return nic
def nic_s(msg):
"""Obtain NIC supplement bit, TC=31 message
Args:
msg (string): 28 bytes hexadecimal message string
Returns:
int: NICs number (0 or 1)
"""
tc = typecode(msg)
if tc != 31:
raise RuntimeError("%s: Not a status operation message, expecting TC = 31" % msg)
msgbin = common.hex2bin(msg) msgbin = common.hex2bin(msg)
return int(msgbin[53]) nic_s = int(msgbin[75])
return nic_s
def nic_a_c(msg):
"""Obtain NICa/c, navigation integrity category supplements a and c
Args:
msg (string): 28 bytes hexadecimal message string
Returns:
(int, int): NICa and NICc number (0 or 1)
"""
tc = typecode(msg)
if tc != 31:
raise RuntimeError("%s: Not a status operation message, expecting TC = 31" % msg)
msgbin = common.hex2bin(msg)
nic_a = int(msgbin[75])
nic_c = int(msgbin[51])
return nic_a, nic_c
def nic_b(msg):
"""Obtain NICb, navigation integrity category supplement-b
Args:
msg (string): 28 bytes hexadecimal message string
Returns:
int: NICb number (0 or 1)
"""
tc = typecode(msg)
if tc < 9 or tc > 18:
raise RuntimeError("%s: Not a airborne position message, expecting 8<TC<19" % msg)
msgbin = common.hex2bin(msg)
nic_b = int(msgbin[39])
return nic_b
def nac_p(msg):
"""Calculate NACp, Navigation Accuracy Category - Position
Args:
msg (string): 28 bytes hexadecimal message string, TC = 29 or 31
Returns:
int: NACp number (0 or 1)
"""
tc = typecode(msg)
if tc not in [29, 31]:
raise RuntimeError("%s: Not a target state and status message, \
or operation status message, expecting TC = 29 or 31" % msg)
msgbin = common.hex2bin(msg)
if tc == 29:
nac_p = common.bin2int(msgbin[71:75])
elif tc == 31:
nac_p = common.bin2int(msgbin[76:80])
return nac_p
def nac_v(msg):
"""Calculate NACv, Navigation Accuracy Category - Velocity
Args:
msg (string): 28 bytes hexadecimal message string, TC = 19
Returns:
int: NACv number (from 0 to 4), -1 if not applicable
"""
tc = typecode(msg)
if tc != 19:
raise RuntimeError("%s: Not an airborne velocity message, expecting TC = 19" % msg)
msgbin = common.hex2bin(msg)
nac_v = common.bin2int(msgbin[42:45])
return nac_v
def sil(msg, version):
"""Calculate SIL, Surveillance Integrity Level
Args:
msg (string): 28 bytes hexadecimal message string with TC = 29, 31
Returns:
(int, int): sil number and sil supplement (only for v2)
"""
tc = typecode(msg)
if tc not in [29, 31]:
raise RuntimeError("%s: Not a target state and status messag, \
or operation status message, expecting TC = 29 or 31" % msg)
msgbin = common.hex2bin(msg)
if tc == 29:
sil = common.bin2int(msgbin[76:78])
elif tc == 31:
sil = common.bin2int(msg[82:84])
if version == 2:
if version == 29:
sil_sup = common.bin2int(msgbin[39])
elif version == 31:
sil_sup = common.bin2int(msgbin[86])
return sil, sil_sup
def version(msg):
"""ADS-B Version
Args:
msg (string): 28 bytes hexadecimal message string, TC = 31
Returns:
int: version number
"""
tc = typecode(msg)
if tc != 31:
raise RuntimeError("%s: Not a status operation message, expecting TC = 31" % msg)
msgbin = common.hex2bin(msg)
version = common.bin2int(msgbin[72:75])
return version

View File

@ -46,6 +46,11 @@ class Stream():
'ias': None, 'ias': None,
'mach': None, 'mach': None,
'hdg': None, 'hdg': None,
'adsb_version' : None,
'nic_s' : None,
'nic_a' : None,
'nic_b' : None,
'nic_c' : None
} }
self.acs[icao]['t'] = t self.acs[icao]['t'] = t
@ -103,6 +108,47 @@ class Stream():
self.acs[icao]['alt'] = adsb.altitude(msg) self.acs[icao]['alt'] = adsb.altitude(msg)
local_updated_acs_buffer.append(icao) local_updated_acs_buffer.append(icao)
# Uncertainty & accuracy
if (5 <= tc <= 8):
if self.acs[icao]['adsb_version'] == 1:
if self.acs[icao]['nic_s'] != None:
self.nic = adsb.nic_v1(msg, self.acs[icao]['nic_s'])
elif self.acs[icao]['adsb_version'] == 2:
if self.acs[icao]['nic_a'] != None and self.acs[icao]['nic_b'] != None:
self.nic = adsb.nic_v2(msg, self.nic_a, self.acs[icao]['nic_b'], self.acs[icao]['nic_c'])
if (9 <= tc <= 18):
if self.acs[icao]['adsb_version'] == 1:
if self.acs[icao]['nic_s'] != None:
self.nic = adsb.nic_v1(msg, self.acs[icao]['nic_s'])
elif self.acs[icao]['adsb_version'] == 2:
self.acs[icao]['nic_b'] = adsb.nic_b(msg)
if self.acs[icao]['nic_a'] != None and self.acs[icao]['nic_b'] != None:
self.nic = adsb.nic_v2(msg, self.acs[icao]['nic_a'], self.nic_b, self.acs[icao]['nic_c'])
if tc == 19:
self.acs[icao]['nac_v'] = adsb.nac_v(msg)
if (20 <= tc <= 22):
if self.acs[icao]['adsb_version'] == 1:
if self.acs[icao]['nic_s'] != None:
self.nic = adsb.nic_v1(msg, self.acs[icao]['nic_s'])
elif self.acs[icao]['adsb_version'] == 2:
if self.acs[icao]['nic_a'] != None and self.acs[icao]['nic_b'] != None:
self.nic = adsb.nic_v2(msg, self.acs[icao]['nic_a'], self.acs[icao]['nic_b'], self.acs[icao]['nic_c'])
if tc == 29:
if self.acs[icao]['adsb_version'] != None:
self.acs[icao]['sil'] = adsb.sil(msg, self.acs[icao]['adsb_version'])
self.acs[icao]['nac_p'] = adsb.nac_p(msg)
if tc == 31:
self.acs[icao]['adsb_version'] = adsb.version(msg)
self.acs[icao]['sil'] = adsb.version(msg)
self.acs[icao]['nac_p'] = adsb.nac_p(msg)
if self.acs[icao]['adsb_version'] == 1:
self.acs[icao]['nic_s'] = adsb.nic_s(msg)
elif self.acs[icao]['adsb_version'] == 2:
self.acs[icao]['nic_a'], self.acs[icao]['nic_c'] = adsb.nic_a_c(msg)
# process ehs message # process ehs message
for t, msg in zip(ehs_ts, ehs_msgs): for t, msg in zip(ehs_ts, ehs_msgs):
icao = ehs.icao(msg) icao = ehs.icao(msg)