2026-03-18 21:43:28 +00:00
|
|
|
#include "imu.h"
|
2026-04-17 00:24:52 +01:00
|
|
|
#include "Eigen/Geometry"
|
2026-04-07 10:48:44 +01:00
|
|
|
#include "Esp.h"
|
2026-04-17 00:24:52 +01:00
|
|
|
#include "drone_controller.h"
|
2026-03-18 21:43:28 +00:00
|
|
|
|
2026-03-30 22:09:23 +01:00
|
|
|
#ifdef PS
|
|
|
|
|
#undef PS
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef F
|
|
|
|
|
#undef F
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <Eigen/Dense>
|
2026-03-18 21:43:28 +00:00
|
|
|
|
2026-04-07 10:48:44 +01:00
|
|
|
#include "esp_log.h"
|
|
|
|
|
#include "esp_timer.h"
|
|
|
|
|
#include "hal/spi_types.h"
|
|
|
|
|
#include "sens_fus.h"
|
|
|
|
|
|
2026-04-06 03:39:08 +01:00
|
|
|
#include "freertos/idf_additions.h"
|
|
|
|
|
|
2026-03-30 22:09:23 +01:00
|
|
|
static const char *TAG = "IMU";
|
2026-03-18 21:43:28 +00:00
|
|
|
|
2026-04-18 01:29:08 +01:00
|
|
|
#define IMU_CS GPIO_NUM_3 // Green
|
|
|
|
|
#define IMU_MOSI GPIO_NUM_2 // DI - White
|
|
|
|
|
#define IMU_RST GPIO_NUM_1 // Red
|
2026-04-12 16:52:29 +01:00
|
|
|
|
2026-04-18 01:29:08 +01:00
|
|
|
#define IMU_INT GPIO_NUM_4 // Yellow
|
|
|
|
|
#define IMU_MISO GPIO_NUM_5 // SDA - White
|
|
|
|
|
#define IMU_SCLK GPIO_NUM_6 // SCL - Green
|
2026-04-12 16:52:29 +01:00
|
|
|
|
2026-04-17 00:24:52 +01:00
|
|
|
BNO08x *setup_imu() {
|
2026-04-03 19:13:39 +01:00
|
|
|
imu_state *local_state = new imu_state;
|
2026-04-06 03:39:08 +01:00
|
|
|
imu_state_mutex = xSemaphoreCreateMutex();
|
2026-04-03 19:13:39 +01:00
|
|
|
|
2026-04-12 16:52:29 +01:00
|
|
|
BNO08x *imu =
|
|
|
|
|
new BNO08x(bno08x_config_t(SPI2_HOST, IMU_MOSI, IMU_MISO, IMU_SCLK,
|
|
|
|
|
IMU_CS, IMU_INT, IMU_RST, 2000000, false));
|
2026-03-18 21:43:28 +00:00
|
|
|
|
2026-04-14 16:00:52 +01:00
|
|
|
ESP_LOGI(TAG, "INITIALIZING IMU");
|
2026-03-18 21:43:28 +00:00
|
|
|
if (!imu->initialize()) {
|
|
|
|
|
ESP_LOGE(TAG, "BNO08x Init failure.");
|
2026-04-07 10:48:44 +01:00
|
|
|
ESP.restart();
|
2026-03-18 21:43:28 +00:00
|
|
|
}
|
2026-04-14 16:00:52 +01:00
|
|
|
imu->print_product_ids();
|
2026-03-18 21:43:28 +00:00
|
|
|
|
|
|
|
|
imu->dynamic_calibration_autosave_enable();
|
|
|
|
|
imu->dynamic_calibration_enable(BNO08xCalSel::all);
|
|
|
|
|
|
2026-04-17 00:24:52 +01:00
|
|
|
// imu->rpt.rv_game.enable(2500UL);
|
|
|
|
|
imu->rpt.rv.enable(2500UL);
|
|
|
|
|
// imu->rpt.cal_magnetometer.enable(10000UL);
|
2026-03-18 21:43:28 +00:00
|
|
|
imu->rpt.linear_accelerometer.enable(2500UL);
|
2026-04-17 00:24:52 +01:00
|
|
|
// imu->rpt.accelerometer.enable(10000UL);
|
2026-04-06 03:39:08 +01:00
|
|
|
imu->rpt.cal_gyro.enable(2500UL);
|
2026-04-03 19:13:39 +01:00
|
|
|
|
|
|
|
|
imu->register_cb([imu, local_state]() {
|
2026-04-17 00:24:52 +01:00
|
|
|
// ESP_LOGI("IMU", "CALLBACK");
|
2026-04-03 19:13:39 +01:00
|
|
|
bool needs_updating = false;
|
2026-04-06 03:39:08 +01:00
|
|
|
if (sens_fus_mutex == NULL || imu_state_mutex == NULL)
|
|
|
|
|
return;
|
2026-03-18 21:43:28 +00:00
|
|
|
|
2026-04-17 00:24:52 +01:00
|
|
|
if (imu->rpt.rv.has_new_data()) {
|
2026-04-03 19:13:39 +01:00
|
|
|
|
|
|
|
|
needs_updating = true;
|
|
|
|
|
|
2026-04-17 00:24:52 +01:00
|
|
|
auto sens_rot = imu->rpt.rv.get_quat();
|
|
|
|
|
auto sens_euler = imu->rpt.rv.get_euler();
|
|
|
|
|
local_state->rot =
|
|
|
|
|
Eigen::Quaternionf(sens_rot.real, sens_rot.i, sens_rot.j, sens_rot.k);
|
|
|
|
|
|
|
|
|
|
// Eigen::Quaternionf q_global_yaw(
|
|
|
|
|
// Eigen::AngleAxisf(-M_PI / 2.0, Eigen::Vector3f::UnitZ()));
|
|
|
|
|
// local_state->rot = q_global_yaw * local_state->rot;
|
|
|
|
|
|
|
|
|
|
local_state->rot.normalize();
|
|
|
|
|
|
|
|
|
|
// {.i = sens_rot.i, .j = sens_rot.j, .k = sens_rot.k, .w =
|
|
|
|
|
// sens_rot.real}; local_state->rot_euler = {sens_euler.x, sens_euler.y,
|
|
|
|
|
// sens_euler.z}; ESP_LOGI("IMU", "rot: roll %f, pitch %f, yaw %f",
|
|
|
|
|
// local_state->rot_euler.x(), local_state->rot_euler.y(),
|
|
|
|
|
// local_state->rot_euler.z());
|
2026-04-03 19:13:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (imu->rpt.cal_gyro.has_new_data()) {
|
|
|
|
|
|
|
|
|
|
needs_updating = true;
|
|
|
|
|
|
|
|
|
|
auto cal_gyro = imu->rpt.cal_gyro.get();
|
2026-04-17 00:24:52 +01:00
|
|
|
local_state->angvel = {cal_gyro.x, cal_gyro.y, cal_gyro.z};
|
2026-04-19 18:46:42 +01:00
|
|
|
// ESP_LOGI("ROT", "angvel_z: %f", cal_gyro.z);
|
2026-03-18 21:43:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (imu->rpt.linear_accelerometer.has_new_data()) {
|
|
|
|
|
|
2026-04-03 19:13:39 +01:00
|
|
|
needs_updating = true;
|
2026-03-18 21:43:28 +00:00
|
|
|
|
2026-04-17 00:24:52 +01:00
|
|
|
auto sens_accel_lin = imu->rpt.linear_accelerometer.get();
|
|
|
|
|
local_state->lin_accel = {sens_accel_lin.x, sens_accel_lin.y,
|
|
|
|
|
sens_accel_lin.z};
|
|
|
|
|
|
|
|
|
|
// ESP_LOGI("IMU-ac", "lin_accel %f,%f,%f", sens_accel_lin.x,
|
|
|
|
|
// sens_accel_lin.y, sens_accel_lin.z);
|
|
|
|
|
|
2026-03-30 22:09:23 +01:00
|
|
|
int64_t current_time = esp_timer_get_time();
|
2026-03-18 21:43:28 +00:00
|
|
|
|
2026-04-03 19:13:39 +01:00
|
|
|
if (local_state->last_time != -1) {
|
|
|
|
|
|
|
|
|
|
float dt =
|
|
|
|
|
((float)(current_time - local_state->last_time)) / 1000000.0f;
|
2026-04-17 00:24:52 +01:00
|
|
|
|
|
|
|
|
dcont::QuatC quatc{.i = local_state->rot.x(),
|
|
|
|
|
.j = local_state->rot.y(),
|
|
|
|
|
.k = local_state->rot.z(),
|
|
|
|
|
.w = local_state->rot.w()};
|
|
|
|
|
|
2026-04-04 02:39:41 +01:00
|
|
|
dcont::Vec3C accel_global =
|
2026-04-17 00:24:52 +01:00
|
|
|
dcont::apply_rot(&local_state->lin_accel, &quatc);
|
|
|
|
|
|
|
|
|
|
local_state->lin_accel_global = accel_global;
|
2026-03-18 21:43:28 +00:00
|
|
|
|
2026-04-07 10:48:44 +01:00
|
|
|
if (xSemaphoreTake(sens_fus_mutex, (TickType_t)2) == pdTRUE) {
|
2026-04-06 03:39:08 +01:00
|
|
|
|
2026-04-07 10:48:44 +01:00
|
|
|
// ESP_LOGE(TAG, "accel: (%f, %f, %f), dt: %f", accel_global.x,
|
|
|
|
|
// accel_global.y, accel_global.z, dt);
|
2026-04-06 03:39:08 +01:00
|
|
|
|
2026-04-03 17:52:02 +01:00
|
|
|
sens_fus.predict(dt, Eigen::Vector3f(accel_global.x, accel_global.y,
|
|
|
|
|
accel_global.z));
|
2026-04-06 03:39:08 +01:00
|
|
|
|
2026-04-07 10:48:44 +01:00
|
|
|
// ESP_LOGE(TAG, "vel: (%f, %f, %f)", sens_fus.velocity.x(),
|
|
|
|
|
// sens_fus.velocity.z(), sens_fus.velocity.y());
|
2026-04-03 17:52:02 +01:00
|
|
|
xSemaphoreGive(sens_fus_mutex);
|
2026-03-30 22:09:23 +01:00
|
|
|
} else {
|
2026-04-03 19:13:39 +01:00
|
|
|
ESP_LOGE(TAG, "Failed to get sens_fus mutex.");
|
2026-03-18 21:43:28 +00:00
|
|
|
}
|
|
|
|
|
}
|
2026-04-03 19:13:39 +01:00
|
|
|
local_state->last_time = current_time;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (needs_updating) {
|
2026-04-06 03:39:08 +01:00
|
|
|
if (xSemaphoreTake(imu_state_mutex, 0)) {
|
2026-04-03 19:13:39 +01:00
|
|
|
imu_state_var = *local_state;
|
|
|
|
|
xSemaphoreGive(imu_state_mutex);
|
|
|
|
|
}
|
2026-03-18 21:43:28 +00:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
ESP_LOGI(TAG, "IMU Setup Success.");
|
2026-04-17 00:24:52 +01:00
|
|
|
return imu;
|
2026-03-18 21:43:28 +00:00
|
|
|
}
|