update airborne_position(), allow swapping the odd and even messages
This commit is contained in:
parent
0eb333ba8c
commit
695fc34988
@ -24,6 +24,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 airborne_position(msg0, msg1, t0, t1):
|
def airborne_position(msg0, msg1, t0, t1):
|
||||||
"""Decode airborn position from a pair of even and odd position message
|
"""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:]
|
mb0 = common.hex2bin(msg0)[32:]
|
||||||
mb1 = common.hex2bin(msg1)[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.
|
# 131072 is 2^17, since CPR lat and lon are 17 bits each.
|
||||||
cprlat_even = common.bin2int(mb0[22:39]) / 131072.0
|
cprlat_even = common.bin2int(mb0[22:39]) / 131072.0
|
||||||
cprlon_even = common.bin2int(mb0[39:56]) / 131072.0
|
cprlon_even = common.bin2int(mb0[39:56]) / 131072.0
|
||||||
@ -66,17 +77,17 @@ def airborne_position(msg0, msg1, t0, t1):
|
|||||||
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)
|
nl = common.cprNL(lat)
|
||||||
ni = max(common.cprNL(lat)- 0, 1)
|
ni = max(common.cprNL(lat) - 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 = (360.0 / ni) * (m % ni + cprlon_even)
|
lon = (360.0 / ni) * (m % ni + cprlon_even)
|
||||||
else:
|
else:
|
||||||
lat = lat_odd
|
lat = lat_odd
|
||||||
nl = common.cprNL(lat)
|
nl = common.cprNL(lat)
|
||||||
ni = max(common.cprNL(lat) - 1, 1)
|
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)
|
lon = (360.0 / ni) * (m % ni + cprlon_odd)
|
||||||
|
|
||||||
if lon > 180:
|
if lon > 180:
|
||||||
@ -100,17 +111,17 @@ def airborne_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 = 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) \
|
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)
|
||||||
|
|
||||||
@ -121,8 +132,9 @@ def airborne_position_with_ref(msg, lat_ref, lon_ref):
|
|||||||
else:
|
else:
|
||||||
d_lon = 360.0
|
d_lon = 360.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)
|
||||||
|
|
||||||
@ -141,7 +153,7 @@ def altitude(msg):
|
|||||||
|
|
||||||
tc = common.typecode(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)
|
raise RuntimeError("%s: Not a airborn position message" % msg)
|
||||||
|
|
||||||
mb = common.hex2bin(msg)[32:]
|
mb = common.hex2bin(msg)[32:]
|
||||||
@ -150,7 +162,7 @@ def altitude(msg):
|
|||||||
# barometric altitude
|
# barometric altitude
|
||||||
q = mb[15]
|
q = mb[15]
|
||||||
if q:
|
if q:
|
||||||
n = common.bin2int(mb[8:15]+mb[16:20])
|
n = common.bin2int(mb[8:15] + mb[16:20])
|
||||||
alt = n * 25 - 1000
|
alt = n * 25 - 1000
|
||||||
else:
|
else:
|
||||||
alt = None
|
alt = None
|
||||||
|
@ -25,6 +25,16 @@ def test_adsb_position():
|
|||||||
assert pos == (49.81755, 6.08442)
|
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():
|
def test_adsb_position_with_ref():
|
||||||
pos = adsb.position_with_ref("8D40058B58C901375147EFD09357", 49.0, 6.0)
|
pos = adsb.position_with_ref("8D40058B58C901375147EFD09357", 49.0, 6.0)
|
||||||
assert pos == (49.82410, 6.06785)
|
assert pos == (49.82410, 6.06785)
|
||||||
@ -33,20 +43,14 @@ def test_adsb_position_with_ref():
|
|||||||
|
|
||||||
|
|
||||||
def test_adsb_airborne_position_with_ref():
|
def test_adsb_airborne_position_with_ref():
|
||||||
pos = adsb.airborne_position_with_ref(
|
pos = adsb.airborne_position_with_ref("8D40058B58C901375147EFD09357", 49.0, 6.0)
|
||||||
"8D40058B58C901375147EFD09357", 49.0, 6.0
|
|
||||||
)
|
|
||||||
assert pos == (49.82410, 6.06785)
|
assert pos == (49.82410, 6.06785)
|
||||||
pos = adsb.airborne_position_with_ref(
|
pos = adsb.airborne_position_with_ref("8D40058B58C904A87F402D3B8C59", 49.0, 6.0)
|
||||||
"8D40058B58C904A87F402D3B8C59", 49.0, 6.0
|
|
||||||
)
|
|
||||||
assert pos == (49.81755, 6.08442)
|
assert pos == (49.81755, 6.08442)
|
||||||
|
|
||||||
|
|
||||||
def test_adsb_surface_position_with_ref():
|
def test_adsb_surface_position_with_ref():
|
||||||
pos = adsb.surface_position_with_ref(
|
pos = adsb.surface_position_with_ref("8FC8200A3AB8F5F893096B000000", -43.5, 172.5)
|
||||||
"8FC8200A3AB8F5F893096B000000", -43.5, 172.5
|
|
||||||
)
|
|
||||||
assert pos == (-43.48564, 172.53942)
|
assert pos == (-43.48564, 172.53942)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user