2026-04-03 17:52:02 +01:00
|
|
|
#pragma once
|
2026-04-14 16:00:52 +01:00
|
|
|
#include "Eigen/Core"
|
2026-04-03 17:52:02 +01:00
|
|
|
#include <cmath>
|
2026-04-14 16:14:04 +01:00
|
|
|
#include <cstdlib>
|
2026-04-03 17:52:02 +01:00
|
|
|
|
|
|
|
|
#ifdef PS
|
|
|
|
|
#undef PS
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef F
|
|
|
|
|
#undef F
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <Eigen/Dense>
|
|
|
|
|
|
2026-04-06 03:39:08 +01:00
|
|
|
#include "freertos/idf_additions.h"
|
|
|
|
|
|
2026-04-03 17:52:02 +01:00
|
|
|
inline float getYawDifference(const Eigen::Vector3f &v_gps,
|
|
|
|
|
const Eigen::Vector3f &v_imu) {
|
|
|
|
|
float yaw_gps = std::atan2(v_gps.y(), v_gps.x());
|
|
|
|
|
float yaw_imu = std::atan2(v_imu.y(), v_imu.x());
|
|
|
|
|
|
|
|
|
|
float delta_yaw = yaw_gps - yaw_imu;
|
|
|
|
|
return std::atan2(std::sin(delta_yaw), std::cos(delta_yaw));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct sens_fus_compl {
|
|
|
|
|
Eigen::Vector3f position = Eigen::Vector3f::Zero();
|
|
|
|
|
Eigen::Vector3f velocity = Eigen::Vector3f::Zero();
|
2026-04-03 18:20:55 +01:00
|
|
|
Eigen::Vector3f last_accel_world = Eigen::Vector3f::Zero();
|
2026-04-18 01:29:08 +01:00
|
|
|
|
|
|
|
|
Eigen::Vector3f velocity_error = Eigen::Vector3f::Zero();
|
|
|
|
|
Eigen::Vector3f position_error = Eigen::Vector3f::Zero();
|
|
|
|
|
|
|
|
|
|
void gps_lost() {
|
|
|
|
|
this->position_error = Eigen::Vector3f::Zero();
|
|
|
|
|
this->velocity_error = Eigen::Vector3f::Zero();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Eigen::Vector3f velocity_error_mult = {40.0f, 40.0f, 0.0f};
|
|
|
|
|
Eigen::Vector3f position_error_mult = {40.0f, 40.0f, 0.0f};
|
2026-04-03 17:52:02 +01:00
|
|
|
|
2026-04-03 18:20:55 +01:00
|
|
|
/*
|
|
|
|
|
* Tau is the time that the filter takes to reach 1-e^(-1) of the difference
|
|
|
|
|
* to a constant target
|
|
|
|
|
* so at t=tau, were 63% of the way there
|
|
|
|
|
* at t=3*tau, were 95% of the way there
|
|
|
|
|
*/
|
2026-04-18 01:29:08 +01:00
|
|
|
Eigen::Vector3f tau_gps_pos = {4.0f, 4.0f, INFINITY};
|
|
|
|
|
Eigen::Vector3f tau_gps_vel = {4.0f, 4.0f, INFINITY};
|
2026-04-03 17:52:02 +01:00
|
|
|
|
2026-04-18 01:29:08 +01:00
|
|
|
Eigen::Vector3f tau_baro_pos = {INFINITY, INFINITY, 4.0f};
|
|
|
|
|
Eigen::Vector3f tau_baro_vel = {INFINITY, INFINITY, 4.0f};
|
2026-04-03 17:52:02 +01:00
|
|
|
|
2026-04-07 10:48:44 +01:00
|
|
|
Eigen::Matrix3f yaw_rotation_matrix = Eigen::Matrix3f::Identity().eval();
|
2026-04-03 19:13:39 +01:00
|
|
|
|
2026-04-03 17:52:02 +01:00
|
|
|
void predict(float dt, Eigen::Vector3f accel) {
|
2026-04-18 01:29:08 +01:00
|
|
|
Eigen::Vector3f accel_err_rmvd =
|
|
|
|
|
accel.array() -
|
|
|
|
|
this->velocity_error.array() * this->velocity_error_mult.array();
|
2026-04-03 17:52:02 +01:00
|
|
|
|
2026-04-03 18:20:55 +01:00
|
|
|
Eigen::Vector3f next_velocity =
|
2026-04-18 01:29:08 +01:00
|
|
|
this->velocity + (this->last_accel_world + accel_err_rmvd) * 0.5f * dt;
|
2026-04-03 17:52:02 +01:00
|
|
|
|
2026-04-18 01:29:08 +01:00
|
|
|
this->position =
|
|
|
|
|
this->position.array() +
|
|
|
|
|
(((this->velocity + next_velocity) * 0.5f).array() -
|
|
|
|
|
this->position_error.array() * this->position_error_mult.array()) *
|
|
|
|
|
dt;
|
2026-04-03 18:20:55 +01:00
|
|
|
|
2026-04-03 17:52:02 +01:00
|
|
|
this->velocity = next_velocity;
|
2026-04-18 01:29:08 +01:00
|
|
|
this->last_accel_world = accel_err_rmvd;
|
2026-04-03 17:52:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void measure_gps(float dt, Eigen::Vector3f gps_pos, Eigen::Vector3f gps_vel) {
|
2026-04-03 18:20:55 +01:00
|
|
|
// alpha = dt / (tau + dt)
|
2026-04-03 17:52:02 +01:00
|
|
|
Eigen::Vector3f alpha_pos = dt / (tau_gps_pos.array() + dt);
|
|
|
|
|
Eigen::Vector3f alpha_vel = dt / (tau_gps_vel.array() + dt);
|
|
|
|
|
|
2026-04-18 01:29:08 +01:00
|
|
|
this->velocity_error = this->velocity - gps_vel;
|
|
|
|
|
this->position_error = this->position - gps_pos;
|
|
|
|
|
|
|
|
|
|
// next_state = (1 - alpha) * state + alpha * measurement
|
2026-04-03 17:52:02 +01:00
|
|
|
this->position =
|
|
|
|
|
(Eigen::Vector3f::Ones() - alpha_pos).array() * this->position.array() +
|
|
|
|
|
alpha_pos.array() * gps_pos.array();
|
|
|
|
|
|
2026-04-18 01:29:08 +01:00
|
|
|
this->velocity =
|
|
|
|
|
(Eigen::Vector3f::Ones() - alpha_vel).array() * this->velocity.array() +
|
|
|
|
|
alpha_vel.array() * gps_vel.array();
|
2026-04-03 17:52:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void measure_baro(float dt, Eigen::Vector3f baro_pos,
|
|
|
|
|
Eigen::Vector3f baro_vel) {
|
|
|
|
|
// Formula: alpha = dt / (tau + dt)
|
|
|
|
|
Eigen::Vector3f alpha_pos = dt / (tau_baro_pos.array() + dt);
|
|
|
|
|
Eigen::Vector3f alpha_vel = dt / (tau_baro_vel.array() + dt);
|
|
|
|
|
|
|
|
|
|
this->position =
|
|
|
|
|
(Eigen::Vector3f::Ones() - alpha_pos).array() * this->position.array() +
|
|
|
|
|
alpha_pos.array() * baro_pos.array();
|
|
|
|
|
|
|
|
|
|
this->velocity =
|
|
|
|
|
(Eigen::Vector3f::Ones() - alpha_vel).array() * this->velocity.array() +
|
|
|
|
|
alpha_vel.array() * baro_vel.array();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
inline SemaphoreHandle_t sens_fus_mutex = NULL;
|
|
|
|
|
inline sens_fus_compl sens_fus;
|