Laikad: the basics for ublox msg processing (#24359)
	
		
	
				
					
				
			* Add laikad that receives ublox messages and publishes corrected measurements and position fix * types * cleanup * laikad version 1 with uncorrected measurements * push * Fix glonass frequency and delete redundant test * Update after cereal and cleanup * Add test, fix laikad and remove process replay for now * update laika * add hatanaka to packages. Used to decompress orbit data * Fix pippull/24404/head^2
							parent
							
								
									df8f024e19
								
							
						
					
					
						commit
						b64fe6e339
					
				
				 5 changed files with 170 additions and 3 deletions
			
			
		| @ -1 +1 @@ | |||||||
| Subproject commit 226adc655e1488474468a97ab4a7705aad7e5837 | Subproject commit 1fbc6780d5184efd5ccf4518a01fe947ffbb4ba0 | ||||||
| @ -0,0 +1,84 @@ | |||||||
|  | #!/usr/bin/env python3 | ||||||
|  | from typing import List | ||||||
|  | 
 | ||||||
|  | from cereal import log, messaging | ||||||
|  | from laika import AstroDog | ||||||
|  | from laika.helpers import UbloxGnssId | ||||||
|  | from laika.raw_gnss import GNSSMeasurement, calc_pos_fix, correct_measurements, process_measurements, read_raw_ublox | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def correct_and_pos_fix(processed_measurements: List[GNSSMeasurement], dog: AstroDog): | ||||||
|  |   # pos fix needs more than 5 processed_measurements | ||||||
|  |   pos_fix = calc_pos_fix(processed_measurements) | ||||||
|  | 
 | ||||||
|  |   if len(pos_fix) == 0: | ||||||
|  |     return [], [] | ||||||
|  |   est_pos = pos_fix[0][:3] | ||||||
|  |   corrected = correct_measurements(processed_measurements, est_pos, dog) | ||||||
|  |   return calc_pos_fix(corrected), corrected | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def process_ublox_msg(ublox_msg, dog, ublox_mono_time: int): | ||||||
|  |   if ublox_msg.which == 'measurementReport': | ||||||
|  |     report = ublox_msg.measurementReport | ||||||
|  |     if len(report.measurements) == 0: | ||||||
|  |       return None | ||||||
|  |     new_meas = read_raw_ublox(report) | ||||||
|  |     processed_measurements = process_measurements(new_meas, dog) | ||||||
|  | 
 | ||||||
|  |     corrected = correct_and_pos_fix(processed_measurements, dog) | ||||||
|  |     pos_fix, _ = corrected | ||||||
|  |     # todo send corrected messages instead of processed_measurements. Need fix for when having less than 6 measurements | ||||||
|  |     correct_meas_msgs = [create_measurement_msg(m) for m in processed_measurements] | ||||||
|  |     # pos fix can be an empty list if not enough correct measurements are available | ||||||
|  |     if len(pos_fix) > 0: | ||||||
|  |       corrected_pos = pos_fix[0][:3].tolist() | ||||||
|  |     else: | ||||||
|  |       corrected_pos = [0., 0., 0.] | ||||||
|  |     dat = messaging.new_message('gnssMeasurements') | ||||||
|  |     dat.gnssMeasurements = { | ||||||
|  |       "position": corrected_pos, | ||||||
|  |       "ubloxMonoTime": ublox_mono_time, | ||||||
|  |       "correctedMeasurements": correct_meas_msgs | ||||||
|  |     } | ||||||
|  |     return dat | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def create_measurement_msg(meas: GNSSMeasurement): | ||||||
|  |   c = log.GnssMeasurements.CorrectedMeasurement.new_message() | ||||||
|  |   ublox_gnss_id = meas.ublox_gnss_id | ||||||
|  |   if ublox_gnss_id is None: | ||||||
|  |     # todo never happens will fix in later pr | ||||||
|  |     ublox_gnss_id = UbloxGnssId.GPS | ||||||
|  |   c.constellationId = ublox_gnss_id.value | ||||||
|  |   c.svId = int(meas.prn[1:]) | ||||||
|  |   c.glonassFrequency = meas.glonass_freq if meas.ublox_gnss_id == UbloxGnssId.GLONASS else 0 | ||||||
|  |   c.pseudorange = float(meas.observables['C1C'])  # todo should be observables_final when using corrected measurements | ||||||
|  |   c.pseudorangeStd = float(meas.observables_std['C1C']) | ||||||
|  |   c.pseudorangeRate = float(meas.observables['D1C'])  # todo should be observables_final when using corrected measurements | ||||||
|  |   c.pseudorangeRateStd = float(meas.observables_std['D1C']) | ||||||
|  |   c.satPos = meas.sat_pos_final.tolist() | ||||||
|  |   c.satVel = meas.sat_vel.tolist() | ||||||
|  |   return c | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def main(): | ||||||
|  |   dog = AstroDog() | ||||||
|  |   sm = messaging.SubMaster(['ubloxGnss']) | ||||||
|  |   pm = messaging.PubMaster(['gnssMeasurements']) | ||||||
|  | 
 | ||||||
|  |   while True: | ||||||
|  |     sm.update() | ||||||
|  | 
 | ||||||
|  |     # Todo if no internet available use latest ephemeris | ||||||
|  |     if sm.updated['ubloxGnss']: | ||||||
|  |       ublox_msg = sm['ubloxGnss'] | ||||||
|  |       msg = process_ublox_msg(ublox_msg, dog, sm.logMonoTime['ubloxGnss']) | ||||||
|  |       if msg is None: | ||||||
|  |         msg = messaging.new_message('gnssMeasurements') | ||||||
|  |       pm.send('gnssMeasurements', msg) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if __name__ == "__main__": | ||||||
|  |   main() | ||||||
| @ -0,0 +1,23 @@ | |||||||
|  | #!/usr/bin/env python3 | ||||||
|  | import unittest | ||||||
|  | from datetime import datetime | ||||||
|  | 
 | ||||||
|  | from laika.helpers import UbloxGnssId | ||||||
|  | 
 | ||||||
|  | from laika.gps_time import GPSTime | ||||||
|  | from laika.raw_gnss import GNSSMeasurement | ||||||
|  | from selfdrive.locationd.laikad import create_measurement_msg | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class TestLaikad(unittest.TestCase): | ||||||
|  | 
 | ||||||
|  |   def test_create_msg_without_errors(self): | ||||||
|  |     gpstime = GPSTime.from_datetime(datetime.now()) | ||||||
|  |     meas = GNSSMeasurement('G01', gpstime.week, gpstime.tow, {'C1C': 0., 'D1C': 0.}, {'C1C': 0., 'D1C': 0.}, ublox_gnss_id=UbloxGnssId.GPS) | ||||||
|  |     msg = create_measurement_msg(meas) | ||||||
|  | 
 | ||||||
|  |     self.assertEqual(msg.constellationId, 'gps') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if __name__ == "__main__": | ||||||
|  |   unittest.main() | ||||||
					Loading…
					
					
				
		Reference in new issue