11#!/usr/bin/env python3
22import time
3- from multiprocessing import Process , Queue
3+ from concurrent . futures import Future , ProcessPoolExecutor
44from typing import List , Optional
55
66import numpy as np
1010
1111from cereal import log , messaging
1212from laika import AstroDog
13- from laika .constants import SECS_IN_MIN
13+ from laika .constants import SECS_IN_HR , SECS_IN_MIN
1414from laika .ephemeris import EphemerisType , convert_ublox_ephem
1515from laika .gps_time import GPSTime
1616from laika .helpers import ConstellationId
@@ -29,8 +29,9 @@ class Laikad:
2929 def __init__ (self , valid_const = ("GPS" , "GLONASS" ), auto_update = False , valid_ephem_types = (EphemerisType .ULTRA_RAPID_ORBIT , EphemerisType .NAV )):
3030 self .astro_dog = AstroDog (valid_const = valid_const , auto_update = auto_update , valid_ephem_types = valid_ephem_types )
3131 self .gnss_kf = GNSSKalman (GENERATED_DIR )
32- self .orbit_p : Optional [Process ] = None
33- self .orbit_q = Queue ()
32+ self .orbit_fetch_executor = ProcessPoolExecutor ()
33+ self .orbit_fetch_future : Optional [Future ] = None
34+ self .last_fetch_orbits_t = None
3435
3536 def process_ublox_msg (self , ublox_msg , ublox_mono_time : int , block = False ):
3637 if ublox_msg .which == 'measurementReport' :
@@ -82,7 +83,7 @@ def process_ublox_msg(self, ublox_msg, ublox_mono_time: int, block=False):
8283 return dat
8384 elif ublox_msg .which == 'ephemeris' :
8485 ephem = convert_ublox_ephem (ublox_msg .ephemeris )
85- self .astro_dog .add_ephems ([ephem ], self . astro_dog . nav )
86+ self .astro_dog .add_navs ([ephem ])
8687 # elif ublox_msg.which == 'ionoData':
8788 # todo add this. Needed to better correct messages offline. First fix ublox_msg.cc to sent them.
8889
@@ -100,7 +101,7 @@ def update_localizer(self, pos_fix, t: float, measurements: List[GNSSMeasurement
100101 cloudlog .error ("Gnss kalman std too far" )
101102
102103 if len (pos_fix ) == 0 :
103- cloudlog .error ("Position fix not available when resetting kalman filter" )
104+ cloudlog .warning ("Position fix not available when resetting kalman filter" )
104105 return
105106 post_est = pos_fix [0 ][:3 ].tolist ()
106107 self .init_gnss_localizer (post_est )
@@ -124,36 +125,33 @@ def init_gnss_localizer(self, est_pos):
124125
125126 self .gnss_kf .init_state (x_initial , covs_diag = p_initial_diag )
126127
127- def get_orbit_data (self , t : GPSTime , queue ):
128- cloudlog .info (f"Start to download/parse orbits for time { t .as_datetime ()} " )
129- start_time = time .monotonic ()
130- try :
131- self .astro_dog .get_orbit_data (t , only_predictions = True )
132- except RuntimeError as e :
133- cloudlog .info (f"No orbit data found. { e } " )
134- return
135- cloudlog .info (f"Done parsing orbits. Took { time .monotonic () - start_time :.2f} s" )
136- if queue is not None :
137- queue .put ((self .astro_dog .orbits , self .astro_dog .orbit_fetched_times ))
138-
139128 def fetch_orbits (self , t : GPSTime , block ):
140- if t not in self .astro_dog .orbit_fetched_times :
141- if block :
142- self .get_orbit_data (t , None )
143- return
144- if self .orbit_p is None :
145- self .orbit_p = Process (target = self .get_orbit_data , args = (t , self .orbit_q ))
146- self .orbit_p .start ()
147- if not self .orbit_q .empty ():
148- ret = self .orbit_q .get ()
129+ if t not in self .astro_dog .orbit_fetched_times and (self .last_fetch_orbits_t is None or t - self .last_fetch_orbits_t > SECS_IN_HR ):
130+ astro_dog_vars = self .astro_dog .valid_const , self .astro_dog .auto_update , self .astro_dog .valid_ephem_types
131+ if self .orbit_fetch_future is None :
132+ self .orbit_fetch_future = self .orbit_fetch_executor .submit (get_orbit_data , t , * astro_dog_vars )
133+ if block :
134+ self .orbit_fetch_future .result ()
135+ if self .orbit_fetch_future .done ():
136+ ret = self .orbit_fetch_future .result ()
149137 if ret :
150138 self .astro_dog .orbits , self .astro_dog .orbit_fetched_times = ret
151- self .orbit_p .join ()
152- self .orbit_p = None
153-
154- def __del__ (self ):
155- if self .orbit_p is not None :
156- self .orbit_p .kill ()
139+ self .orbit_fetch_future = None
140+ self .last_fetch_orbits_t = t
141+
142+
143+ def get_orbit_data (t : GPSTime , valid_const , auto_update , valid_ephem_types ):
144+ astro_dog = AstroDog (valid_const = valid_const , auto_update = auto_update , valid_ephem_types = valid_ephem_types )
145+ cloudlog .info (f"Start to download/parse orbits for time { t .as_datetime ()} " )
146+ start_time = time .monotonic ()
147+ data = None
148+ try :
149+ astro_dog .get_orbit_data (t , only_predictions = True )
150+ data = (astro_dog .orbits , astro_dog .orbit_fetched_times )
151+ except RuntimeError as e :
152+ cloudlog .info (f"No orbit data found. { e } " )
153+ cloudlog .info (f"Done parsing orbits. Took { time .monotonic () - start_time :.1f} s" )
154+ return data
157155
158156
159157def create_measurement_msg (meas : GNSSMeasurement ):
0 commit comments