|
|
|
@ -7,7 +7,7 @@ from collections import defaultdict |
|
|
|
|
from concurrent.futures import Future, ProcessPoolExecutor |
|
|
|
|
from datetime import datetime |
|
|
|
|
from enum import IntEnum |
|
|
|
|
from typing import List, Optional |
|
|
|
|
from typing import List, Optional, Dict, Any |
|
|
|
|
|
|
|
|
|
import numpy as np |
|
|
|
|
|
|
|
|
@ -241,12 +241,14 @@ class Laikad: |
|
|
|
|
new_meas = [m for m in new_meas if 1e7 < m.observables['C1C'] < 3e7] |
|
|
|
|
processed_measurements = process_measurements(new_meas, self.astro_dog) |
|
|
|
|
if self.last_fix_pos is not None: |
|
|
|
|
corrected_measurements = correct_measurements(processed_measurements, self.last_fix_pos, self.astro_dog) |
|
|
|
|
instant_fix = self.get_lsq_fix(t, corrected_measurements) |
|
|
|
|
#instant_fix = self.get_lsq_fix(t, processed_measurements) |
|
|
|
|
est_pos = self.last_fix_pos |
|
|
|
|
else: |
|
|
|
|
corrected_measurements = [] |
|
|
|
|
instant_fix = self.get_lsq_fix(t, processed_measurements) |
|
|
|
|
est_pos = self.gnss_kf.x[GStates.ECEF_POS].tolist() |
|
|
|
|
corrected_measurements = correct_measurements(processed_measurements, est_pos, self.astro_dog) |
|
|
|
|
return corrected_measurements |
|
|
|
|
|
|
|
|
|
def calc_fix(self, t, measurements): |
|
|
|
|
instant_fix = self.get_lsq_fix(t, measurements) |
|
|
|
|
if instant_fix is None: |
|
|
|
|
return None |
|
|
|
|
else: |
|
|
|
@ -254,64 +256,52 @@ class Laikad: |
|
|
|
|
self.last_fix_t = t |
|
|
|
|
self.last_fix_pos = position_estimate |
|
|
|
|
self.lat_fix_pos_std = position_std |
|
|
|
|
if (t*1e9) % 10 == 0: |
|
|
|
|
cloudlog.debug(f"Measurements Incoming/Processed/Corrected: {len(new_meas), len(processed_measurements), len(corrected_measurements)}") |
|
|
|
|
return position_estimate, position_std, velocity_estimate, velocity_std, corrected_measurements, processed_measurements |
|
|
|
|
return position_estimate, position_std, velocity_estimate, velocity_std |
|
|
|
|
|
|
|
|
|
def process_gnss_msg(self, gnss_msg, gnss_mono_time: int, block=False): |
|
|
|
|
out_msg = messaging.new_message("gnssMeasurements") |
|
|
|
|
out_msg.gnssMeasurements = { |
|
|
|
|
"timeToFirstFix": self.ttff, |
|
|
|
|
"ephemerisStatuses": self.create_ephem_statuses(), |
|
|
|
|
} |
|
|
|
|
t = gnss_mono_time * 1e-9 |
|
|
|
|
msg_dict: Dict[str, Any] = {"measTime": gnss_mono_time} |
|
|
|
|
if self.first_log_time is None: |
|
|
|
|
self.first_log_time = 1e-9 * gnss_mono_time |
|
|
|
|
if self.is_ephemeris(gnss_msg): |
|
|
|
|
self.read_ephemeris(gnss_msg) |
|
|
|
|
return out_msg |
|
|
|
|
elif self.is_good_report(gnss_msg): |
|
|
|
|
week, tow, new_meas = self.read_report(gnss_msg) |
|
|
|
|
self.gps_week = week |
|
|
|
|
if len(new_meas) == 0: |
|
|
|
|
return out_msg |
|
|
|
|
|
|
|
|
|
t = gnss_mono_time * 1e-9 |
|
|
|
|
if week > 0: |
|
|
|
|
self.got_first_gnss_msg = True |
|
|
|
|
latest_msg_t = GPSTime(week, tow) |
|
|
|
|
if self.auto_fetch_navs: |
|
|
|
|
self.fetch_navs(latest_msg_t, block) |
|
|
|
|
|
|
|
|
|
output = self.process_report(new_meas, t) |
|
|
|
|
if output is None: |
|
|
|
|
return out_msg |
|
|
|
|
if self.ttff <= 0: |
|
|
|
|
self.ttff = max(1e-3, t - self.first_log_time) |
|
|
|
|
position_estimate, position_std, velocity_estimate, velocity_std, corrected_measurements, _ = output |
|
|
|
|
corrected_measurements = self.process_report(new_meas, t) |
|
|
|
|
msg_dict['correctedMeasurements'] = [create_measurement_msg(m) for m in corrected_measurements] |
|
|
|
|
|
|
|
|
|
self.update_localizer(position_estimate, t, corrected_measurements) |
|
|
|
|
meas_msgs = [create_measurement_msg(m) for m in corrected_measurements] |
|
|
|
|
fix = self.calc_fix(t, corrected_measurements) |
|
|
|
|
measurement_msg = log.LiveLocationKalman.Measurement.new_message |
|
|
|
|
if fix is not None: |
|
|
|
|
position_estimate, position_std, velocity_estimate, velocity_std = fix |
|
|
|
|
if self.ttff <= 0: |
|
|
|
|
self.ttff = max(1e-3, t - self.first_log_time) |
|
|
|
|
msg_dict["positionECEF"] = measurement_msg(value=position_estimate, std=position_std.tolist(), valid=bool(self.last_fix_t == t)) |
|
|
|
|
msg_dict["velocityECEF"] = measurement_msg(value=velocity_estimate, std=velocity_std.tolist(), valid=bool(self.last_fix_t == t)) |
|
|
|
|
|
|
|
|
|
self.update_localizer(self.last_fix_pos, t, corrected_measurements) |
|
|
|
|
P_diag = self.gnss_kf.P.diagonal() |
|
|
|
|
kf_valid = all(self.kf_valid(t)) |
|
|
|
|
out_msg.gnssMeasurements = { |
|
|
|
|
"gpsWeek": week, |
|
|
|
|
"gpsTimeOfWeek": tow, |
|
|
|
|
"kalmanPositionECEF": measurement_msg(value=self.gnss_kf.x[GStates.ECEF_POS].tolist(), |
|
|
|
|
msg_dict["kalmanPositionECEF"] = measurement_msg(value=self.gnss_kf.x[GStates.ECEF_POS].tolist(), |
|
|
|
|
std=np.sqrt(P_diag[GStates.ECEF_POS]).tolist(), |
|
|
|
|
valid=kf_valid), |
|
|
|
|
"kalmanVelocityECEF": measurement_msg(value=self.gnss_kf.x[GStates.ECEF_VELOCITY].tolist(), |
|
|
|
|
valid=kf_valid) |
|
|
|
|
msg_dict["kalmanVelocityECEF"] = measurement_msg(value=self.gnss_kf.x[GStates.ECEF_VELOCITY].tolist(), |
|
|
|
|
std=np.sqrt(P_diag[GStates.ECEF_VELOCITY]).tolist(), |
|
|
|
|
valid=kf_valid), |
|
|
|
|
"positionECEF": measurement_msg(value=position_estimate, std=position_std.tolist(), valid=bool(self.last_fix_t == t)), |
|
|
|
|
"velocityECEF": measurement_msg(value=velocity_estimate, std=velocity_std.tolist(), valid=bool(self.last_fix_t == t)), |
|
|
|
|
|
|
|
|
|
"measTime": gnss_mono_time, |
|
|
|
|
"correctedMeasurements": meas_msgs, |
|
|
|
|
"timeToFirstFix": self.ttff, |
|
|
|
|
"ephemerisStatuses": self.create_ephem_statuses(), |
|
|
|
|
} |
|
|
|
|
valid=kf_valid) |
|
|
|
|
|
|
|
|
|
msg_dict['gpsWeek'] = self.last_report_time.week |
|
|
|
|
msg_dict['gpsTimeOfWeek'] = self.last_report_time.tow |
|
|
|
|
msg_dict['timeToFirstFix'] = self.ttff |
|
|
|
|
msg_dict['ephemerisStatuses'] = self.create_ephem_statuses() |
|
|
|
|
out_msg.gnssMeasurements = msg_dict |
|
|
|
|
return out_msg |
|
|
|
|
|
|
|
|
|
def update_localizer(self, est_pos, t: float, measurements: List[GNSSMeasurement]): |
|
|
|
@ -324,7 +314,7 @@ class Laikad: |
|
|
|
|
cloudlog.error("Time gap of over 10s detected, gnss kalman reset") |
|
|
|
|
elif not valid[2]: |
|
|
|
|
cloudlog.error("Gnss kalman filter state is nan") |
|
|
|
|
if len(est_pos) > 0: |
|
|
|
|
if est_pos is not None and len(est_pos) > 0: |
|
|
|
|
cloudlog.info(f"Reset kalman filter with {est_pos}") |
|
|
|
|
self.init_gnss_localizer(est_pos) |
|
|
|
|
else: |
|
|
|
|