update position decoding, handle surface position messages, error fix in vertical rate calculation.

This commit is contained in:
junzis 2016-08-16 14:33:31 +02:00
parent 556e499064
commit 2fccacd724
3 changed files with 119 additions and 12 deletions

View File

@ -60,7 +60,7 @@ Core functions for ADS-B decoding:
pms.adsb.icao(msg)
pms.adsb.callsign(msg)
pms.adsb.position(msg_odd, msg_even, t_odd, t_even)
pms.adsb.position(msg_even, msg_odd, t_even, t_odd)
pms.adsb.altitude(msg)
pms.adsb.velocity(msg)
pms.adsb.speed_heading(msg)

View File

@ -222,11 +222,99 @@ def airborne_position(msg0, msg1, t0, t1):
return round(lat, 5), round(lon, 5)
def position_with_ref(msg, lat_ref, lon_ref):
if 5 <= typecode(msg) <= 8:
return airborne_position_with_ref(msg, lat_ref, lon_ref)
elif 9 <= typecode(msg) <= 18:
return surface_position_with_ref(msg, lat_ref, lon_ref)
else:
raise RuntimeError("incorrect or inconsistant message types")
def airborne_position_with_ref(msg, lat_ref, lon_ref):
"""Decode airborn position with one message,
knowing previous reference location
Args:
msg (string): even message (28 bytes hexadecimal string)
lat_ref: previous known latitude
lon_ref: previous known longitude
Returns:
(float, float): (latitude, longitude) of the aircraft
"""
i = oe_flag(msg)
d_lat = 360.0/59 if i else 360.0/60
msgbin = util.hex2bin(msg)
cprlat = util.bin2int(msgbin[54:71]) / 131072.0
cprlon = util.bin2int(msgbin[71:88]) / 131072.0
j = util.floor(lat_ref / d_lat) \
+ util.floor(0.5 + ((lat_ref % d_lat) / d_lat) - cprlat)
lat = d_lat * (j + cprlat)
ni = _cprNL(lat) - i
if ni > 0:
d_lon = 360.0 / ni
else:
d_lon = 360.0
m = util.floor(lon_ref / d_lon) \
+ util.floor(0.5 + ((lon_ref % d_lon) / d_lon) - cprlon)
lon = d_lon * (m + cprlon)
return round(lat, 5), round(lon, 5)
def surface_position(msg0, msg1, t0, t1):
# TODO: implement surface positon decoding
# TODO: implement surface positon
raise RuntimeError('suface position decoding to be implemented soon...')
def surface_position_with_ref(msg, lat_ref, lon_ref):
"""Decode surface position with one message,
knowing reference nearby location, such as previously calculated location,
ground station, or airport location, etc.
Args:
msg (string): even message (28 bytes hexadecimal string)
lat_ref: previous known latitude
lon_ref: previous known longitude
Returns:
(float, float): (latitude, longitude) of the aircraft
"""
i = oe_flag(msg)
d_lat = 90.0/59 if i else 90.0/60
msgbin = util.hex2bin(msg)
cprlat = util.bin2int(msgbin[54:71]) / 131072.0
cprlon = util.bin2int(msgbin[71:88]) / 131072.0
j = util.floor(lat_ref / d_lat) \
+ util.floor(0.5 + ((lat_ref % d_lat) / d_lat) - cprlat)
lat = d_lat * (j + cprlat)
ni = _cprNL(lat) - i
if ni > 0:
d_lon = 360.0 / ni
else:
d_lon = 360.0
m = util.floor(lon_ref / d_lon) \
+ util.floor(0.5 + ((lon_ref % d_lon) / d_lon) - cprlon)
lon = d_lon * (m + cprlon)
return round(lat, 5), round(lon, 5)
def _cprNL(lat):
if lat == 0:
return 59
@ -356,7 +444,7 @@ def velocity(msg):
tag = 'AS'
vr_sign = util.bin2int(msgbin[68])
vr = util.bin2int(msgbin[68:77]) # vertical rate
vr = util.bin2int(msgbin[69:78]) # vertical rate
rocd = -1*vr if vr_sign else vr # rate of climb/descend
return int(spd), round(hdg, 1), int(rocd), tag

View File

@ -39,13 +39,28 @@ def test_adsb_callsign():
assert adsb.callsign("8D406B902015A678D4D220AA4BDA") == "EZY85MH_"
def test_adsb_position():
pos = adsb.position("8D40058B58C901375147EFD09357",
def test_adsb_airborne_position():
pos = adsb.airborne_position("8D40058B58C901375147EFD09357",
"8D40058B58C904A87F402D3B8C59",
1446332400, 1446332405)
assert pos == (49.81755, 6.08442)
def test_adsb_airborne_position_with_ref():
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)
assert pos == (49.81755, 6.08442)
def test_adsb_surface_position_with_ref():
pos = adsb.surface_position_with_ref("8FC8200A3AB8F5F893096B22B4A8",
-43.5, 172.5)
assert pos == (-43.48564, 175.87195)
def test_adsb_alt():
assert adsb.altitude("8D40058B58C901375147EFD09357") == 39000
@ -53,8 +68,8 @@ def test_adsb_alt():
def test_adsb_velocity():
vgs = adsb.velocity("8D485020994409940838175B284F")
vas = adsb.velocity("8DA05F219B06B6AF189400CBC33F")
assert vgs == (159, 182.9, -263, 'GS')
assert vas == (376, 244.0, -274, 'AS')
assert vgs == (159, 182.9, -14, 'GS')
assert vas == (376, 244.0, -37, 'AS')
def test_nic():
@ -183,5 +198,9 @@ def ehs_decode_all(n=None):
print ts, m, icao, vBDS
if __name__ == '__main__':
adsb_decode_all(100)
ehs_decode_all(100)
# adsb_decode_all(100)
# ehs_decode_all(100)
adsb.airborne_position_with_ref("8D40058B58C901375147EFD09357",
49.0, 6.0)