diff --git a/CMakeLists.txt b/CMakeLists.txt index 11d68fa236ff1d7089ebc53b684a179763e35b1b..ce92b66665d75340ae5d18e57f4844b853ab66ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,13 +151,18 @@ sbs_target(parafoil-t-approach-milano stm32f429zi_death_stack_v2) add_executable(parafoil-t-approach-dynamic src/Parafoil/parafoil-entry.cpp ${PARAFOIL_COMPUTER}) target_include_directories(parafoil-t-approach-dynamic PRIVATE ${OBSW_INCLUDE_DIRS}) - target_compile_definitions(parafoil-t-approach-dynamic PRIVATE +target_compile_definitions(parafoil-t-approach-dynamic PRIVATE ALGORITHM_EARLY_MANEUVER DYNAMIC_TARGET DYNAMIC_TARGET_LATITUDE_OFFSET=35 DYNAMIC_TARGET_LONGITUDE_OFFSET=-156 ) sbs_target(parafoil-t-approach-dynamic stm32f429zi_death_stack_v2) +add_executable(parafoil-ground-test src/Parafoil/parafoil-entry.cpp ${PARAFOIL_COMPUTER}) +target_include_directories(parafoil-ground-test PRIVATE ${OBSW_INCLUDE_DIRS}) +target_compile_definitions(parafoil-ground-test PRIVATE ALGORITHM_PROGRESSIVE_ROTATION MILANO DISABLE_LANDING_FLARE) +sbs_target(parafoil-ground-test stm32f429zi_death_stack_v2) + add_executable(mockup-main src/MockupMain/mockup-entry.cpp ${MOCKUP_MAIN_COMPUTER}) target_include_directories(mockup-main PRIVATE ${OBSW_INCLUDE_DIRS}) sbs_target(mockup-main stm32f429zi_death_stack_v2) \ No newline at end of file diff --git a/src/Parafoil/AltitudeTrigger/AltitudeTrigger.cpp b/src/Parafoil/AltitudeTrigger/AltitudeTrigger.cpp index c029ea89be576748073192edd7ae04bdd71834e3..64153468bf1c09d84c55a37c0f98ea4ee2940ec6 100644 --- a/src/Parafoil/AltitudeTrigger/AltitudeTrigger.cpp +++ b/src/Parafoil/AltitudeTrigger/AltitudeTrigger.cpp @@ -31,17 +31,20 @@ using namespace Boardcore; using namespace Boardcore::Units::Length; using namespace Common; -namespace config = Parafoil::Config; namespace Parafoil { +AltitudeTrigger::AltitudeTrigger(AltitudeTriggerConfig config) : config(config) +{ + this->thresholdAltitude = config.threshold.value(); +} + bool AltitudeTrigger::start() { auto& scheduler = getModule<BoardScheduler>()->altitudeTrigger(); - auto task = scheduler.addTask([this] { update(); }, - config::AltitudeTrigger::UPDATE_RATE); + auto task = scheduler.addTask([this] { update(); }, config.updateRate); if (task == 0) return false; @@ -67,7 +70,7 @@ bool AltitudeTrigger::isEnabled() { return running; } void AltitudeTrigger::setDeploymentAltitude(Meter altitude) { - targetAltitude = altitude.value(); + thresholdAltitude = altitude.value(); } void AltitudeTrigger::update() @@ -79,12 +82,12 @@ void AltitudeTrigger::update() auto nasState = getModule<NASController>()->getNasState(); float altitude = -nasState.d; - if (altitude < targetAltitude) + if (altitude < thresholdAltitude) confidence++; else confidence = 0; - if (confidence >= config::AltitudeTrigger::CONFIDENCE) + if (confidence >= config.confidence) { confidence = 0; EventBroker::getInstance().post(ALTITUDE_TRIGGER_ALTITUDE_REACHED, diff --git a/src/Parafoil/AltitudeTrigger/AltitudeTrigger.h b/src/Parafoil/AltitudeTrigger/AltitudeTrigger.h index 7531f60a6e4e993210589a8c33787e0914fd1e67..7024795542b2de8068820ee7af628f8b59f78b5d 100644 --- a/src/Parafoil/AltitudeTrigger/AltitudeTrigger.h +++ b/src/Parafoil/AltitudeTrigger/AltitudeTrigger.h @@ -28,6 +28,8 @@ #include <atomic> #include <utils/ModuleManager/ModuleManager.hpp> +#include "AltitudeTriggerConfig.h" + namespace Parafoil { class BoardScheduler; @@ -37,6 +39,11 @@ class AltitudeTrigger : public Boardcore::InjectableWithDeps<BoardScheduler, NASController> { public: + /** + * @brief Constructor + */ + AltitudeTrigger(AltitudeTriggerConfig config); + /** * @brief Adds the update() task to the task scheduler. */ @@ -68,6 +75,8 @@ public: void setDeploymentAltitude(Boardcore::Units::Length::Meter altitude); private: + AltitudeTriggerConfig config; + // Update method that posts a FLIGHT_WING_ALT_PASSED when the correct // altitude is reached void update(); @@ -79,9 +88,7 @@ private: // altitude int confidence = 0; - std::atomic<float> targetAltitude{Boardcore::Units::Length::Meter{ - Config::AltitudeTrigger::DEPLOYMENT_ALTITUDE} - .value()}; + std::atomic<float> thresholdAltitude{0}; }; } // namespace Parafoil diff --git a/src/Parafoil/AltitudeTrigger/AltitudeTriggerConfig.h b/src/Parafoil/AltitudeTrigger/AltitudeTriggerConfig.h new file mode 100644 index 0000000000000000000000000000000000000000..b0a9bff7afd5e04d9766e1feae7aa6ed2661b121 --- /dev/null +++ b/src/Parafoil/AltitudeTrigger/AltitudeTriggerConfig.h @@ -0,0 +1,41 @@ +/* Copyright (c) 2025 Skyward Experimental Rocketry + * Author: Davide Basso + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include <units/Frequency.h> +#include <units/Length.h> + +namespace Parafoil +{ + +/* linter-off */ using namespace Boardcore::Units::Length; +/* linter-off */ using namespace Boardcore::Units::Frequency; + +struct AltitudeTriggerConfig +{ + Meter threshold; ///< [m] Altitude threshold + int confidence; ///< Number of samples to reach the threshold + Hertz updateRate; ///< [Hz] Update rate of the trigger +}; + +} // namespace Parafoil diff --git a/src/Parafoil/Configs/WingConfig.h b/src/Parafoil/Configs/WingConfig.h index d8eeea8b96b814ed33385cf7976eba1e974c6ee4..89e440403e8c762a2895e6b1c6ea63f62678d5ab 100644 --- a/src/Parafoil/Configs/WingConfig.h +++ b/src/Parafoil/Configs/WingConfig.h @@ -135,17 +135,24 @@ constexpr auto TARGET_ALTITUDE_THRESHOLD = 50_m; } // namespace Guidance -} // namespace Wing - -namespace AltitudeTrigger +namespace LandingFlare { /* linter off */ using namespace Boardcore::Units::Frequency; /* linter off */ using namespace Boardcore::Units::Length; -constexpr auto DEPLOYMENT_ALTITUDE = 300_m; -constexpr auto CONFIDENCE = 10; // [samples] -constexpr auto UPDATE_RATE = 10_hz; -} // namespace AltitudeTrigger +#ifdef DISABLE_LANDING_FLARE +constexpr auto ENABLED = false; +#else +constexpr auto ENABLED = true; +#endif + +constexpr auto FLARE_ALTITUDE = 15_m; +constexpr auto CONFIDENCE = 10; // [samples] +constexpr auto UPDATE_RATE = 10_hz; +constexpr auto FLARE_DURATION = 5_s; +} // namespace LandingFlare + +} // namespace Wing } // namespace Config } // namespace Parafoil diff --git a/src/Parafoil/StateMachines/WingController/WingController.cpp b/src/Parafoil/StateMachines/WingController/WingController.cpp index 33543e55b5be1a24fad6ab57f6788db8c7a9796b..b63eebcb5723c3534a29763b1ba4597c6c30a794 100644 --- a/src/Parafoil/StateMachines/WingController/WingController.cpp +++ b/src/Parafoil/StateMachines/WingController/WingController.cpp @@ -205,6 +205,8 @@ State WingController::FlyingDeployment(const Boardcore::Event& event) State WingController::FlyingControlledDescent(const Boardcore::Event& event) { + static uint16_t flareTimeoutEventId; + switch (event) { case EV_ENTRY: // start automatic algorithms @@ -222,10 +224,31 @@ State WingController::FlyingControlledDescent(const Boardcore::Event& event) { return transition(&WingController::OnGround); } + case ALTITUDE_TRIGGER_ALTITUDE_REACHED: + { + pauseAlgorithm(); + flareWing(); + + flareTimeoutEventId = EventBroker::getInstance().postDelayed( + DPL_FLARE_STOP, TOPIC_FLIGHT, + Millisecond{Config::Wing::LandingFlare::FLARE_DURATION} + .value()); + + return HANDLED; + } + case DPL_FLARE_STOP: + { + resetWing(); + resumeAlgorithm(); + + return HANDLED; + } case EV_EXIT: { stopAlgorithm(); + EventBroker::getInstance().removeDelayed(flareTimeoutEventId); + getModule<WindEstimation>()->stopAlgorithm(); getModule<WindEstimation>()->stopCalibration(); @@ -567,6 +590,9 @@ void WingController::stopAlgorithm() } } +void WingController::pauseAlgorithm() { running = false; } +void WingController::resumeAlgorithm() { running = true; } + void WingController::updateEarlyManeuverPoints() { using namespace Eigen; diff --git a/src/Parafoil/StateMachines/WingController/WingController.h b/src/Parafoil/StateMachines/WingController/WingController.h index 0b277170f63cc6dfab0bd893039d3fa1e42cf05a..4edeb0245ae5257a814fb271573e17d8ebf17328 100644 --- a/src/Parafoil/StateMachines/WingController/WingController.h +++ b/src/Parafoil/StateMachines/WingController/WingController.h @@ -203,6 +203,16 @@ private: */ void stopAlgorithm(); + /** + * @brief Pauses the currently selected algorithm. + */ + void pauseAlgorithm(); + + /** + * @brief Resumes the currently selected algorithm. + */ + void resumeAlgorithm(); + /** * @brief Update early maneuver guidance points (EMC, M1, M2) based on the * current position and the target position. diff --git a/src/Parafoil/parafoil-entry.cpp b/src/Parafoil/parafoil-entry.cpp index 918ea77d2e0b7a097f1052e3685d4302f14d983b..034e23310f3bbf648bc1a39b1d8c93cb25a49b77 100644 --- a/src/Parafoil/parafoil-entry.cpp +++ b/src/Parafoil/parafoil-entry.cpp @@ -121,9 +121,17 @@ int main() auto radio = new Radio(); initResult &= depman.insert(radio); + // Landing flare activation + namespace LandingFlareConfig = Config::Wing::LandingFlare; + AltitudeTriggerConfig landingFlareConfig = { + .threshold = LandingFlareConfig::FLARE_ALTITUDE, + .confidence = LandingFlareConfig::CONFIDENCE, + .updateRate = LandingFlareConfig::UPDATE_RATE, + }; + auto landingFlare = new AltitudeTrigger(landingFlareConfig); + initResult &= depman.insert(landingFlare); + // Flight algorithms - auto altitudeTrigger = new AltitudeTrigger(); - initResult &= depman.insert(altitudeTrigger); auto wingController = new WingController(); initResult &= depman.insert(wingController); auto windEstimation = new WindEstimation(); @@ -152,7 +160,7 @@ int main() START_MODULE(radio); START_MODULE(nasController); START_MODULE(flightModeManager); - START_MODULE(altitudeTrigger); + START_MODULE(landingFlare); START_MODULE(windEstimation); START_MODULE(wingController); START_MODULE(actuators);