work on getting positioning working
This commit is contained in:
parent
8c087ab5f3
commit
587d977018
83
main/gps.h
83
main/gps.h
|
|
@ -1,24 +1,91 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef PS
|
||||||
|
#undef PS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef F
|
||||||
|
#undef F
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Eigen/Dense>
|
||||||
|
|
||||||
#include "HardwareSerial.h"
|
#include "HardwareSerial.h"
|
||||||
#include "Wire.h"
|
#include "esp_log.h"
|
||||||
#include <Adafruit_GPS.h>
|
#include <Adafruit_GPS.h>
|
||||||
|
#include <cmath>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
const float TO_RAD = M_PI / 180.0f;
|
||||||
|
const float KNOTS_TO_M_SEC = 0.5144444f;
|
||||||
|
|
||||||
|
const float earth_radius = 6371000.0f;
|
||||||
|
|
||||||
struct GPS {
|
struct GPS {
|
||||||
Adafruit_GPS gps;
|
Adafruit_GPS gps;
|
||||||
GPS(TwoWire *theWire) {
|
float origin_lat;
|
||||||
Serial2.begin(9600);
|
float origin_long;
|
||||||
gps = Adafruit_GPS(&Serial2);
|
|
||||||
gps.begin(0x10);
|
|
||||||
gps.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
|
|
||||||
|
|
||||||
gps.sendCommand(PMTK_API_SET_FIX_CTL_5HZ);
|
GPS() {
|
||||||
gps.sendCommand(PMTK_SET_NMEA_UPDATE_5HZ);
|
|
||||||
|
origin_lat = INFINITY;
|
||||||
|
origin_long = INFINITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void begin() {
|
||||||
|
this->gps = Adafruit_GPS(&Serial2);
|
||||||
|
this->gps.begin(9600);
|
||||||
|
this->gps.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
|
||||||
|
|
||||||
|
this->gps.sendCommand(PMTK_API_SET_FIX_CTL_5HZ);
|
||||||
|
this->gps.sendCommand(PMTK_SET_NMEA_UPDATE_5HZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gps_avaliable() { return this->gps.fix; }
|
||||||
|
|
||||||
|
std::optional<Eigen::Vector2f> velocity() {
|
||||||
|
if (!this->gps.fix) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
float speed = this->gps.speed * KNOTS_TO_M_SEC;
|
||||||
|
float angle = this->gps.angle * TO_RAD;
|
||||||
|
|
||||||
|
return Eigen::Vector2f(cos(M_PI_2 - angle), sin(M_PI_2 - angle)) * speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<Eigen::Vector3f>
|
||||||
|
waypoint_to_xyz(float latitude, float longitude, float height) {
|
||||||
|
if (this->origin_lat == INFINITY || this->origin_long == INFINITY) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
float dLat = (latitude - this->origin_lat) * TO_RAD;
|
||||||
|
float dLon = (longitude - this->origin_long) * TO_RAD;
|
||||||
|
|
||||||
|
float meanLat = (this->origin_lat) * TO_RAD;
|
||||||
|
|
||||||
|
float y = dLat * earth_radius;
|
||||||
|
float x = dLon * earth_radius * std::cos(meanLat);
|
||||||
|
float z = this->gps.altitude;
|
||||||
|
|
||||||
|
return Eigen::Vector3f(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<Eigen::Vector3f> get_coordinates() {
|
||||||
|
if (this->gps.fix == false && this->gps.latitudeDegrees != 0.0 &&
|
||||||
|
this->gps.longitudeDegrees != 0.0) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
float latitude = this->gps.latitudeDegrees;
|
||||||
|
float longitude = this->gps.longitudeDegrees;
|
||||||
|
|
||||||
|
return this->waypoint_to_xyz(latitude, longitude, this->gps.altitude);
|
||||||
}
|
}
|
||||||
|
|
||||||
void poll() {
|
void poll() {
|
||||||
this->gps.read();
|
this->gps.read();
|
||||||
if (this->gps.newNMEAreceived()) {
|
if (this->gps.newNMEAreceived()) {
|
||||||
|
ESP_LOGD("GPS", "NMEA LINE: %s", this->gps.lastNMEA());
|
||||||
if (!this->gps.parse(this->gps.lastNMEA()))
|
if (!this->gps.parse(this->gps.lastNMEA()))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,54 @@
|
||||||
#include "HardwareSerial.h"
|
|
||||||
#include "dshot_utils.h"
|
|
||||||
|
|
||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <cstdio>
|
||||||
|
|
||||||
#include "DShotRMT.h"
|
#include "freertos/idf_additions.h"
|
||||||
#include "env_sens.h"
|
#include "freertos/projdefs.h"
|
||||||
|
#include "gps.h"
|
||||||
|
|
||||||
static const constexpr char *TAG = "Main";
|
static const constexpr char *TAG = "Main";
|
||||||
const gpio_num_t MOTOR_PIN = GPIO_NUM_22;
|
|
||||||
|
|
||||||
DShotRMT motor(MOTOR_PIN, DSHOT300, true);
|
SemaphoreHandle_t gps_mutex;
|
||||||
|
GPS *gps = nullptr;
|
||||||
|
|
||||||
|
void gps_poll_task(void *_) {
|
||||||
|
while (true) {
|
||||||
|
if (xSemaphoreTake(gps_mutex, (TickType_t)10) == pdTRUE) {
|
||||||
|
gps->poll();
|
||||||
|
xSemaphoreGive(gps_mutex);
|
||||||
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(50));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gps_poll_init() {
|
||||||
|
gps_mutex = xSemaphoreCreateMutex();
|
||||||
|
if (gps_mutex != NULL) {
|
||||||
|
xTaskCreate(gps_poll_task, "Writer", 2048, NULL, 1, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void app_main(void) {
|
extern "C" void app_main(void) {
|
||||||
initArduino();
|
initArduino();
|
||||||
printf("beg: %d", motor.begin().result_code);
|
gps = new GPS();
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Arming ESC...");
|
while (true) {
|
||||||
// Send 0 throttle for 4 seconds to arm
|
|
||||||
unsigned long armTime = millis();
|
if (xSemaphoreTake(gps_mutex, (TickType_t)10) == pdTRUE) {
|
||||||
while (millis() - armTime < 4000) {
|
ESP_LOGI(TAG, "loc -> lat: %f, long: %f, height: %f",
|
||||||
motor.sendThrottlePercent(0);
|
gps->gps.latitudeDegrees, gps->gps.longitudeDegrees,
|
||||||
// delay(1);
|
gps->gps.altitude);
|
||||||
|
if (gps->gps_avaliable()) {
|
||||||
|
|
||||||
|
auto D_pos = gps->get_coordinates().value();
|
||||||
|
ESP_LOGI(TAG, " -> D(pos): (%f, %f, %f)", D_pos[0], D_pos[1],
|
||||||
|
D_pos[2]);
|
||||||
}
|
}
|
||||||
delay(50);
|
xSemaphoreGive(gps_mutex);
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Motor Armed. Ramping up...");
|
|
||||||
// Send 10% throttle for 5 seconds
|
|
||||||
unsigned long runTime = millis();
|
|
||||||
while (millis() - runTime < 5000) {
|
|
||||||
auto res = motor.sendThrottlePercent(10);
|
|
||||||
printf("%d, %d\n", res.result_code, res.erpm);
|
|
||||||
//
|
|
||||||
// ESP_LOGI(TAG, "current: %d",
|
|
||||||
// motor.getTelemetry().telemetry_data.current);
|
|
||||||
// delay(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Stopping motor");
|
vTaskDelay(pdMS_TO_TICKS(250));
|
||||||
motor.sendThrottlePercent(0);
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
27
main/pos.cpp
27
main/pos.cpp
|
|
@ -1,27 +0,0 @@
|
||||||
#include <Eigen/Dense>
|
|
||||||
|
|
||||||
struct nav_compl {
|
|
||||||
Eigen::Vector3f position = Eigen::Vector3f::Zero();
|
|
||||||
Eigen::Vector3f velocity = Eigen::Vector3f::Zero();
|
|
||||||
|
|
||||||
Eigen::Vector3f gps_weight_vel = Eigen::Vector3f::Constant(0.01f);
|
|
||||||
Eigen::Vector3f gps_weight_pos = Eigen::Vector3f::Constant(0.01f);
|
|
||||||
|
|
||||||
void predict(float dt, Eigen::Vector3f accel) {
|
|
||||||
Eigen::Vector3f next_velocity = this->velocity + (accel * dt);
|
|
||||||
|
|
||||||
this->position += (this->velocity + next_velocity) * 0.5f * dt;
|
|
||||||
|
|
||||||
this->velocity = next_velocity;
|
|
||||||
}
|
|
||||||
|
|
||||||
void measure(Eigen::Vector3f gps_pos, Eigen::Vector3f gps_vel) {
|
|
||||||
this->position = (Eigen::Vector3f::Ones() - gps_weight_pos)
|
|
||||||
.cwiseProduct(this->position) +
|
|
||||||
gps_weight_pos.cwiseProduct(gps_pos);
|
|
||||||
|
|
||||||
this->velocity = (Eigen::Vector3f::Ones() - gps_weight_vel)
|
|
||||||
.cwiseProduct(this->velocity) +
|
|
||||||
gps_weight_vel.cwiseProduct(gps_vel);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
|
||||||
|
#ifdef PS
|
||||||
|
#undef PS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef F
|
||||||
|
#undef F
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Eigen/Dense>
|
||||||
|
|
||||||
|
inline float getYawDifference(const Eigen::Vector3f &v_gps,
|
||||||
|
const Eigen::Vector3f &v_imu) {
|
||||||
|
// 1. Extract the 2D components (Project to XY plane)
|
||||||
|
float yaw_gps = std::atan2(v_gps.y(), v_gps.x());
|
||||||
|
float yaw_imu = std::atan2(v_imu.y(), v_imu.x());
|
||||||
|
|
||||||
|
// 2. Calculate the raw difference
|
||||||
|
float delta_yaw = yaw_gps - yaw_imu;
|
||||||
|
|
||||||
|
// 3. Normalize the angle to [-PI, PI]
|
||||||
|
while (delta_yaw > M_PI)
|
||||||
|
delta_yaw -= 2.0 * M_PI;
|
||||||
|
while (delta_yaw < -M_PI)
|
||||||
|
delta_yaw += 2.0 * M_PI;
|
||||||
|
|
||||||
|
return delta_yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct nav_compl {
|
||||||
|
Eigen::Vector3f position = Eigen::Vector3f::Zero();
|
||||||
|
Eigen::Vector3f velocity = Eigen::Vector3f::Zero();
|
||||||
|
float yaw_offset = 0.0;
|
||||||
|
float yaw_delta_weight = 0.04;
|
||||||
|
|
||||||
|
Eigen::Vector3f gps_weight_vel = Eigen::Vector3f::Constant(0.03f);
|
||||||
|
Eigen::Vector3f gps_weight_pos = Eigen::Vector3f::Constant(0.03f);
|
||||||
|
|
||||||
|
void predict(float dt, Eigen::Vector3f accel) {
|
||||||
|
Eigen::Vector3f accel_rotated =
|
||||||
|
Eigen::AngleAxisf(this->yaw_offset, Eigen::Vector3d::UnitZ()) * accel;
|
||||||
|
|
||||||
|
Eigen::Vector3f next_velocity = this->velocity + (accel_rotated * dt);
|
||||||
|
|
||||||
|
this->position += (this->velocity + next_velocity) * 0.5f * dt;
|
||||||
|
|
||||||
|
this->velocity = next_velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void measure(Eigen::Vector3f gps_pos, Eigen::Vector3f gps_vel) {
|
||||||
|
this->position = (Eigen::Vector3f::Ones() - gps_weight_pos)
|
||||||
|
.cwiseProduct(this->position) +
|
||||||
|
gps_weight_pos.cwiseProduct(gps_pos);
|
||||||
|
|
||||||
|
if (gps_vel.norm() > 1) {
|
||||||
|
float yaw_delta = getYawDifference(gps_vel, this->velocity);
|
||||||
|
yaw_offset =
|
||||||
|
yaw_offset * (1 - yaw_delta_weight) + yaw_delta * yaw_delta_weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->velocity = (Eigen::Vector3f::Ones() - gps_weight_vel)
|
||||||
|
.cwiseProduct(this->velocity) +
|
||||||
|
gps_weight_vel.cwiseProduct(gps_vel);
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue