update position decoding, handle surface position messages, error fix in vertical rate calculation.
This commit is contained in:
parent
556e499064
commit
2fccacd724
@ -60,7 +60,7 @@ Core functions for ADS-B decoding:
|
|||||||
|
|
||||||
pms.adsb.icao(msg)
|
pms.adsb.icao(msg)
|
||||||
pms.adsb.callsign(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.altitude(msg)
|
||||||
pms.adsb.velocity(msg)
|
pms.adsb.velocity(msg)
|
||||||
pms.adsb.speed_heading(msg)
|
pms.adsb.speed_heading(msg)
|
||||||
|
@ -222,11 +222,99 @@ def airborne_position(msg0, msg1, t0, t1):
|
|||||||
return round(lat, 5), round(lon, 5)
|
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):
|
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...')
|
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):
|
def _cprNL(lat):
|
||||||
if lat == 0:
|
if lat == 0:
|
||||||
return 59
|
return 59
|
||||||
@ -356,8 +444,8 @@ def velocity(msg):
|
|||||||
tag = 'AS'
|
tag = 'AS'
|
||||||
|
|
||||||
vr_sign = util.bin2int(msgbin[68])
|
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
|
rocd = -1*vr if vr_sign else vr # rate of climb/descend
|
||||||
|
|
||||||
return int(spd), round(hdg, 1), int(rocd), tag
|
return int(spd), round(hdg, 1), int(rocd), tag
|
||||||
|
|
||||||
|
35
tests/run.py
35
tests/run.py
@ -39,13 +39,28 @@ def test_adsb_callsign():
|
|||||||
assert adsb.callsign("8D406B902015A678D4D220AA4BDA") == "EZY85MH_"
|
assert adsb.callsign("8D406B902015A678D4D220AA4BDA") == "EZY85MH_"
|
||||||
|
|
||||||
|
|
||||||
def test_adsb_position():
|
def test_adsb_airborne_position():
|
||||||
pos = adsb.position("8D40058B58C901375147EFD09357",
|
pos = adsb.airborne_position("8D40058B58C901375147EFD09357",
|
||||||
"8D40058B58C904A87F402D3B8C59",
|
"8D40058B58C904A87F402D3B8C59",
|
||||||
1446332400, 1446332405)
|
1446332400, 1446332405)
|
||||||
assert pos == (49.81755, 6.08442)
|
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():
|
def test_adsb_alt():
|
||||||
assert adsb.altitude("8D40058B58C901375147EFD09357") == 39000
|
assert adsb.altitude("8D40058B58C901375147EFD09357") == 39000
|
||||||
|
|
||||||
@ -53,8 +68,8 @@ def test_adsb_alt():
|
|||||||
def test_adsb_velocity():
|
def test_adsb_velocity():
|
||||||
vgs = adsb.velocity("8D485020994409940838175B284F")
|
vgs = adsb.velocity("8D485020994409940838175B284F")
|
||||||
vas = adsb.velocity("8DA05F219B06B6AF189400CBC33F")
|
vas = adsb.velocity("8DA05F219B06B6AF189400CBC33F")
|
||||||
assert vgs == (159, 182.9, -263, 'GS')
|
assert vgs == (159, 182.9, -14, 'GS')
|
||||||
assert vas == (376, 244.0, -274, 'AS')
|
assert vas == (376, 244.0, -37, 'AS')
|
||||||
|
|
||||||
|
|
||||||
def test_nic():
|
def test_nic():
|
||||||
@ -183,5 +198,9 @@ def ehs_decode_all(n=None):
|
|||||||
print ts, m, icao, vBDS
|
print ts, m, icao, vBDS
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
adsb_decode_all(100)
|
# adsb_decode_all(100)
|
||||||
ehs_decode_all(100)
|
# ehs_decode_all(100)
|
||||||
|
|
||||||
|
|
||||||
|
adsb.airborne_position_with_ref("8D40058B58C901375147EFD09357",
|
||||||
|
49.0, 6.0)
|
Loading…
Reference in New Issue
Block a user