2026-04-18 17:16:06 +01:00
|
|
|
#include "Eigen/Core"
|
2026-03-30 22:09:23 +01:00
|
|
|
#include "driver/gpio.h"
|
2026-04-18 17:16:06 +01:00
|
|
|
#include "drone.h"
|
|
|
|
|
#include "drone_comms.h"
|
2026-04-17 00:24:52 +01:00
|
|
|
#include "drone_controller.h"
|
2026-04-20 02:52:05 +01:00
|
|
|
#include "esp32-hal.h"
|
|
|
|
|
#include "esp_log.h"
|
2026-03-30 22:09:23 +01:00
|
|
|
#include "freertos/FreeRTOS.h"
|
2026-03-26 23:01:20 +00:00
|
|
|
#include "freertos/idf_additions.h"
|
|
|
|
|
#include "freertos/projdefs.h"
|
2026-04-14 16:14:04 +01:00
|
|
|
#include "freertos/task.h"
|
2026-04-17 00:24:52 +01:00
|
|
|
#include <atomic>
|
2026-04-20 02:52:05 +01:00
|
|
|
#include <cmath>
|
|
|
|
|
#include <cstdint>
|
2026-04-04 02:39:41 +01:00
|
|
|
#include <optional>
|
2026-03-30 22:09:23 +01:00
|
|
|
|
|
|
|
|
#include "env_sens.h"
|
2026-03-26 23:01:20 +00:00
|
|
|
#include "gps.h"
|
2026-04-03 17:52:02 +01:00
|
|
|
#include "imu.h"
|
2026-04-20 12:54:01 +01:00
|
|
|
#include "logger.h"
|
2026-03-30 22:09:23 +01:00
|
|
|
#include "nav.h"
|
2026-04-03 17:52:02 +01:00
|
|
|
#include "packet_handler.h"
|
2026-04-20 12:54:01 +01:00
|
|
|
#include "portmacro.h"
|
2026-03-30 22:09:23 +01:00
|
|
|
#include "radio.h"
|
2026-04-03 17:52:02 +01:00
|
|
|
#include "sens_fus.h"
|
2026-04-02 18:57:52 +01:00
|
|
|
|
2026-03-30 22:09:23 +01:00
|
|
|
static const char *TAG = "MAIN";
|
2026-04-24 01:41:23 +01:00
|
|
|
#define TIME_RELEASE_QUEUE_TO_ACTIVATION 1000
|
|
|
|
|
|
|
|
|
|
bool first_wayp_was_set = false;
|
2026-04-17 00:24:52 +01:00
|
|
|
|
2026-03-30 22:09:23 +01:00
|
|
|
extern "C" void app_main(void) {
|
2026-03-18 15:49:09 +00:00
|
|
|
|
2026-04-03 17:52:02 +01:00
|
|
|
sens_fus_mutex = xSemaphoreCreateMutex();
|
2026-03-30 22:09:23 +01:00
|
|
|
nav_mutex = xSemaphoreCreateMutex();
|
2026-04-03 17:52:02 +01:00
|
|
|
|
2026-03-30 22:09:23 +01:00
|
|
|
initArduino();
|
|
|
|
|
gpio_install_isr_service(0);
|
|
|
|
|
Serial.begin(115200);
|
2026-03-26 23:01:20 +00:00
|
|
|
|
2026-04-20 12:54:01 +01:00
|
|
|
xTaskCreatePinnedToCore(logger_task, // Function name
|
|
|
|
|
"logger_task", // Name for debugging
|
2026-04-20 20:31:10 +01:00
|
|
|
2048 * 8, // Stack size in bytes
|
2026-04-20 12:54:01 +01:00
|
|
|
NULL, // Parameters
|
|
|
|
|
2, // Priority (higher = more urgent)
|
|
|
|
|
NULL, // Task handle
|
|
|
|
|
0 // Core ID
|
|
|
|
|
);
|
|
|
|
|
|
2026-04-18 17:16:06 +01:00
|
|
|
xTaskCreatePinnedToCore(radio_task, // Function name
|
|
|
|
|
"radio_rxtx", // Name for debugging
|
|
|
|
|
4096, // Stack size in bytes
|
|
|
|
|
NULL, // Parameters
|
|
|
|
|
5, // Priority (higher = more urgent)
|
|
|
|
|
NULL, // Task handle
|
|
|
|
|
0 // Core ID
|
|
|
|
|
);
|
|
|
|
|
|
2026-04-18 13:24:36 +01:00
|
|
|
xTaskCreatePinnedToCore(env_sens::baro_poll_task, "baro_poll", 8192, NULL, 5,
|
|
|
|
|
NULL, 0);
|
2026-04-17 00:24:52 +01:00
|
|
|
|
|
|
|
|
xTaskCreatePinnedToCore(gps_poll_task, "gps_poll", 8192, NULL, 5, NULL, 0);
|
2026-04-13 14:36:24 +01:00
|
|
|
|
2026-04-19 18:46:42 +01:00
|
|
|
xTaskCreate(
|
|
|
|
|
[](void *pvParameters) {
|
|
|
|
|
while (true) {
|
2026-04-20 12:54:01 +01:00
|
|
|
while (
|
|
|
|
|
packet_rx_queue &&
|
|
|
|
|
xQueueReceive(packet_rx_queue, &packet_data[0], portMAX_DELAY)) {
|
2026-04-19 18:46:42 +01:00
|
|
|
handle_packet(&packet_data[0]);
|
|
|
|
|
}
|
2026-04-20 12:54:01 +01:00
|
|
|
vTaskDelay(1);
|
2026-04-19 18:46:42 +01:00
|
|
|
}
|
|
|
|
|
},
|
2026-04-20 12:54:01 +01:00
|
|
|
"task_recv_task", 8192, NULL, 5, NULL);
|
2026-04-19 18:46:42 +01:00
|
|
|
|
2026-04-17 00:24:52 +01:00
|
|
|
setup_imu();
|
2026-04-20 02:52:05 +01:00
|
|
|
|
|
|
|
|
xTaskCreatePinnedToCore(drone_controller_task, // Function name
|
|
|
|
|
"drone_controller_task", // Name for debugging
|
|
|
|
|
1024 * 32, // Stack size in bytes
|
|
|
|
|
NULL, // Parameters
|
|
|
|
|
20, // Priority (higher = more urgent)
|
|
|
|
|
NULL, // Task handle
|
|
|
|
|
0 // Core ID
|
|
|
|
|
);
|
2026-04-24 01:41:23 +01:00
|
|
|
|
2026-04-14 16:00:52 +01:00
|
|
|
ESP_LOGI("MAIN", "All tasks spawned. Main loop free.");
|
2026-04-06 03:39:08 +01:00
|
|
|
|
2026-03-30 22:09:23 +01:00
|
|
|
Eigen::Vector3f local_pos = {0, 0, 0};
|
|
|
|
|
Eigen::Vector3f local_vel = {0, 0, 0};
|
2026-04-20 20:31:10 +01:00
|
|
|
bool sens_fus_data_ready = false;
|
2026-04-06 00:27:32 +01:00
|
|
|
|
|
|
|
|
uint64_t last_print_time = 0;
|
2026-04-17 00:24:52 +01:00
|
|
|
uint64_t last_position_broadcast_time = 0;
|
|
|
|
|
uint64_t last_status_broadcast_time = 0;
|
|
|
|
|
uint64_t time_activation_queue = 0;
|
|
|
|
|
bool released = false;
|
2026-04-20 20:31:10 +01:00
|
|
|
bool active = false;
|
|
|
|
|
|
2026-03-26 23:01:20 +00:00
|
|
|
while (true) {
|
2026-03-30 22:09:23 +01:00
|
|
|
|
2026-04-24 01:41:23 +01:00
|
|
|
if (millis() > last_position_broadcast_time + 100 && packet_tx_queue) {
|
2026-04-14 16:00:52 +01:00
|
|
|
send_packet_getter(PACKET_TYPE::INFO_DRONE_POSITION);
|
2026-04-17 00:24:52 +01:00
|
|
|
last_position_broadcast_time = millis();
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-24 01:41:23 +01:00
|
|
|
if (millis() > last_status_broadcast_time + 5000 && packet_tx_queue) {
|
2026-04-17 00:24:52 +01:00
|
|
|
send_packet_getter(PACKET_TYPE::INFO_DRONE_STATUS);
|
2026-04-24 01:41:23 +01:00
|
|
|
for (uint8_t i = 0; i < 8; i++) {
|
|
|
|
|
send_packet_getter(
|
|
|
|
|
(PACKET_TYPE)(PACKET_TYPE::DRONE_NAV_WAYPOINT_0 + i));
|
|
|
|
|
}
|
2026-04-17 00:24:52 +01:00
|
|
|
last_status_broadcast_time = millis();
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-18 17:16:06 +01:00
|
|
|
if (nav_mutex && xSemaphoreTake(nav_mutex, 10)) {
|
|
|
|
|
|
2026-04-24 01:41:23 +01:00
|
|
|
if (gps_mutex && xSemaphoreTake(gps_mutex, 10)) {
|
2026-04-18 17:16:06 +01:00
|
|
|
|
2026-04-24 01:41:23 +01:00
|
|
|
if (gps && gps->gps_avaliable()) {
|
|
|
|
|
waypoint current_wayp = nav_man.get_current_waypoint();
|
|
|
|
|
auto pos = sens_fus.position;
|
|
|
|
|
|
|
|
|
|
if ((current_wayp.coords_in_axis.value_or(
|
|
|
|
|
Eigen::Vector3f(INFINITY, INFINITY, INFINITY)) -
|
|
|
|
|
pos)
|
|
|
|
|
.norm() < 2.0) {
|
|
|
|
|
nav_man.waypoint_reached();
|
|
|
|
|
}
|
2026-04-18 17:16:06 +01:00
|
|
|
}
|
2026-04-24 01:41:23 +01:00
|
|
|
xSemaphoreGive(gps_mutex);
|
2026-04-18 17:16:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
xSemaphoreGive(nav_mutex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Release
|
2026-04-24 01:41:23 +01:00
|
|
|
if (xSemaphoreTake(imu_state_mutex, 1)) {
|
|
|
|
|
|
|
|
|
|
if (imu_state_var.lin_accel_global.z < -7.0 && !released) {
|
|
|
|
|
released = true;
|
|
|
|
|
time_activation_queue = millis();
|
|
|
|
|
}
|
|
|
|
|
xSemaphoreGive(imu_state_mutex);
|
2026-04-14 16:00:52 +01:00
|
|
|
}
|
|
|
|
|
|
2026-04-19 15:50:02 +01:00
|
|
|
if (released && drone_cont &&
|
2026-04-17 00:24:52 +01:00
|
|
|
std::atomic_load(&drone_cont->current_input_mode) ==
|
|
|
|
|
INPUT_TYPE::AUTO_NAV &&
|
2026-04-20 20:31:10 +01:00
|
|
|
millis() - time_activation_queue > TIME_RELEASE_QUEUE_TO_ACTIVATION &&
|
|
|
|
|
!active) {
|
2026-04-17 00:24:52 +01:00
|
|
|
|
|
|
|
|
dcont::reset_pid_states(drone_cont->drone_controller);
|
2026-04-24 01:41:23 +01:00
|
|
|
|
|
|
|
|
if (xSemaphoreTake(imu_state_mutex, 100)) {
|
|
|
|
|
|
|
|
|
|
if (imu_state_var.lin_accel_global.z < -7.0) {
|
|
|
|
|
active = true;
|
|
|
|
|
xTaskCreate(
|
|
|
|
|
[](void *pvParameters) {
|
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(100));
|
|
|
|
|
std::atomic_store(&killswitch_active, false);
|
|
|
|
|
vTaskDelete(NULL);
|
|
|
|
|
},
|
|
|
|
|
"lambda_task", 4096, NULL, 5, NULL);
|
|
|
|
|
} else {
|
|
|
|
|
released = false;
|
|
|
|
|
}
|
|
|
|
|
xSemaphoreGive(imu_state_mutex);
|
|
|
|
|
}
|
2026-04-17 00:24:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Logging
|
|
|
|
|
if (millis() > last_print_time + 1000) {
|
2026-04-06 03:39:08 +01:00
|
|
|
last_print_time = millis();
|
2026-04-06 00:27:32 +01:00
|
|
|
|
|
|
|
|
std::optional<Eigen::Vector3f> coords;
|
|
|
|
|
float lat, lon, alt;
|
2026-04-07 10:48:44 +01:00
|
|
|
bool gps_values = false;
|
|
|
|
|
bool fix = false;
|
|
|
|
|
uint8_t sat_count = 0;
|
|
|
|
|
if (gps_mutex && xSemaphoreTake(gps_mutex, (TickType_t)20) == pdTRUE) {
|
2026-04-06 00:27:32 +01:00
|
|
|
if (gps->gps_avaliable()) {
|
|
|
|
|
coords = gps->get_coordinates();
|
|
|
|
|
lat = gps->gps->latitudeDegrees;
|
|
|
|
|
lon = gps->gps->longitudeDegrees;
|
|
|
|
|
alt = gps->gps->altitude;
|
2026-04-20 20:31:10 +01:00
|
|
|
|
2026-04-24 01:41:23 +01:00
|
|
|
if (!first_wayp_was_set) {
|
|
|
|
|
first_wayp_was_set = true;
|
|
|
|
|
xTaskCreate(
|
|
|
|
|
[](void *pvParameters) {
|
|
|
|
|
Eigen::Vector3f coords = Eigen::Vector3f::Zero();
|
|
|
|
|
vTaskDelay(10000);
|
|
|
|
|
int count = 0;
|
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
|
vTaskDelay(4000);
|
|
|
|
|
|
|
|
|
|
if (gps_mutex &&
|
|
|
|
|
xSemaphoreTake(gps_mutex, (TickType_t)20) == pdTRUE) {
|
|
|
|
|
|
|
|
|
|
auto lat = gps->gps->latitudeDegrees;
|
|
|
|
|
auto lon = gps->gps->longitudeDegrees;
|
|
|
|
|
coords +=
|
|
|
|
|
Eigen::Vector3f(lat, lon, sens_fus.position.z());
|
|
|
|
|
count++;
|
|
|
|
|
|
|
|
|
|
xSemaphoreGive(gps_mutex);
|
|
|
|
|
} else {
|
|
|
|
|
ESP_LOGE("FIRST_WAYP", "FAILED TO GET MUTEX ON AVG");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
coords = coords / (float)count;
|
2026-04-20 20:31:10 +01:00
|
|
|
|
|
|
|
|
if (gps_mutex &&
|
|
|
|
|
xSemaphoreTake(gps_mutex, (TickType_t)20) == pdTRUE) {
|
|
|
|
|
|
2026-04-24 01:41:23 +01:00
|
|
|
gps->origin_lat = coords.x();
|
|
|
|
|
gps->origin_long = coords.y();
|
2026-04-20 20:31:10 +01:00
|
|
|
xSemaphoreGive(gps_mutex);
|
2026-04-24 01:41:23 +01:00
|
|
|
} else {
|
|
|
|
|
ESP_LOGE("FIRST_WAYP", "FAILED TO GET MUTEX ON ORIGIN");
|
2026-04-20 20:31:10 +01:00
|
|
|
}
|
|
|
|
|
|
2026-04-24 01:41:23 +01:00
|
|
|
if (nav_mutex && xSemaphoreTake(nav_mutex, 1000)) {
|
2026-04-20 20:31:10 +01:00
|
|
|
|
2026-04-24 01:41:23 +01:00
|
|
|
nav_man.waypoints[0].coords = coords;
|
|
|
|
|
nav_man.current_waypoint = 0;
|
|
|
|
|
nav_man.waypoints[0].active = true;
|
|
|
|
|
nav_man.waypoints[0].landing = true;
|
|
|
|
|
xSemaphoreGive(nav_mutex);
|
|
|
|
|
} else {
|
|
|
|
|
ESP_LOGE("FIRST_WAYP", "FAILED TO GET NAV MUTEX");
|
|
|
|
|
first_wayp_was_set = false;
|
|
|
|
|
}
|
2026-04-20 20:31:10 +01:00
|
|
|
|
2026-04-24 01:41:23 +01:00
|
|
|
vTaskDelete(NULL);
|
|
|
|
|
},
|
|
|
|
|
"lambda_task_gps_init", 8192, NULL, 5, NULL);
|
|
|
|
|
}
|
2026-04-07 10:48:44 +01:00
|
|
|
gps_values = true;
|
2026-04-06 00:27:32 +01:00
|
|
|
}
|
2026-04-07 10:48:44 +01:00
|
|
|
sat_count = gps->gps->satellites;
|
|
|
|
|
fix = gps->gps->fix;
|
2026-04-06 00:27:32 +01:00
|
|
|
xSemaphoreGive(gps_mutex);
|
|
|
|
|
|
2026-04-07 10:48:44 +01:00
|
|
|
if (gps_values) {
|
|
|
|
|
|
|
|
|
|
ESP_LOGI(TAG,
|
|
|
|
|
"loc -> lat: %f, long: %f, height: %f, sat_c: %d, fix: %b",
|
|
|
|
|
lat, lon, alt, sat_count, fix);
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-06 00:27:32 +01:00
|
|
|
if (coords.has_value()) {
|
|
|
|
|
auto D_pos = coords.value();
|
|
|
|
|
|
|
|
|
|
ESP_LOGI(TAG, " -> D(pos): (%f, %f, %f)", D_pos[0], D_pos[1],
|
|
|
|
|
D_pos[2]);
|
|
|
|
|
}
|
2026-04-04 02:39:41 +01:00
|
|
|
}
|
2026-04-06 00:27:32 +01:00
|
|
|
env_sens::dbg_sens();
|
|
|
|
|
|
|
|
|
|
if (sens_fus_mutex &&
|
|
|
|
|
xSemaphoreTake(sens_fus_mutex, pdMS_TO_TICKS(10)) == pdTRUE) {
|
|
|
|
|
local_pos = sens_fus.position;
|
|
|
|
|
local_vel = sens_fus.velocity;
|
2026-04-20 20:31:10 +01:00
|
|
|
sens_fus_data_ready = true;
|
2026-04-06 00:27:32 +01:00
|
|
|
xSemaphoreGive(sens_fus_mutex);
|
2026-03-26 23:01:20 +00:00
|
|
|
}
|
2026-03-30 22:09:23 +01:00
|
|
|
|
2026-04-20 20:31:10 +01:00
|
|
|
auto wayp = nav_man.get_current_waypoint().coords;
|
|
|
|
|
auto wayp_axis = nav_man.get_current_waypoint().coords_in_axis.value_or(
|
|
|
|
|
Eigen::Vector3f::Zero());
|
|
|
|
|
ESP_LOGI(TAG, "wayp(pos): (%f, %f, %f)", wayp.x(), wayp.y(), wayp.z());
|
|
|
|
|
ESP_LOGI(TAG, "wayp_axis(pos): (%f, %f, %f)", wayp_axis.x(),
|
|
|
|
|
wayp_axis.y(), wayp_axis.z());
|
|
|
|
|
|
|
|
|
|
if (sens_fus_data_ready) {
|
|
|
|
|
ESP_LOGI(TAG, "sens_fus(pos): (%f, %f, %f)", local_pos[0], local_pos[1],
|
2026-04-06 00:27:32 +01:00
|
|
|
local_pos[2]);
|
2026-04-20 20:31:10 +01:00
|
|
|
ESP_LOGI(TAG, "sens_fus(vel): (%f, %f, %f)", local_vel[0], local_vel[1],
|
2026-04-06 00:27:32 +01:00
|
|
|
local_vel[2]);
|
|
|
|
|
}
|
2026-04-07 10:48:44 +01:00
|
|
|
|
2026-04-17 00:24:52 +01:00
|
|
|
if (motor_throttles != nullptr) {
|
2026-04-20 02:52:05 +01:00
|
|
|
ESP_LOGI(TAG, "Throttles: (%f, %f, %f, %f), kill: %d",
|
|
|
|
|
motor_throttles[0], motor_throttles[1], motor_throttles[2],
|
|
|
|
|
motor_throttles[3], std::atomic_load(&killswitch_active));
|
2026-04-17 00:24:52 +01:00
|
|
|
}
|
|
|
|
|
|
2026-04-24 01:41:23 +01:00
|
|
|
if (xSemaphoreTake(controller_input_semaphore, 10)) {
|
2026-04-17 00:24:52 +01:00
|
|
|
ESP_LOGI(TAG, "Controller: (%f, %f), (%f, %f)",
|
|
|
|
|
current_controller_input.lx, current_controller_input.ly,
|
|
|
|
|
current_controller_input.rx, current_controller_input.ry);
|
2026-04-24 01:41:23 +01:00
|
|
|
xSemaphoreGive(controller_input_semaphore);
|
2026-04-17 00:24:52 +01:00
|
|
|
}
|
2026-04-24 01:41:23 +01:00
|
|
|
ESP_LOGI(TAG, "ROT: (%f, %f, %f)", imu_state_var.rot_euler.x(),
|
|
|
|
|
imu_state_var.rot_euler.y(), imu_state_var.rot_euler.z());
|
2026-03-30 22:09:23 +01:00
|
|
|
}
|
|
|
|
|
|
2026-04-19 15:50:02 +01:00
|
|
|
vTaskDelay(pdMS_TO_TICKS(5));
|
2026-03-26 23:01:20 +00:00
|
|
|
}
|
2026-03-16 00:49:02 +00:00
|
|
|
}
|