Обновить pilot.cpp
This commit is contained in:
148
pilot.cpp
148
pilot.cpp
@@ -6,24 +6,29 @@
|
|||||||
|
|
||||||
// Настройки
|
// Настройки
|
||||||
constexpr float Ki = 0.03f;
|
constexpr float Ki = 0.03f;
|
||||||
constexpr float target_height = 65.f;
|
constexpr float waypoint_radius = 3.f;
|
||||||
constexpr float waypoint_radius = 1.5f;
|
|
||||||
constexpr float pitch_constraint = 20.f;
|
constexpr float pitch_constraint = 20.f;
|
||||||
constexpr float yaw_constraint = 20.f;
|
constexpr float yaw_constraint = 20.f;
|
||||||
|
|
||||||
|
// https://github.com/GyverLibs/AsyncStream @ 1.1
|
||||||
|
// https://github.com/bblanchon/ArduinoJson @ 7.3.1
|
||||||
|
|
||||||
struct WayPoint {
|
struct WayPoint {
|
||||||
float x;
|
float x;
|
||||||
float z;
|
float z;
|
||||||
|
float y;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector wayPoints = {
|
std::vector<WayPoint> wayPoints = {};
|
||||||
WayPoint{.x = -480.f, .z = 85.f},
|
|
||||||
WayPoint{.x = -30.f, .z = 500.f},
|
|
||||||
WayPoint{.x = 150.f, .z = 330.f},
|
|
||||||
WayPoint{.x = 150.f, .z = 5.f},
|
|
||||||
};
|
|
||||||
|
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
|
bool cargoDrop = false;
|
||||||
|
|
||||||
|
String HandleMessages();
|
||||||
|
bool ReceiveNewMessage(String &err);
|
||||||
|
void RouteNewMessage(String &err);
|
||||||
|
void HandleNewWaypoints(String &err);
|
||||||
|
void HandleDropCargo();
|
||||||
|
|
||||||
void Task_solution::setup(HardwareSerial *a_Serial) {
|
void Task_solution::setup(HardwareSerial *a_Serial) {
|
||||||
debug_serial = a_Serial;
|
debug_serial = a_Serial;
|
||||||
@@ -31,10 +36,11 @@ void Task_solution::setup(HardwareSerial *a_Serial) {
|
|||||||
Serial2.begin(115200);
|
Serial2.begin(115200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printDebugMessage(const String &_) {
|
||||||
|
}
|
||||||
|
|
||||||
float distance(const float x1, const float y1, const float x2, const float y2) {
|
float distance(const float x1, const float y1, const float x2, const float y2) {
|
||||||
return static_cast<float>(
|
return sqrtf(powf(x2 - x1, 2.f) + powf(y2 - y1, 2.f));
|
||||||
sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isEqual(const float a, const float b, const float accuracy) {
|
bool isEqual(const float a, const float b, const float accuracy) {
|
||||||
@@ -69,8 +75,10 @@ SignalBody Task_solution::loop(Skywalker2015PacketTelemetry a_telemetry) {
|
|||||||
// _Point_Index = GetNowPointIndex(a_telemetry.L, a_telemetry.Z, a_telemetry.H);
|
// _Point_Index = GetNowPointIndex(a_telemetry.L, a_telemetry.Z, a_telemetry.H);
|
||||||
const float target_x = wayPoints[_Point_Index].x;
|
const float target_x = wayPoints[_Point_Index].x;
|
||||||
const float target_y = wayPoints[_Point_Index].z;
|
const float target_y = wayPoints[_Point_Index].z;
|
||||||
|
const float target_height = wayPoints[_Point_Index].y;
|
||||||
|
|
||||||
const auto target_psi = static_cast<float>(
|
const auto target_psi = static_cast<float>(
|
||||||
-degrees(atan2(target_y - a_telemetry.Z, target_x - a_telemetry.L))
|
-degrees(atan2f(target_y - a_telemetry.Z, target_x - a_telemetry.L))
|
||||||
);
|
);
|
||||||
|
|
||||||
_ans.Gamma_direct = GammaReg(a_telemetry.Psi, target_psi);
|
_ans.Gamma_direct = GammaReg(a_telemetry.Psi, target_psi);
|
||||||
@@ -84,6 +92,17 @@ SignalBody Task_solution::loop(Skywalker2015PacketTelemetry a_telemetry) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (const String err = HandleMessages(); !err.isEmpty()) {
|
||||||
|
printtoDebugSerial(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cargoDrop) {
|
||||||
|
// Propagate changed state
|
||||||
|
cargo_drop = cargoDrop;
|
||||||
|
cargoDrop = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Отправляем команды на симулятор
|
// Отправляем команды на симулятор
|
||||||
// БЛА будет пытаться выдерживать заданные углы крена и тангажа
|
// БЛА будет пытаться выдерживать заданные углы крена и тангажа
|
||||||
return _ans;
|
return _ans;
|
||||||
@@ -111,12 +130,23 @@ float Task_solution::HeightReg(float Yg, float Vy, float Hz) {
|
|||||||
return Pitch_direct;
|
return Pitch_direct;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
String HandleMessages() {
|
||||||
|
String err;
|
||||||
|
if (ReceiveNewMessage(err)) {
|
||||||
|
RouteNewMessage(err);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
String uartBuffer;
|
String uartBuffer;
|
||||||
bool ReceivedNewMessage(std::string &err) {
|
bool ReceiveNewMessage(String &err) {
|
||||||
while (Serial.available() > 0) {
|
while (Serial.available() > 0) {
|
||||||
const char c = Serial.read();
|
if (const char c = Serial.read(); c == '\n') { // Ожидание конца строки
|
||||||
uartBuffer += c;
|
if (uartBuffer.length() <= 1) {
|
||||||
if (c == '\n') { // Ожидание конца строки
|
printDebugMessage("Invalid message");
|
||||||
|
}
|
||||||
const DeserializationError error = deserializeJson(doc, uartBuffer);
|
const DeserializationError error = deserializeJson(doc, uartBuffer);
|
||||||
uartBuffer = ""; // Очистка буфера
|
uartBuffer = ""; // Очистка буфера
|
||||||
if (error.code() != DeserializationError::Ok) {
|
if (error.code() != DeserializationError::Ok) {
|
||||||
@@ -124,67 +154,49 @@ bool ReceivedNewMessage(std::string &err) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
uartBuffer += c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printDebugMessage(const String &_) {
|
void RouteNewMessage(String &err) {
|
||||||
}
|
if (!doc["cmd"].is<String>()) {
|
||||||
|
err = "Required 'cmd' field";
|
||||||
void ProcessNewMessage(std::string &err) {
|
printDebugMessage(err);
|
||||||
if (!doc.containsKey("path")) {
|
|
||||||
err = "Missing 'path' key";
|
|
||||||
printDebugMessage(String(err.c_str()));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Получение массива точек
|
if (doc["cmd"] == "add_wp") {
|
||||||
|
HandleNewWaypoints(err);
|
||||||
|
} else if (doc["cmd"] == "drop") {
|
||||||
|
HandleDropCargo();
|
||||||
|
} else {
|
||||||
|
err = "Unknown command";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleNewWaypoints(String &err) {
|
||||||
|
if (!doc["path"].is<JsonArray>()) {
|
||||||
|
err = "Required 'path' field";
|
||||||
|
printDebugMessage(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const auto pointsArray = doc["path"].as<JsonArray>();
|
const auto pointsArray = doc["path"].as<JsonArray>();
|
||||||
if (pointsArray.isNull()) {
|
for (const auto &p : pointsArray) {
|
||||||
err = "'wp' is not an array";
|
if (!p["x"].is<float>() || !p["y"].is<float>() || !p["z"].is<float>()) {
|
||||||
printDebugMessage(String(err.c_str()));
|
err = "Missing point field";
|
||||||
return;
|
continue;
|
||||||
|
}
|
||||||
|
WayPoint point{};
|
||||||
|
point.x = p["x"].as<float>();
|
||||||
|
point.z = p["y"].as<float>();
|
||||||
|
point.y = p["z"].as<float>();
|
||||||
|
wayPoints.push_back(point);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<WayPoint> newWayPoints;
|
void HandleDropCargo() {
|
||||||
|
cargoDrop = true;
|
||||||
// Обход всех элементов массива
|
|
||||||
for (JsonVariant value : pointsArray) {
|
|
||||||
auto point = value.as<JsonObject>();
|
|
||||||
if (point.isNull()) {
|
|
||||||
err = "Invalid waypoint format";
|
|
||||||
printDebugMessage(String(err.c_str()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Проверка наличия полей x и z
|
|
||||||
if (!point.containsKey("x") || !point.containsKey("z")) {
|
|
||||||
err = "Waypoint missing x or z field";
|
|
||||||
printDebugMessage(String(err.c_str()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Проверка типов данных
|
|
||||||
if (!point["x"].is<float>() || !point["z"].is<float>()) {
|
|
||||||
err = "Invalid x or z data type";
|
|
||||||
printDebugMessage(String(err.c_str()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Извлечение значений
|
|
||||||
float x = point["x"];
|
|
||||||
float z = point["z"];
|
|
||||||
newWayPoints.push_back(WayPoint{.x = x, .z = z});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Проверка на пустой массив
|
|
||||||
if (newWayPoints.empty()) {
|
|
||||||
err = "No waypoints provided";
|
|
||||||
printDebugMessage(String(err.c_str()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wayPoints = std::move(newWayPoints);
|
|
||||||
err.clear(); // Успешное выполнение без ошибок
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user