|
|
@ -2,6 +2,7 @@ |
|
|
|
import math |
|
|
|
import math |
|
|
|
|
|
|
|
|
|
|
|
import numpy as np |
|
|
|
import numpy as np |
|
|
|
|
|
|
|
import sympy as sp |
|
|
|
|
|
|
|
|
|
|
|
import cereal.messaging as messaging |
|
|
|
import cereal.messaging as messaging |
|
|
|
import common.transformations.coordinates as coord |
|
|
|
import common.transformations.coordinates as coord |
|
|
@ -16,6 +17,9 @@ from selfdrive.swaglog import cloudlog |
|
|
|
#from datetime import datetime |
|
|
|
#from datetime import datetime |
|
|
|
#from laika.gps_time import GPSTime |
|
|
|
#from laika.gps_time import GPSTime |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from sympy.utilities.lambdify import lambdify |
|
|
|
|
|
|
|
from selfdrive.locationd.kalman.helpers.sympy_helpers import euler_rotate |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VISION_DECIMATION = 2 |
|
|
|
VISION_DECIMATION = 2 |
|
|
|
SENSOR_DECIMATION = 10 |
|
|
|
SENSOR_DECIMATION = 10 |
|
|
@ -25,6 +29,22 @@ def to_float(arr): |
|
|
|
return [float(arr[0]), float(arr[1]), float(arr[2])] |
|
|
|
return [float(arr[0]), float(arr[1]), float(arr[2])] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_H(): |
|
|
|
|
|
|
|
# this returns a function to eval the jacobian |
|
|
|
|
|
|
|
# of the observation function of the local vel |
|
|
|
|
|
|
|
roll = sp.Symbol('roll') |
|
|
|
|
|
|
|
pitch = sp.Symbol('pitch') |
|
|
|
|
|
|
|
yaw = sp.Symbol('yaw') |
|
|
|
|
|
|
|
vx = sp.Symbol('vx') |
|
|
|
|
|
|
|
vy = sp.Symbol('vy') |
|
|
|
|
|
|
|
vz = sp.Symbol('vz') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
h = euler_rotate(roll, pitch, yaw).T*(sp.Matrix([vx, vy, vz])) |
|
|
|
|
|
|
|
H = h.jacobian(sp.Matrix([roll, pitch, yaw, vx, vy, vz])) |
|
|
|
|
|
|
|
H_f = lambdify([roll, pitch, yaw, vx, vy, vz], H) |
|
|
|
|
|
|
|
return H_f |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Localizer(): |
|
|
|
class Localizer(): |
|
|
|
def __init__(self, disabled_logs=[], dog=None): |
|
|
|
def __init__(self, disabled_logs=[], dog=None): |
|
|
|
self.kf = LiveKalman() |
|
|
|
self.kf = LiveKalman() |
|
|
@ -35,9 +55,11 @@ class Localizer(): |
|
|
|
self.device_from_calib = np.eye(3) |
|
|
|
self.device_from_calib = np.eye(3) |
|
|
|
self.calib_from_device = np.eye(3) |
|
|
|
self.calib_from_device = np.eye(3) |
|
|
|
self.calibrated = 0 |
|
|
|
self.calibrated = 0 |
|
|
|
|
|
|
|
self.H = get_H() |
|
|
|
|
|
|
|
|
|
|
|
def liveLocationMsg(self, time): |
|
|
|
def liveLocationMsg(self, time): |
|
|
|
predicted_state = self.kf.x |
|
|
|
predicted_state = self.kf.x |
|
|
|
|
|
|
|
predicted_cov = self.kf.P |
|
|
|
predicted_std = np.sqrt(np.diagonal(self.kf.P)) |
|
|
|
predicted_std = np.sqrt(np.diagonal(self.kf.P)) |
|
|
|
|
|
|
|
|
|
|
|
fix_ecef = predicted_state[States.ECEF_POS] |
|
|
|
fix_ecef = predicted_state[States.ECEF_POS] |
|
|
@ -46,21 +68,36 @@ class Localizer(): |
|
|
|
vel_ecef_std = predicted_std[States.ECEF_VELOCITY_ERR] |
|
|
|
vel_ecef_std = predicted_std[States.ECEF_VELOCITY_ERR] |
|
|
|
fix_pos_geo = coord.ecef2geodetic(fix_ecef) |
|
|
|
fix_pos_geo = coord.ecef2geodetic(fix_ecef) |
|
|
|
fix_pos_geo_std = coord.ecef2geodetic(fix_ecef + fix_ecef_std) - fix_pos_geo |
|
|
|
fix_pos_geo_std = coord.ecef2geodetic(fix_ecef + fix_ecef_std) - fix_pos_geo |
|
|
|
ned_vel = self.converter.ecef2ned(fix_ecef + vel_ecef) - self.converter.ecef2ned(fix_ecef) |
|
|
|
|
|
|
|
ned_vel_std = self.converter.ecef2ned(fix_ecef + vel_ecef + vel_ecef_std) - self.converter.ecef2ned(fix_ecef + vel_ecef) |
|
|
|
|
|
|
|
device_from_ecef = rot_from_quat(predicted_state[States.ECEF_ORIENTATION]).T |
|
|
|
|
|
|
|
vel_device = device_from_ecef.dot(vel_ecef) |
|
|
|
|
|
|
|
vel_device_std = device_from_ecef.dot(vel_ecef_std) |
|
|
|
|
|
|
|
orientation_ecef = euler_from_quat(predicted_state[States.ECEF_ORIENTATION]) |
|
|
|
orientation_ecef = euler_from_quat(predicted_state[States.ECEF_ORIENTATION]) |
|
|
|
orientation_ecef_std = predicted_std[States.ECEF_ORIENTATION_ERR] |
|
|
|
orientation_ecef_std = predicted_std[States.ECEF_ORIENTATION_ERR] |
|
|
|
orientation_ned = ned_euler_from_ecef(fix_ecef, orientation_ecef) |
|
|
|
|
|
|
|
orientation_ned_std = ned_euler_from_ecef(fix_ecef, orientation_ecef + orientation_ecef_std) - orientation_ned |
|
|
|
|
|
|
|
vel_calib = self.calib_from_device.dot(vel_device) |
|
|
|
|
|
|
|
vel_calib_std = self.calib_from_device.dot(vel_device_std) |
|
|
|
|
|
|
|
acc_calib = self.calib_from_device.dot(predicted_state[States.ACCELERATION]) |
|
|
|
acc_calib = self.calib_from_device.dot(predicted_state[States.ACCELERATION]) |
|
|
|
acc_calib_std = self.calib_from_device.dot(predicted_std[States.ACCELERATION_ERR]) |
|
|
|
acc_calib_std = np.sqrt(np.diagonal(self.calib_from_device.dot( |
|
|
|
|
|
|
|
predicted_cov[States.ACCELERATION_ERR, States.ACCELERATION_ERR]).dot( |
|
|
|
|
|
|
|
self.calib_from_device.T))) |
|
|
|
ang_vel_calib = self.calib_from_device.dot(predicted_state[States.ANGULAR_VELOCITY]) |
|
|
|
ang_vel_calib = self.calib_from_device.dot(predicted_state[States.ANGULAR_VELOCITY]) |
|
|
|
ang_vel_calib_std = self.calib_from_device.dot(predicted_std[States.ANGULAR_VELOCITY_ERR]) |
|
|
|
ang_vel_calib_std = np.sqrt(np.diagonal(self.calib_from_device.dot( |
|
|
|
|
|
|
|
predicted_cov[States.ANGULAR_VELOCITY_ERR, States.ANGULAR_VELOCITY_ERR]).dot( |
|
|
|
|
|
|
|
self.calib_from_device.T))) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
device_from_ecef = rot_from_quat(predicted_state[States.ECEF_ORIENTATION]).T |
|
|
|
|
|
|
|
vel_device = device_from_ecef.dot(vel_ecef) |
|
|
|
|
|
|
|
device_from_ecef_eul = euler_from_quat(predicted_state[States.ECEF_ORIENTATION]).T |
|
|
|
|
|
|
|
idxs = list(range(States.ECEF_ORIENTATION_ERR.start, States.ECEF_ORIENTATION_ERR.stop)) + list(range(States.ECEF_VELOCITY_ERR.start, States.ECEF_VELOCITY_ERR.stop)) |
|
|
|
|
|
|
|
condensed_cov = predicted_cov[idxs][:,idxs] |
|
|
|
|
|
|
|
H = self.H(*list(np.concatenate([device_from_ecef_eul, vel_ecef]))) |
|
|
|
|
|
|
|
vel_device_cov = H.dot(condensed_cov).dot(H.T) |
|
|
|
|
|
|
|
vel_device_std = np.sqrt(np.diagonal(vel_device_cov)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vel_calib = self.calib_from_device.dot(vel_device) |
|
|
|
|
|
|
|
vel_calib_std = np.sqrt(np.diagonal(self.calib_from_device.dot( |
|
|
|
|
|
|
|
vel_device_cov).dot( |
|
|
|
|
|
|
|
self.calib_from_device.T))) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
orientation_ned = ned_euler_from_ecef(fix_ecef, orientation_ecef) |
|
|
|
|
|
|
|
#orientation_ned_std = ned_euler_from_ecef(fix_ecef, orientation_ecef + orientation_ecef_std) - orientation_ned |
|
|
|
|
|
|
|
ned_vel = self.converter.ecef2ned(fix_ecef + vel_ecef) - self.converter.ecef2ned(fix_ecef) |
|
|
|
|
|
|
|
#ned_vel_std = self.converter.ecef2ned(fix_ecef + vel_ecef + vel_ecef_std) - self.converter.ecef2ned(fix_ecef + vel_ecef) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fix = messaging.log.LiveLocationKalman.new_message() |
|
|
|
fix = messaging.log.LiveLocationKalman.new_message() |
|
|
@ -74,8 +111,8 @@ class Localizer(): |
|
|
|
fix.velocityECEF.std = to_float(vel_ecef_std) |
|
|
|
fix.velocityECEF.std = to_float(vel_ecef_std) |
|
|
|
fix.velocityECEF.valid = True |
|
|
|
fix.velocityECEF.valid = True |
|
|
|
fix.velocityNED.value = to_float(ned_vel) |
|
|
|
fix.velocityNED.value = to_float(ned_vel) |
|
|
|
fix.velocityNED.std = to_float(ned_vel_std) |
|
|
|
#fix.velocityNED.std = to_float(ned_vel_std) |
|
|
|
fix.velocityNED.valid = True |
|
|
|
#fix.velocityNED.valid = True |
|
|
|
fix.velocityDevice.value = to_float(vel_device) |
|
|
|
fix.velocityDevice.value = to_float(vel_device) |
|
|
|
fix.velocityDevice.std = to_float(vel_device_std) |
|
|
|
fix.velocityDevice.std = to_float(vel_device_std) |
|
|
|
fix.velocityDevice.valid = True |
|
|
|
fix.velocityDevice.valid = True |
|
|
@ -87,8 +124,8 @@ class Localizer(): |
|
|
|
fix.orientationECEF.std = to_float(orientation_ecef_std) |
|
|
|
fix.orientationECEF.std = to_float(orientation_ecef_std) |
|
|
|
fix.orientationECEF.valid = True |
|
|
|
fix.orientationECEF.valid = True |
|
|
|
fix.orientationNED.value = to_float(orientation_ned) |
|
|
|
fix.orientationNED.value = to_float(orientation_ned) |
|
|
|
fix.orientationNED.std = to_float(orientation_ned_std) |
|
|
|
#fix.orientationNED.std = to_float(orientation_ned_std) |
|
|
|
fix.orientationNED.valid = True |
|
|
|
#fix.orientationNED.valid = True |
|
|
|
fix.angularVelocityDevice.value = to_float(predicted_state[States.ANGULAR_VELOCITY]) |
|
|
|
fix.angularVelocityDevice.value = to_float(predicted_state[States.ANGULAR_VELOCITY]) |
|
|
|
fix.angularVelocityDevice.std = to_float(predicted_std[States.ANGULAR_VELOCITY_ERR]) |
|
|
|
fix.angularVelocityDevice.std = to_float(predicted_std[States.ANGULAR_VELOCITY_ERR]) |
|
|
|
fix.angularVelocityDevice.valid = True |
|
|
|
fix.angularVelocityDevice.valid = True |
|
|
|