|  |  |  | @ -147,21 +147,20 @@ class Localizer(): | 
			
		
	
		
			
				
					|  |  |  |  |     #fix.gpsTimeOfWeek = self.time.tow | 
			
		
	
		
			
				
					|  |  |  |  |     fix.unixTimestampMillis = self.unix_timestamp_millis | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     if self.filter_ready and self.calibrated: | 
			
		
	
		
			
				
					|  |  |  |  |     if np.limalg.norm(fix.positionECEF.std) < 50 and self.calibrated: | 
			
		
	
		
			
				
					|  |  |  |  |       fix.status = 'valid' | 
			
		
	
		
			
				
					|  |  |  |  |     elif self.filter_ready: | 
			
		
	
		
			
				
					|  |  |  |  |     elif np.limalg.norm(fix.positionECEF.std) < 50: | 
			
		
	
		
			
				
					|  |  |  |  |       fix.status = 'uncalibrated' | 
			
		
	
		
			
				
					|  |  |  |  |     else: | 
			
		
	
		
			
				
					|  |  |  |  |       fix.status = 'uninitialized' | 
			
		
	
		
			
				
					|  |  |  |  |     return fix | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   def update_kalman(self, time, kind, meas): | 
			
		
	
		
			
				
					|  |  |  |  |     if self.filter_ready: | 
			
		
	
		
			
				
					|  |  |  |  |       try: | 
			
		
	
		
			
				
					|  |  |  |  |         self.kf.predict_and_observe(time, kind, meas) | 
			
		
	
		
			
				
					|  |  |  |  |       except KalmanError: | 
			
		
	
		
			
				
					|  |  |  |  |         cloudlog.error("Error in predict and observe, kalman reset") | 
			
		
	
		
			
				
					|  |  |  |  |         self.reset_kalman() | 
			
		
	
		
			
				
					|  |  |  |  |     try: | 
			
		
	
		
			
				
					|  |  |  |  |       self.kf.predict_and_observe(time, kind, meas) | 
			
		
	
		
			
				
					|  |  |  |  |     except KalmanError: | 
			
		
	
		
			
				
					|  |  |  |  |       cloudlog.error("Error in predict and observe, kalman reset") | 
			
		
	
		
			
				
					|  |  |  |  |       self.reset_kalman() | 
			
		
	
		
			
				
					|  |  |  |  |     #idx = bisect_right([x[0] for x in self.observation_buffer], time) | 
			
		
	
		
			
				
					|  |  |  |  |     #self.observation_buffer.insert(idx, (time, kind, meas)) | 
			
		
	
		
			
				
					|  |  |  |  |     #while len(self.observation_buffer) > 0 and self.observation_buffer[-1][0] - self.observation_buffer[0][0] > self.max_age: | 
			
		
	
	
		
			
				
					|  |  |  | @ -171,40 +170,19 @@ class Localizer(): | 
			
		
	
		
			
				
					|  |  |  |  |   def handle_gps(self, current_time, log): | 
			
		
	
		
			
				
					|  |  |  |  |     self.converter = coord.LocalCoord.from_geodetic([log.latitude, log.longitude, log.altitude]) | 
			
		
	
		
			
				
					|  |  |  |  |     fix_ecef = self.converter.ned2ecef([0, 0, 0]) | 
			
		
	
		
			
				
					|  |  |  |  |     vel_ecef = self.converter.ned2ecef_matrix.dot(np.array(log.vNED)) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     #self.time = GPSTime.from_datetime(datetime.utcfromtimestamp(log.timestamp*1e-3)) | 
			
		
	
		
			
				
					|  |  |  |  |     self.unix_timestamp_millis = log.timestamp | 
			
		
	
		
			
				
					|  |  |  |  |     gps_est_error = np.sqrt((self.kf.x[0] - fix_ecef[0])**2 + | 
			
		
	
		
			
				
					|  |  |  |  |                             (self.kf.x[1] - fix_ecef[1])**2 + | 
			
		
	
		
			
				
					|  |  |  |  |                             (self.kf.x[2] - fix_ecef[2])**2) | 
			
		
	
		
			
				
					|  |  |  |  |     if gps_est_error > 50: | 
			
		
	
		
			
				
					|  |  |  |  |       cloudlog.error("Locationd vs ubloxLocation difference too large, kalman reset") | 
			
		
	
		
			
				
					|  |  |  |  |       self.reset_kalman(current_time) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # TODO initing with bad bearing not allowed, maybe not bad? | 
			
		
	
		
			
				
					|  |  |  |  |     if not self.filter_ready and log.speed > 5: | 
			
		
	
		
			
				
					|  |  |  |  |       self.filter_ready = True | 
			
		
	
		
			
				
					|  |  |  |  |       initial_ecef = fix_ecef | 
			
		
	
		
			
				
					|  |  |  |  |       gps_bearing = math.radians(log.bearing) | 
			
		
	
		
			
				
					|  |  |  |  |       initial_pose_ecef = ecef_euler_from_ned(initial_ecef, [0, 0, gps_bearing]) | 
			
		
	
		
			
				
					|  |  |  |  |       initial_pose_ecef_quat = quat_from_euler(initial_pose_ecef) | 
			
		
	
		
			
				
					|  |  |  |  |       gps_speed = log.speed | 
			
		
	
		
			
				
					|  |  |  |  |       quat_uncertainty = 0.2**2 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       initial_state = LiveKalman.initial_x | 
			
		
	
		
			
				
					|  |  |  |  |       initial_covs_diag = LiveKalman.initial_P_diag | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       initial_state[States.ECEF_POS] = initial_ecef | 
			
		
	
		
			
				
					|  |  |  |  |       initial_state[States.ECEF_ORIENTATION] = initial_pose_ecef_quat | 
			
		
	
		
			
				
					|  |  |  |  |       initial_state[States.ECEF_VELOCITY] = rot_from_quat(initial_pose_ecef_quat).dot(np.array([gps_speed, 0, 0])) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       initial_covs_diag[States.ECEF_POS_ERR] = 10**2 | 
			
		
	
		
			
				
					|  |  |  |  |       initial_covs_diag[States.ECEF_ORIENTATION_ERR] = quat_uncertainty | 
			
		
	
		
			
				
					|  |  |  |  |       initial_covs_diag[States.ECEF_VELOCITY_ERR] = 1**2 | 
			
		
	
		
			
				
					|  |  |  |  |       self.kf.init_state(initial_state, covs=np.diag(initial_covs_diag), filter_time=current_time) | 
			
		
	
		
			
				
					|  |  |  |  |       cloudlog.info("Filter initialized") | 
			
		
	
		
			
				
					|  |  |  |  |     elif self.filter_ready: | 
			
		
	
		
			
				
					|  |  |  |  |       self.update_kalman(current_time, ObservationKind.ECEF_POS, fix_ecef) | 
			
		
	
		
			
				
					|  |  |  |  |       gps_est_error = np.sqrt((self.kf.x[0] - fix_ecef[0])**2 + | 
			
		
	
		
			
				
					|  |  |  |  |                               (self.kf.x[1] - fix_ecef[1])**2 + | 
			
		
	
		
			
				
					|  |  |  |  |                               (self.kf.x[2] - fix_ecef[2])**2) | 
			
		
	
		
			
				
					|  |  |  |  |       if gps_est_error > 50: | 
			
		
	
		
			
				
					|  |  |  |  |         cloudlog.error("Locationd vs ubloxLocation difference too large, kalman reset") | 
			
		
	
		
			
				
					|  |  |  |  |         self.reset_kalman() | 
			
		
	
		
			
				
					|  |  |  |  |     self.update_kalman(current_time, ObservationKind.ECEF_POS, fix_ecef) | 
			
		
	
		
			
				
					|  |  |  |  |     self.update_kalman(current_time, ObservationKind.ECEF_VEL, vel_ecef) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   def handle_car_state(self, current_time, log): | 
			
		
	
		
			
				
					|  |  |  |  |     self.speed_counter += 1 | 
			
		
	
	
		
			
				
					|  |  |  | @ -256,9 +234,9 @@ class Localizer(): | 
			
		
	
		
			
				
					|  |  |  |  |     self.calib_from_device = self.device_from_calib.T | 
			
		
	
		
			
				
					|  |  |  |  |     self.calibrated = log.calStatus == 1 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   def reset_kalman(self): | 
			
		
	
		
			
				
					|  |  |  |  |     self.filter_time = None | 
			
		
	
		
			
				
					|  |  |  |  |     self.filter_ready = False | 
			
		
	
		
			
				
					|  |  |  |  |   def reset_kalman(self, current_time=None): | 
			
		
	
		
			
				
					|  |  |  |  |     self.filter_time = current_time | 
			
		
	
		
			
				
					|  |  |  |  |     self.kf.init_state(self.kf.x, covs=np.diag(LiveKalman.initial_P_diag), filter_time=current_time) | 
			
		
	
		
			
				
					|  |  |  |  |     self.observation_buffer = [] | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     self.gyro_counter = 0 | 
			
		
	
	
		
			
				
					|  |  |  | @ -292,7 +270,7 @@ def locationd_thread(sm, pm, disabled_logs=[]): | 
			
		
	
		
			
				
					|  |  |  |  |         elif sock == "liveCalibration": | 
			
		
	
		
			
				
					|  |  |  |  |           localizer.handle_live_calib(t, sm[sock]) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     if localizer.filter_ready and sm.updated['gpsLocationExternal']: | 
			
		
	
		
			
				
					|  |  |  |  |     if sm.updated['gpsLocationExternal']: | 
			
		
	
		
			
				
					|  |  |  |  |       t = sm.logMonoTime['gpsLocationExternal'] | 
			
		
	
		
			
				
					|  |  |  |  |       msg = messaging.new_message('liveLocationKalman') | 
			
		
	
		
			
				
					|  |  |  |  |       msg.logMonoTime = t | 
			
		
	
	
		
			
				
					|  |  |  | 
 |