LaikaD: Fix offline handling (#24781)

* Test handling no internet correctly.

* Clean

* Comment

* remove del
pull/214/head
Gijs Koning 3 years ago committed by GitHub
parent 45c43f9c87
commit a9bdc792a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 30
      selfdrive/locationd/laikad.py
  2. 22
      selfdrive/locationd/test/test_laikad.py

@ -30,12 +30,12 @@ class Laikad:
self.orbit_p: Optional[Process] = None self.orbit_p: Optional[Process] = None
self.orbit_q = Queue() self.orbit_q = Queue()
def process_ublox_msg(self, ublox_msg, ublox_mono_time: int): def process_ublox_msg(self, ublox_msg, ublox_mono_time: int, block=False):
if ublox_msg.which == 'measurementReport': if ublox_msg.which == 'measurementReport':
report = ublox_msg.measurementReport report = ublox_msg.measurementReport
if report.gpsWeek > 0: if report.gpsWeek > 0:
latest_msg_t = GPSTime(report.gpsWeek, report.rcvTow) latest_msg_t = GPSTime(report.gpsWeek, report.rcvTow)
self.fetch_orbits(latest_msg_t + SECS_IN_MIN, block=False) self.fetch_orbits(latest_msg_t + SECS_IN_MIN, block)
new_meas = read_raw_ublox(report) new_meas = read_raw_ublox(report)
measurements = process_measurements(new_meas, self.astro_dog) measurements = process_measurements(new_meas, self.astro_dog)
@ -110,25 +110,29 @@ class Laikad:
def get_orbit_data(self, t: GPSTime, queue): def get_orbit_data(self, t: GPSTime, queue):
cloudlog.info(f"Start to download/parse orbits for time {t.as_datetime()}") cloudlog.info(f"Start to download/parse orbits for time {t.as_datetime()}")
start_time = time.monotonic() start_time = time.monotonic()
self.astro_dog.get_orbit_data(t, only_predictions=True) try:
self.astro_dog.get_orbit_data(t, only_predictions=True)
except RuntimeError as e:
cloudlog.info(f"No orbit data found. {e}")
return
cloudlog.info(f"Done parsing orbits. Took {time.monotonic() - start_time:.2f}s") cloudlog.info(f"Done parsing orbits. Took {time.monotonic() - start_time:.2f}s")
queue.put((self.astro_dog.orbits, self.astro_dog.orbit_fetched_times)) if queue is not None:
queue.put((self.astro_dog.orbits, self.astro_dog.orbit_fetched_times))
def fetch_orbits(self, t: GPSTime, block): def fetch_orbits(self, t: GPSTime, block):
if t not in self.astro_dog.orbit_fetched_times: if t not in self.astro_dog.orbit_fetched_times:
if block:
self.get_orbit_data(t, None)
return
if self.orbit_p is None: if self.orbit_p is None:
self.orbit_p = Process(target=self.get_orbit_data, args=(t, self.orbit_q)) self.orbit_p = Process(target=self.get_orbit_data, args=(t, self.orbit_q))
self.orbit_p.start() self.orbit_p.start()
ret = None if not self.orbit_q.empty():
if block:
ret = self.orbit_q.get(block=True)
elif not self.orbit_q.empty():
ret = self.orbit_q.get() ret = self.orbit_q.get()
if ret:
if ret: self.astro_dog.orbits, self.astro_dog.orbit_fetched_times = ret
self.astro_dog.orbits, self.astro_dog.orbit_fetched_times = ret self.orbit_p.join()
self.orbit_p.join() self.orbit_p = None
self.orbit_p = None
def __del__(self): def __del__(self):
if self.orbit_p is not None: if self.orbit_p is not None:

@ -1,6 +1,8 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import unittest import unittest
from datetime import datetime from datetime import datetime
from unittest import mock
from unittest.mock import Mock
from laika.ephemeris import EphemerisType from laika.ephemeris import EphemerisType
from laika.gps_time import GPSTime from laika.gps_time import GPSTime
@ -21,7 +23,7 @@ def get_log(segs=range(0)):
def verify_messages(lr, laikad): def verify_messages(lr, laikad):
good_msgs = [] good_msgs = []
for m in lr: for m in lr:
msg = laikad.process_ublox_msg(m.ubloxGnss, m.logMonoTime) msg = laikad.process_ublox_msg(m.ubloxGnss, 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)
return good_msgs return good_msgs
@ -52,28 +54,21 @@ class TestLaikad(unittest.TestCase):
def test_laika_online_nav_only(self): def test_laika_online_nav_only(self):
laikad = Laikad(auto_update=True, valid_ephem_types=EphemerisType.NAV) laikad = Laikad(auto_update=True, valid_ephem_types=EphemerisType.NAV)
# Disable fetch_orbits to test NAV only
laikad.fetch_orbits = Mock()
correct_msgs = verify_messages(self.logs, laikad) correct_msgs = verify_messages(self.logs, laikad)
correct_msgs_expected = 560 correct_msgs_expected = 560
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]))
def test_laika_offline(self): @mock.patch('laika.downloader.download_and_cache_file')
# Set auto_update to false forces to use ephemeris messages def test_laika_offline(self, downloader_mock):
downloader_mock.side_effect = IOError
laikad = Laikad(auto_update=False) laikad = Laikad(auto_update=False)
correct_msgs = verify_messages(self.logs, laikad) correct_msgs = verify_messages(self.logs, laikad)
self.assertEqual(256, len(correct_msgs)) self.assertEqual(256, len(correct_msgs))
self.assertEqual(256, len([m for m in correct_msgs if m.gnssMeasurements.positionECEF.valid])) self.assertEqual(256, len([m for m in correct_msgs if m.gnssMeasurements.positionECEF.valid]))
def test_laika_offline_ephem_at_start(self):
# Test offline but process ephemeris msgs of segment first
laikad = Laikad(auto_update=False, valid_ephem_types=EphemerisType.NAV)
ephemeris_logs = [m for m in self.logs if m.ubloxGnss.which() == 'ephemeris']
correct_msgs = verify_messages(ephemeris_logs+self.logs, laikad)
self.assertEqual(554, len(correct_msgs))
self.assertGreaterEqual(554, len([m for m in correct_msgs if m.gnssMeasurements.positionECEF.valid]))
def test_laika_get_orbits(self): def test_laika_get_orbits(self):
laikad = Laikad(auto_update=False) laikad = Laikad(auto_update=False)
first_gps_time = None first_gps_time = None
@ -97,5 +92,6 @@ class TestLaikad(unittest.TestCase):
self.assertLess(0, len(laikad.astro_dog.orbits[prn])) self.assertLess(0, len(laikad.astro_dog.orbits[prn]))
print(min(laikad.astro_dog.orbits[prn], key=lambda e: e.epoch).epoch.as_datetime()) print(min(laikad.astro_dog.orbits[prn], key=lambda e: e.epoch).epoch.as_datetime())
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()

Loading…
Cancel
Save