diff --git a/pyModeS/decoder/bds/bds05.py b/pyModeS/decoder/bds/bds05.py index ea03945..15a64fe 100644 --- a/pyModeS/decoder/bds/bds05.py +++ b/pyModeS/decoder/bds/bds05.py @@ -24,6 +24,7 @@ from __future__ import absolute_import, print_function, division from pyModeS.decoder import common + def airborne_position(msg0, msg1, t0, t1): """Decode airborn position from a pair of even and odd position message @@ -40,6 +41,16 @@ def airborne_position(msg0, msg1, t0, t1): mb0 = common.hex2bin(msg0)[32:] mb1 = common.hex2bin(msg1)[32:] + oe0 = int(mb0[21]) + oe1 = int(mb1[21]) + if oe0 == 0 and oe1 == 1: + pass + elif oe0 == 1 and oe1 == 0: + mb0, mb1 = mb1, mb0 + t0, t1 = t1, t0 + else: + raise RuntimeError("Both even and odd CPR frames are required.") + # 131072 is 2^17, since CPR lat and lon are 17 bits each. cprlat_even = common.bin2int(mb0[22:39]) / 131072.0 cprlon_even = common.bin2int(mb0[39:56]) / 131072.0 @@ -66,17 +77,17 @@ def airborne_position(msg0, msg1, t0, t1): return None # compute ni, longitude index m, and longitude - if (t0 > t1): + if t0 > t1: lat = lat_even nl = common.cprNL(lat) - ni = max(common.cprNL(lat)- 0, 1) - m = common.floor(cprlon_even * (nl-1) - cprlon_odd * nl + 0.5) + ni = max(common.cprNL(lat) - 0, 1) + m = common.floor(cprlon_even * (nl - 1) - cprlon_odd * nl + 0.5) lon = (360.0 / ni) * (m % ni + cprlon_even) else: lat = lat_odd nl = common.cprNL(lat) ni = max(common.cprNL(lat) - 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 = (360.0 / ni) * (m % ni + cprlon_odd) if lon > 180: @@ -100,17 +111,17 @@ def airborne_position_with_ref(msg, lat_ref, lon_ref): (float, float): (latitude, longitude) of the aircraft """ - mb = common.hex2bin(msg)[32:] cprlat = common.bin2int(mb[22:39]) / 131072.0 cprlon = common.bin2int(mb[39:56]) / 131072.0 i = int(mb[21]) - d_lat = 360.0/59 if i else 360.0/60 + d_lat = 360.0 / 59 if i else 360.0 / 60 - j = common.floor(lat_ref / d_lat) \ - + common.floor(0.5 + ((lat_ref % d_lat) / d_lat) - cprlat) + j = common.floor(lat_ref / d_lat) + common.floor( + 0.5 + ((lat_ref % d_lat) / d_lat) - cprlat + ) lat = d_lat * (j + cprlat) @@ -121,8 +132,9 @@ def airborne_position_with_ref(msg, lat_ref, lon_ref): else: d_lon = 360.0 - m = common.floor(lon_ref / d_lon) \ - + common.floor(0.5 + ((lon_ref % d_lon) / d_lon) - cprlon) + m = common.floor(lon_ref / d_lon) + common.floor( + 0.5 + ((lon_ref % d_lon) / d_lon) - cprlon + ) lon = d_lon * (m + cprlon) @@ -141,7 +153,7 @@ def altitude(msg): tc = common.typecode(msg) - if tc<9 or tc==19 or tc>22: + if tc < 9 or tc == 19 or tc > 22: raise RuntimeError("%s: Not a airborn position message" % msg) mb = common.hex2bin(msg)[32:] @@ -150,7 +162,7 @@ def altitude(msg): # barometric altitude q = mb[15] if q: - n = common.bin2int(mb[8:15]+mb[16:20]) + n = common.bin2int(mb[8:15] + mb[16:20]) alt = n * 25 - 1000 else: alt = None diff --git a/tests/test_adsb.py b/tests/test_adsb.py index 58e5015..64599ab 100644 --- a/tests/test_adsb.py +++ b/tests/test_adsb.py @@ -25,6 +25,16 @@ def test_adsb_position(): assert pos == (49.81755, 6.08442) +def test_adsb_position_swap_odd_even(): + pos = adsb.position( + "8D40058B58C904A87F402D3B8C59", + "8D40058B58C901375147EFD09357", + 1446332405, + 1446332400, + ) + assert pos == (49.81755, 6.08442) + + def test_adsb_position_with_ref(): pos = adsb.position_with_ref("8D40058B58C901375147EFD09357", 49.0, 6.0) assert pos == (49.82410, 6.06785) @@ -33,20 +43,14 @@ def test_adsb_position_with_ref(): def test_adsb_airborne_position_with_ref(): - pos = adsb.airborne_position_with_ref( - "8D40058B58C901375147EFD09357", 49.0, 6.0 - ) + pos = adsb.airborne_position_with_ref("8D40058B58C901375147EFD09357", 49.0, 6.0) assert pos == (49.82410, 6.06785) - pos = adsb.airborne_position_with_ref( - "8D40058B58C904A87F402D3B8C59", 49.0, 6.0 - ) + pos = adsb.airborne_position_with_ref("8D40058B58C904A87F402D3B8C59", 49.0, 6.0) assert pos == (49.81755, 6.08442) def test_adsb_surface_position_with_ref(): - pos = adsb.surface_position_with_ref( - "8FC8200A3AB8F5F893096B000000", -43.5, 172.5 - ) + pos = adsb.surface_position_with_ref("8FC8200A3AB8F5F893096B000000", -43.5, 172.5) assert pos == (-43.48564, 172.53942)