|
|
|
@ -49,8 +49,8 @@ class Localizer(): |
|
|
|
|
fix.accel = [float(predicted_state[19]), float(predicted_state[20]), float(predicted_state[21])] |
|
|
|
|
|
|
|
|
|
local_vel = rotations_from_quats(predicted_state[States.ECEF_ORIENTATION]).T.dot(predicted_state[States.ECEF_VELOCITY]) |
|
|
|
|
fix.pitchCalibration = math.degrees(math.arctan2(local_vel[2], local_vel[0])) |
|
|
|
|
fix.yawCalibration = math.degrees(math.arctan2(local_vel[1], local_vel[0])) |
|
|
|
|
fix.pitchCalibration = math.degrees(math.atan2(local_vel[2], local_vel[0])) |
|
|
|
|
fix.yawCalibration = math.degrees(math.atan2(local_vel[1], local_vel[0])) |
|
|
|
|
|
|
|
|
|
#fix.imuFrame = [(180/np.pi)*float(predicted_state[23]), (180/np.pi)*float(predicted_state[24]), (180/np.pi)*float(predicted_state[25])] |
|
|
|
|
return fix |
|
|
|
@ -58,7 +58,7 @@ class Localizer(): |
|
|
|
|
def update_kalman(self, time, kind, meas): |
|
|
|
|
idx = bisect_right([x[0] for x in self.observation_buffer], time) |
|
|
|
|
self.observation_buffer.insert(idx, (time, kind, meas)) |
|
|
|
|
while self.observation_buffer[-1][0] - self.observation_buffer[0][0] > self.max_age: |
|
|
|
|
while len(self.observation_buffer) > 0 and self.observation_buffer[-1][0] - self.observation_buffer[0][0] > self.max_age: |
|
|
|
|
if self.filter_ready: |
|
|
|
|
try: |
|
|
|
|
self.kf.predict_and_observe(*self.observation_buffer.pop(0)) |
|
|
|
@ -68,18 +68,18 @@ class Localizer(): |
|
|
|
|
else: |
|
|
|
|
self.observation_buffer.pop(0) |
|
|
|
|
|
|
|
|
|
def handle_gps(self, log, current_time): |
|
|
|
|
converter = coord.LocalCoord.from_geodetic([log.gpsLocationExternal.latitude, log.gpsLocationExternal.longitude, log.gpsLocationExternal.altitude]) |
|
|
|
|
def handle_gps(self, current_time, log): |
|
|
|
|
converter = coord.LocalCoord.from_geodetic([log.latitude, log.longitude, log.altitude]) |
|
|
|
|
fix_ecef = converter.ned2ecef([0, 0, 0]) |
|
|
|
|
|
|
|
|
|
# TODO initing with bad bearing not allowed, maybe not bad? |
|
|
|
|
if not self.filter_ready and log.gpsLocationExternal.speed > 5: |
|
|
|
|
if not self.filter_ready and log.speed > 5: |
|
|
|
|
self.filter_ready = True |
|
|
|
|
initial_ecef = fix_ecef |
|
|
|
|
gps_bearing = math.radians(log.gpsLocationExternal.bearing) |
|
|
|
|
gps_bearing = math.radians(log.bearing) |
|
|
|
|
initial_pose_ecef = ecef_euler_from_ned(initial_ecef, [0, 0, gps_bearing]) |
|
|
|
|
initial_pose_ecef_quat = euler2quat(initial_pose_ecef) |
|
|
|
|
gps_speed = log.gpsLocationExternal.speed |
|
|
|
|
gps_speed = log.speed |
|
|
|
|
quat_uncertainty = 0.2**2 |
|
|
|
|
initial_pose_ecef_quat = euler2quat(initial_pose_ecef) |
|
|
|
|
|
|
|
|
@ -105,25 +105,25 @@ class Localizer(): |
|
|
|
|
cloudlog.error("Locationd vs ubloxLocation difference too large, kalman reset") |
|
|
|
|
self.reset_kalman() |
|
|
|
|
|
|
|
|
|
def handle_car_state(self, log, current_time): |
|
|
|
|
def handle_car_state(self, current_time, log): |
|
|
|
|
self.speed_counter += 1 |
|
|
|
|
|
|
|
|
|
if self.speed_counter % SENSOR_DECIMATION == 0: |
|
|
|
|
self.update_kalman(current_time, ObservationKind.ODOMETRIC_SPEED, log.carState.vEgo) |
|
|
|
|
self.update_kalman(current_time, ObservationKind.ODOMETRIC_SPEED, log.vEgo) |
|
|
|
|
if log.carState.vEgo == 0: |
|
|
|
|
self.update_kalman(current_time, ObservationKind.NO_ROT, [0, 0, 0]) |
|
|
|
|
|
|
|
|
|
def handle_cam_odo(self, log, current_time): |
|
|
|
|
def handle_cam_odo(self, current_time, log): |
|
|
|
|
self.update_kalman(current_time, |
|
|
|
|
ObservationKind.CAMERA_ODO_ROTATION, |
|
|
|
|
np.concatenate([log.cameraOdometry.rot, log.cameraOdometry.rotStd])) |
|
|
|
|
np.concatenate([log.rot, log.rotStd])) |
|
|
|
|
self.update_kalman(current_time, |
|
|
|
|
ObservationKind.CAMERA_ODO_TRANSLATION, |
|
|
|
|
np.concatenate([log.cameraOdometry.trans, log.cameraOdometry.transStd])) |
|
|
|
|
np.concatenate([log.trans, log.transStd])) |
|
|
|
|
|
|
|
|
|
def handle_sensors(self, log, current_time): |
|
|
|
|
def handle_sensors(self, current_time, log): |
|
|
|
|
# TODO does not yet account for double sensor readings in the log |
|
|
|
|
for sensor_reading in log.sensorEvents: |
|
|
|
|
for sensor_reading in log: |
|
|
|
|
# Gyro Uncalibrated |
|
|
|
|
if sensor_reading.sensor == 5 and sensor_reading.type == 16: |
|
|
|
|
self.gyro_counter += 1 |
|
|
|
@ -142,23 +142,6 @@ class Localizer(): |
|
|
|
|
v = sensor_reading.acceleration.v |
|
|
|
|
self.update_kalman(current_time, ObservationKind.PHONE_ACCEL, [-v[2], -v[1], -v[0]]) |
|
|
|
|
|
|
|
|
|
def handle_log(self, log): |
|
|
|
|
current_time = 1e-9 * log.logMonoTime |
|
|
|
|
|
|
|
|
|
typ = log.which |
|
|
|
|
|
|
|
|
|
if typ in self.disabled_logs: |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
if typ == "sensorEvents": |
|
|
|
|
self.handle_sensors(log, current_time) |
|
|
|
|
elif typ == "gpsLocationExternal": |
|
|
|
|
self.handle_gps(log, current_time) |
|
|
|
|
elif typ == "carState": |
|
|
|
|
self.handle_car_state(log, current_time) |
|
|
|
|
elif typ == "cameraOdometry": |
|
|
|
|
self.handle_cam_odo(log, current_time) |
|
|
|
|
|
|
|
|
|
def reset_kalman(self): |
|
|
|
|
self.filter_time = None |
|
|
|
|
self.filter_ready = False |
|
|
|
@ -171,7 +154,7 @@ class Localizer(): |
|
|
|
|
|
|
|
|
|
def locationd_thread(sm, pm, disabled_logs=[]): |
|
|
|
|
if sm is None: |
|
|
|
|
sm = messaging.SubMaster(['carState', 'gpsLocationExternal', 'sensorEvents', 'cameraOdometry']) |
|
|
|
|
sm = messaging.SubMaster(['gpsLocationExternal', 'sensorEvents', 'cameraOdometry']) |
|
|
|
|
if pm is None: |
|
|
|
|
pm = messaging.PubMaster(['liveLocation']) |
|
|
|
|
|
|
|
|
@ -182,7 +165,15 @@ def locationd_thread(sm, pm, disabled_logs=[]): |
|
|
|
|
|
|
|
|
|
for sock, updated in sm.updated.items(): |
|
|
|
|
if updated: |
|
|
|
|
localizer.handle_log(sm[sock]) |
|
|
|
|
t = sm.logMonoTime[sock] * 1e-9 |
|
|
|
|
if sock == "sensorEvents": |
|
|
|
|
localizer.handle_sensors(t, sm[sock]) |
|
|
|
|
elif sock == "gpsLocationExternal": |
|
|
|
|
localizer.handle_gps(t, sm[sock]) |
|
|
|
|
elif sock == "carState": |
|
|
|
|
localizer.handle_car_state(t, sm[sock]) |
|
|
|
|
elif sock == "cameraOdometry": |
|
|
|
|
localizer.handle_cam_odo(t, sm[sock]) |
|
|
|
|
|
|
|
|
|
if localizer.filter_ready and sm.updated['gpsLocationExternal']: |
|
|
|
|
t = sm.logMonoTime['gpsLocationExternal'] |
|
|
|
|