|
|
@ -15,7 +15,7 @@ from laika.downloader import DownloadFailed |
|
|
|
from laika.ephemeris import EphemerisType, GPSEphemeris, ephemeris_structs |
|
|
|
from laika.ephemeris import EphemerisType, GPSEphemeris, ephemeris_structs |
|
|
|
from laika.gps_time import GPSTime |
|
|
|
from laika.gps_time import GPSTime |
|
|
|
from laika.helpers import ConstellationId, TimeRangeHolder |
|
|
|
from laika.helpers import ConstellationId, TimeRangeHolder |
|
|
|
from laika.raw_gnss import GNSSMeasurement, read_raw_ublox |
|
|
|
from laika.raw_gnss import GNSSMeasurement, read_raw_ublox, read_raw_qcom |
|
|
|
from selfdrive.locationd.laikad import EPHEMERIS_CACHE, EphemerisSourceType, Laikad, create_measurement_msg |
|
|
|
from selfdrive.locationd.laikad import EPHEMERIS_CACHE, EphemerisSourceType, Laikad, create_measurement_msg |
|
|
|
from selfdrive.test.openpilotci import get_url |
|
|
|
from selfdrive.test.openpilotci import get_url |
|
|
|
from tools.lib.logreader import LogReader |
|
|
|
from tools.lib.logreader import LogReader |
|
|
@ -70,14 +70,23 @@ def get_log(segs=range(0)): |
|
|
|
low_gnss.append(mb.as_reader()) |
|
|
|
low_gnss.append(mb.as_reader()) |
|
|
|
else: |
|
|
|
else: |
|
|
|
low_gnss.append(m) |
|
|
|
low_gnss.append(m) |
|
|
|
|
|
|
|
|
|
|
|
return all_logs, low_gnss |
|
|
|
return all_logs, low_gnss |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_log_qcom(segs=range(0)): |
|
|
|
|
|
|
|
logs = [] |
|
|
|
|
|
|
|
for i in segs: |
|
|
|
|
|
|
|
logs.extend(LogReader(get_url("b0b3cba7abf862d1|2023-03-11--09-40-33", i))) |
|
|
|
|
|
|
|
all_logs = [m for m in logs if m.which() == 'qcomGnss'] |
|
|
|
|
|
|
|
return all_logs |
|
|
|
|
|
|
|
|
|
|
|
def verify_messages(lr, laikad, return_one_success=False): |
|
|
|
def verify_messages(lr, laikad, return_one_success=False): |
|
|
|
good_msgs = [] |
|
|
|
good_msgs = [] |
|
|
|
for m in lr: |
|
|
|
for m in lr: |
|
|
|
msg = laikad.process_gnss_msg(m.ubloxGnss, m.logMonoTime, block=True) |
|
|
|
if m.which() == 'ubloxGnss': |
|
|
|
|
|
|
|
gnss_msg = m.ubloxGnss |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
gnss_msg = m.qcomGnss |
|
|
|
|
|
|
|
msg = laikad.process_gnss_msg(gnss_msg, m.logMonoTime, block=True) |
|
|
|
if msg is not None and len(msg.gnssMeasurements.correctedMeasurements) > 0: |
|
|
|
if msg is not None and len(msg.gnssMeasurements.correctedMeasurements) > 0: |
|
|
|
good_msgs.append(msg) |
|
|
|
good_msgs.append(msg) |
|
|
|
if return_one_success: |
|
|
|
if return_one_success: |
|
|
@ -87,10 +96,16 @@ def verify_messages(lr, laikad, return_one_success=False): |
|
|
|
|
|
|
|
|
|
|
|
def get_first_gps_time(logs): |
|
|
|
def get_first_gps_time(logs): |
|
|
|
for m in logs: |
|
|
|
for m in logs: |
|
|
|
|
|
|
|
if m.which() == 'ubloxGnss': |
|
|
|
if m.ubloxGnss.which == 'measurementReport': |
|
|
|
if m.ubloxGnss.which == 'measurementReport': |
|
|
|
new_meas = read_raw_ublox(m.ubloxGnss.measurementReport) |
|
|
|
new_meas = read_raw_ublox(m.ubloxGnss.measurementReport) |
|
|
|
if len(new_meas) > 0: |
|
|
|
if len(new_meas) > 0: |
|
|
|
return new_meas[0].recv_time |
|
|
|
return new_meas[0].recv_time |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
if m.qcomGnss.which == 'measurementReport': |
|
|
|
|
|
|
|
new_meas = read_raw_qcom(m.qcomGnss.measurementReport) |
|
|
|
|
|
|
|
if len(new_meas) > 0: |
|
|
|
|
|
|
|
return new_meas[0].recv_time |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_measurement_mock(gpstime, sat_ephemeris): |
|
|
|
def get_measurement_mock(gpstime, sat_ephemeris): |
|
|
@ -111,6 +126,7 @@ class TestLaikad(unittest.TestCase): |
|
|
|
logs, low_gnss = get_log(range(1)) |
|
|
|
logs, low_gnss = get_log(range(1)) |
|
|
|
cls.logs = logs |
|
|
|
cls.logs = logs |
|
|
|
cls.low_gnss = low_gnss |
|
|
|
cls.low_gnss = low_gnss |
|
|
|
|
|
|
|
cls.logs_qcom = get_log_qcom(range(1)) |
|
|
|
first_gps_time = get_first_gps_time(logs) |
|
|
|
first_gps_time = get_first_gps_time(logs) |
|
|
|
cls.first_gps_time = first_gps_time |
|
|
|
cls.first_gps_time = first_gps_time |
|
|
|
|
|
|
|
|
|
|
@ -209,10 +225,11 @@ class TestLaikad(unittest.TestCase): |
|
|
|
self.assertTrue(kf_valid) |
|
|
|
self.assertTrue(kf_valid) |
|
|
|
|
|
|
|
|
|
|
|
def test_laika_online_nav_only(self): |
|
|
|
def test_laika_online_nav_only(self): |
|
|
|
laikad = Laikad(auto_update=True, valid_ephem_types=EphemerisType.NAV) |
|
|
|
for use_qcom, logs in zip([True, False], [self.logs_qcom, self.logs]): |
|
|
|
|
|
|
|
laikad = Laikad(auto_update=True, valid_ephem_types=EphemerisType.NAV, use_qcom=use_qcom) |
|
|
|
# Disable fetch_orbits to test NAV only |
|
|
|
# Disable fetch_orbits to test NAV only |
|
|
|
correct_msgs = verify_messages(self.logs, laikad) |
|
|
|
correct_msgs = verify_messages(logs, laikad) |
|
|
|
correct_msgs_expected = 559 |
|
|
|
correct_msgs_expected = 42 if use_qcom else 559 |
|
|
|
self.assertEqual(correct_msgs_expected, len(correct_msgs)) |
|
|
|
self.assertEqual(correct_msgs_expected, len(correct_msgs)) |
|
|
|
self.assertEqual(correct_msgs_expected, len([m for m in correct_msgs if m.gnssMeasurements.positionECEF.valid])) |
|
|
|
self.assertEqual(correct_msgs_expected, len([m for m in correct_msgs if m.gnssMeasurements.positionECEF.valid])) |
|
|
|
|
|
|
|
|
|
|
@ -247,23 +264,31 @@ class TestLaikad(unittest.TestCase): |
|
|
|
print(min(laikad.astro_dog.navs[prn], key=lambda e: e.epoch).epoch.as_datetime()) |
|
|
|
print(min(laikad.astro_dog.navs[prn], key=lambda e: e.epoch).epoch.as_datetime()) |
|
|
|
|
|
|
|
|
|
|
|
def test_get_navs_in_process(self): |
|
|
|
def test_get_navs_in_process(self): |
|
|
|
laikad = Laikad(auto_update=False) |
|
|
|
for use_qcom, logs in zip([True, False], [self.logs_qcom, self.logs]): |
|
|
|
|
|
|
|
laikad = Laikad(auto_update=False, use_qcom=use_qcom) |
|
|
|
has_navs = False |
|
|
|
has_navs = False |
|
|
|
for m in self.logs: |
|
|
|
has_fix = False |
|
|
|
laikad.process_gnss_msg(m.ubloxGnss, m.logMonoTime, block=False) |
|
|
|
for m in logs: |
|
|
|
|
|
|
|
gnss_msg = m.qcomGnss if use_qcom else m.ubloxGnss |
|
|
|
|
|
|
|
out_msg = laikad.process_gnss_msg(gnss_msg, m.logMonoTime, block=False) |
|
|
|
if laikad.orbit_fetch_future is not None: |
|
|
|
if laikad.orbit_fetch_future is not None: |
|
|
|
laikad.orbit_fetch_future.result() |
|
|
|
laikad.orbit_fetch_future.result() |
|
|
|
vals = laikad.astro_dog.navs.values() |
|
|
|
vals = laikad.astro_dog.navs.values() |
|
|
|
has_navs = len(vals) > 0 and max([len(v) for v in vals]) > 0 |
|
|
|
has_navs = len(vals) > 0 and max([len(v) for v in vals]) > 0 |
|
|
|
if has_navs: |
|
|
|
vals = laikad.astro_dog.orbits.values() |
|
|
|
break |
|
|
|
has_polys = len(vals) > 0 and max([len(v) for v in vals]) > 0 |
|
|
|
self.assertTrue(has_navs) |
|
|
|
if out_msg is not None: |
|
|
|
|
|
|
|
has_fix = has_fix or out_msg.gnssMeasurements.positionECEF.valid |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.assertTrue(has_navs or has_polys) |
|
|
|
|
|
|
|
self.assertTrue(has_fix) |
|
|
|
self.assertGreater(len(laikad.astro_dog.navs_fetched_times._ranges), 0) |
|
|
|
self.assertGreater(len(laikad.astro_dog.navs_fetched_times._ranges), 0) |
|
|
|
self.assertEqual(None, laikad.orbit_fetch_future) |
|
|
|
self.assertEqual(None, laikad.orbit_fetch_future) |
|
|
|
|
|
|
|
|
|
|
|
def test_cache(self): |
|
|
|
def test_cache(self): |
|
|
|
laikad = Laikad(auto_update=True, save_ephemeris=True) |
|
|
|
use_qcom = True |
|
|
|
|
|
|
|
for use_qcom, logs in zip([True, False], [self.logs_qcom, self.logs]): |
|
|
|
|
|
|
|
laikad = Laikad(auto_update=True, save_ephemeris=True, use_qcom=use_qcom) |
|
|
|
def wait_for_cache(): |
|
|
|
def wait_for_cache(): |
|
|
|
max_time = 2 |
|
|
|
max_time = 2 |
|
|
|
while Params().get(EPHEMERIS_CACHE) is None: |
|
|
|
while Params().get(EPHEMERIS_CACHE) is None: |
|
|
@ -286,11 +311,11 @@ class TestLaikad(unittest.TestCase): |
|
|
|
wait_for_cache() |
|
|
|
wait_for_cache() |
|
|
|
|
|
|
|
|
|
|
|
# Check both nav and orbits separate |
|
|
|
# Check both nav and orbits separate |
|
|
|
laikad = Laikad(auto_update=False, valid_ephem_types=EphemerisType.NAV, save_ephemeris=True) |
|
|
|
laikad = Laikad(auto_update=False, valid_ephem_types=EphemerisType.NAV, save_ephemeris=True, use_qcom=use_qcom) |
|
|
|
# Verify navs are loaded from cache |
|
|
|
# Verify navs are loaded from cache |
|
|
|
self.dict_has_values(laikad.astro_dog.navs) |
|
|
|
self.dict_has_values(laikad.astro_dog.navs) |
|
|
|
# Verify cache is working for only nav by running a segment |
|
|
|
# Verify cache is working for only nav by running a segment |
|
|
|
msg = verify_messages(self.logs, laikad, return_one_success=True) |
|
|
|
msg = verify_messages(logs, laikad, return_one_success=True) |
|
|
|
self.assertIsNotNone(msg) |
|
|
|
self.assertIsNotNone(msg) |
|
|
|
|
|
|
|
|
|
|
|
with patch('selfdrive.locationd.laikad.get_orbit_data', return_value=None) as mock_method: |
|
|
|
with patch('selfdrive.locationd.laikad.get_orbit_data', return_value=None) as mock_method: |
|
|
@ -305,7 +330,7 @@ class TestLaikad(unittest.TestCase): |
|
|
|
self.assertIsNotNone(msg) |
|
|
|
self.assertIsNotNone(msg) |
|
|
|
# Verify orbit data is not downloaded |
|
|
|
# Verify orbit data is not downloaded |
|
|
|
mock_method.assert_not_called() |
|
|
|
mock_method.assert_not_called() |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
|
|
|
|
def test_low_gnss_meas(self): |
|
|
|
def test_low_gnss_meas(self): |
|
|
|
cnt = 0 |
|
|
|
cnt = 0 |
|
|
@ -323,6 +348,5 @@ class TestLaikad(unittest.TestCase): |
|
|
|
self.assertGreater(len(dct), 0) |
|
|
|
self.assertGreater(len(dct), 0) |
|
|
|
self.assertGreater(min([len(v) for v in dct.values()]), 0) |
|
|
|
self.assertGreater(min([len(v) for v in dct.values()]), 0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
if __name__ == "__main__": |
|
|
|
unittest.main() |
|
|
|
unittest.main() |
|
|
|