diff --git a/cmake/boardcore.cmake b/cmake/boardcore.cmake index 00caab9dcaec93b676d3f75476f48b3699d92dc4..af7bd7e40ee90659f52b2cc0d0f4aa14b1baa531 100644 --- a/cmake/boardcore.cmake +++ b/cmake/boardcore.cmake @@ -33,6 +33,7 @@ foreach(OPT_BOARD ${BOARDS}) # Algorithms ${SBS_BASE}/src/shared/algorithms/ADA/ADA.cpp + ${SBS_BASE}/src/shared/algorithms/AirBrakes/AirBrakes.cpp ${SBS_BASE}/src/shared/algorithms/NAS/NAS.cpp # Debug diff --git a/src/shared/algorithms/AirBrakes/AirBrakes.cpp b/src/shared/algorithms/AirBrakes/AirBrakes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9e288ba06a9f93c6b8179ff0e3669db0be571dee --- /dev/null +++ b/src/shared/algorithms/AirBrakes/AirBrakes.cpp @@ -0,0 +1,239 @@ +/* Copyright (c) 2021-2022 Skyward Experimental Rocketry + * Author: Vincenzo Santomarco, Alberto Nidasio + * + * 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. + */ + +#include "AirBrakes.h" + +#include <logger/Logger.h> +#include <utils/Constants.h> + +#include <limits> + +namespace Boardcore +{ + +AirBrakes::AirBrakes(std::function<TimedTrajectoryPoint()> getCurrentPosition, + TrajectorySet &trajectorySet, + const AirBrakesConfig &config, + std::function<void(float)> setActuator) + : getCurrentPosition(getCurrentPosition), trajectorySet(trajectorySet), + config(config), setActuator(setActuator), + pi(config.KP, config.KI, config.TS) +{ +} + +bool AirBrakes::init() { return true; } + +void AirBrakes::begin() +{ + if (running) + return; + + lastPosition = getCurrentPosition(); + chooseTrajectory(lastPosition); + + Algorithm::begin(); +} + +void AirBrakes::step() +{ + auto currentPosition = getCurrentPosition(); + + // Do nothing if we have no new data + if (lastPosition.timestamp >= currentPosition.timestamp) + return; + lastPosition = currentPosition; + + auto setPoint = getSetpoint(currentPosition); + float rho = getRho(currentPosition.z); + + float targetDrag = piStep(currentPosition, setPoint, rho); + float surface = getSurface(currentPosition, rho, targetDrag); + + setActuator(surface / config.SURFACE); +} + +void AirBrakes::chooseTrajectory(TrajectoryPoint currentPosition) +{ + float minDistance = std::numeric_limits<float>::infinity(); + uint8_t trjIndexMin = trajectorySet.length() / 2; + + for (uint8_t trjIndex = 0; trjIndex < trajectorySet.length(); trjIndex++) + { + Trajectory &trajectory = trajectorySet.trajectories[trjIndex]; + + for (uint32_t ptIndex = 0; ptIndex < trajectory.size(); ptIndex++) + { + TrajectoryPoint point = trajectory.points[ptIndex]; + float distance = + TrajectoryPoint::distanceSquared(point, currentPosition); + + if (distance < minDistance) + { + minDistance = distance; + trjIndexMin = trjIndex; + lastSelectedPointIndex = ptIndex; + chosenTrajectory = &trajectory; + } + } + } + + chosenTrajectory = &(trajectorySet.trajectories[trjIndexMin]); + + Logger::getInstance().log(AirBrakesChosenTrajectory{trjIndexMin}); +} + +TrajectoryPoint AirBrakes::getSetpoint(TrajectoryPoint currentPosition) +{ + if (chosenTrajectory == nullptr) + return {}; + + float minDistance = std::numeric_limits<float>::infinity(); + + uint32_t end = chosenTrajectory->size(); + for (uint32_t ptIndex = lastSelectedPointIndex; ptIndex < end; ptIndex++) + { + float distanceFromCurrentinput = TrajectoryPoint::distanceSquared( + chosenTrajectory->points[ptIndex], currentPosition); + + if (distanceFromCurrentinput < minDistance) + { + minDistance = distanceFromCurrentinput; + lastSelectedPointIndex = ptIndex; + } + } + + return chosenTrajectory->points[lastSelectedPointIndex]; +} + +float AirBrakes::getRho(float z) +{ + return Constants::RHO_0 * expf(-z / Constants::Hn); +} + +float AirBrakes::piStep(TimedTrajectoryPoint currentPosition, + TrajectoryPoint setPoint, float rho) +{ + const float cdMin = getCD(currentPosition, 0); + const float dragMin = getDrag(currentPosition, cdMin, rho); + + const float cdMax = getCD(currentPosition, config.EXTENSION); + const float dragMax = getDrag(currentPosition, cdMax, rho); + + // Get target surface percentage + const float cdRef = getCD(currentPosition, chosenTrajectory->extension); + const float dragRef = getDrag(currentPosition, cdRef, rho); + + // PI update + const float error = currentPosition.vz - setPoint.vz; + const float dragPi = + pi.antiWindUp(pi.update(error) + dragRef, dragMin, dragMax); + + return dragPi; +} + +float AirBrakes::getSurface(const TimedTrajectoryPoint ¤tPosition, + float rho, float targetDrag) +{ + float bestDDrag = std::numeric_limits<float>::infinity(); + float bestSurface = 0; + + // TODO: Drags are monotone, here the algorithm can be more efficient + for (uint8_t step = 0; step < config.DRAG_STEPS; step++) + { + float surface = (step / (config.DRAG_STEPS - 1)) * config.SURFACE; + + float extension = getExtension(surface); + float cd = getCD(currentPosition, extension); + float drag = getDrag(currentPosition, cd, rho); + float dDrag = abs(targetDrag - drag); + + if (dDrag < bestDDrag) + { + bestDDrag = dDrag; + bestSurface = surface; + } + } + + return bestSurface; +} + +float AirBrakes::getMach(TimedTrajectoryPoint currentPosition) +{ + return currentPosition.vMod / + (Constants::CO + Constants::ALPHA * currentPosition.z); +} + +float AirBrakes::getExtension(float surface) +{ + // clang-format off + return + config.EXT_POL_1 * powf(surface, 4) + + config.EXT_POL_2 * powf(surface, 3) + + config.EXT_POL_3 * powf(surface, 2) + + config.EXT_POL_4 * surface; + // clang-format on +} + +float AirBrakes::getCD(TimedTrajectoryPoint currentPosition, float extension) +{ + const float mach1 = currentPosition.getMac(); + const float mach2 = powf(mach1, 2); + const float mach3 = powf(mach1, 3); + const float mach4 = powf(mach1, 4); + const float mach5 = powf(mach1, 5); + const float mach6 = powf(mach1, 6); + + const float extension2 = powf(extension, 2); + + // clang-format off + return + config.N000 + + config.N100 * mach1 + + config.N200 * mach2 + + config.N300 * mach3 + + config.N400 * mach4 + + config.N500 * mach5 + + config.N600 * mach6 + + config.N010 * extension + + config.N020 * extension2 + + config.N110 * extension * mach1 + + config.N120 * extension2 * mach1 + + config.N210 * extension * mach2 + + config.N220 * extension2 * mach2 + + config.N310 * extension * mach3 + + config.N320 * extension2 * mach3 + + config.N410 * extension * mach4 + + config.N420 * extension2 * mach4 + + config.N510 * extension * mach5 + + config.N520 * extension2 * mach5 + + config.N001 * currentPosition.z; + // clang-format on +} + +float AirBrakes::getDrag(TimedTrajectoryPoint currentPosition, float cd, + float rho) +{ + return 0.5 * rho * config.S0 * cd * currentPosition.vz * + currentPosition.vMod; +} + +} // namespace Boardcore diff --git a/src/shared/algorithms/AirBrakes/AirBrakes.h b/src/shared/algorithms/AirBrakes/AirBrakes.h new file mode 100644 index 0000000000000000000000000000000000000000..b8d7d8b3c4bbc8cbb3411924934295f3710232a8 --- /dev/null +++ b/src/shared/algorithms/AirBrakes/AirBrakes.h @@ -0,0 +1,153 @@ +/* Copyright (c) 2021-2022 Skyward Experimental Rocketry + * Author: Vincenzo Santomarco, Alberto Nidasio + * + * 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 <actuators/Servo/Servo.h> +#include <algorithms/Algorithm.h> +#include <algorithms/PIController.h> + +#include <functional> +#include <vector> + +#include "AirBrakesConfig.h" +#include "AirBrakesData.h" +#include "TrajectorySet.h" + +namespace Boardcore +{ + +class AirBrakes : public Algorithm +{ +public: + AirBrakes(std::function<TimedTrajectoryPoint()> getCurrentPosition, + TrajectorySet &trajectorySet, const AirBrakesConfig &config, + std::function<void(float)> setActuator); + + bool init() override; + + /** + * @brief This method chooses the trajectory the rocket will follow and + * starts the algorithm. + */ + void begin(); + + /** + * @brief Looks for nearest point in the current chosen trajectory and moves + * the airbraks according to the current rocket speed and the prediction. + */ + void step() override; + +private: + /** + * @brief Searched all the trajectories and find the neares point to the + * given position. The trajectory of this point is the one choosen. + */ + void chooseTrajectory(TrajectoryPoint currentPosition); + + /** + * @brief Searches, in the choosen trajectory, the point neares to the given + * one. This method considers the Euclidean distance between altitude and + * vertical speed. + */ + TrajectoryPoint getSetpoint(TrajectoryPoint currentPosition); + + /** + * @brief Returns the air density at the current altitude using the basic + * atmosphere model. + * + * @param z The current altitude [m]. + * @return The density of air according to current altitude [Kg/m^3] + */ + float getRho(float z); + + /** + * @brief Update PI to compute the target drag froce. + * + * @returns Target drag force to generate [N]. + */ + float piStep(TimedTrajectoryPoint currentPosition, + TrajectoryPoint reference, float rho); + + /** + * @brief Compute the necessary airbrakes surface to match the + * given drag force from the Pid as closely as possible. + * + * @param currentPosition Current rocket position. + * @param rho Air density [kg/m^2]. + * @param drag Target drag force. + * @return AirBrakes surface [m]; + */ + float getSurface(const TimedTrajectoryPoint ¤tPosition, float rho, + float drag); + + /** + * @brief Computes the speed in Mach unit for the given position. + * + * @return Mach speed [M]. + */ + float getMach(TimedTrajectoryPoint currentPosition); + + /** + * @brief Computes the airbrakes extension given the desired area. + * + * @param surface Desired airbrakes surface [m^2]. + * @return The radial extension [m]. + */ + float getExtension(float surface); + + /** + * @brief Returns the coefficient of drag for the airbrakes at the given + * position and with the given extension. + * + * @param currentPosition Current rocket position. + * @param extension AirBrakes extension [m]. + * @return The coefficient drag [1]. + */ + float getCD(TimedTrajectoryPoint currentPosition, float extension); + + /** + * @brief Return the drag generated from the AirBrakes in the given + * conditions. + * + * @param currentPosition Current position of the rocket. + * @param cd Coefficient of drag [1]. + * @param rho Air density [kg/m^2]. + * @return Generated drag [N]. + */ + float getDrag(TimedTrajectoryPoint currentPosition, float cd, float rho); + +private: + std::function<TimedTrajectoryPoint()> getCurrentPosition; + TrajectorySet &trajectorySet; + const AirBrakesConfig &config; + std::function<void(float)> setActuator; + + TimedTrajectoryPoint lastPosition; + uint32_t lastSelectedPointIndex = 0; + + PIController pi; + + Trajectory *chosenTrajectory = nullptr; +}; + +} // namespace Boardcore diff --git a/src/shared/algorithms/AirBrakes/AirBrakesConfig.h b/src/shared/algorithms/AirBrakes/AirBrakesConfig.h new file mode 100644 index 0000000000000000000000000000000000000000..8294310a556dceaaef69f17e86bd056b5997e6e7 --- /dev/null +++ b/src/shared/algorithms/AirBrakes/AirBrakesConfig.h @@ -0,0 +1,69 @@ +/* Copyright (c) 2022 Skyward Experimental Rocketry + * Author: Alberto Nidasio + * + * 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 + +namespace Boardcore +{ + +struct AirBrakesConfig +{ + // Coefficient of drag coefficients. + float N000; + float N100; + float N200; + float N300; + float N400; + float N500; + float N600; + float N010; + float N020; + float N110; + float N120; + float N210; + float N220; + float N310; + float N320; + float N410; + float N420; + float N510; + float N520; + float N001; + + // Aibrakes extension. + float EXTENSION; ///< [m] + uint8_t DRAG_STEPS; + float EXT_POL_1; + float EXT_POL_2; + float EXT_POL_3; + float EXT_POL_4; + + float S0; ///< Rocket surface [m^2] + float SURFACE; ///< AirBrakes max surface [m^2] + + // PI parameters + float KP; + float KI; + float TS; +}; + +} // namespace Boardcore diff --git a/src/shared/algorithms/AirBrakes/AirBrakesData.h b/src/shared/algorithms/AirBrakes/AirBrakesData.h new file mode 100644 index 0000000000000000000000000000000000000000..1e9ee5c9f152a46731c4379c55d9f8c33e322cb8 --- /dev/null +++ b/src/shared/algorithms/AirBrakes/AirBrakesData.h @@ -0,0 +1,41 @@ +/* Copyright (c) 2021-2022 Skyward Experimental Rocketry + * Author: Vincenzo Santomarco, Alberto Nidasio + * + * 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 <stdint.h> + +#include <iostream> + +namespace Boardcore +{ + +struct AirBrakesChosenTrajectory +{ + uint8_t trajectory; + + static std::string header() { return "trajectory\n"; } + + void print(std::ostream& os) const { os << (int)trajectory << "\n"; } +}; + +} // namespace Boardcore diff --git a/src/shared/algorithms/AirBrakes/Trajectory.h b/src/shared/algorithms/AirBrakes/Trajectory.h new file mode 100644 index 0000000000000000000000000000000000000000..0f8d1774089ad6ca215bba360f633dc31deaab0e --- /dev/null +++ b/src/shared/algorithms/AirBrakes/Trajectory.h @@ -0,0 +1,45 @@ +/* Copyright (c) 2021-2022 Skyward Experimental Rocketry + * Author: Vincenzo Santomarco, Alberto Nidasio + * + * 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 "TrajectoryPoint.h" + +namespace Boardcore +{ + +class Trajectory +{ +public: + float extension; ///< AirBrakes target extension for this trajectory [m]. + TrajectoryPoint *points; + uint16_t trjSize; + + Trajectory(float extension, TrajectoryPoint points[], uint16_t trjSize) + : extension(extension), points(points), trjSize(trjSize) + { + } + + uint32_t size() { return trjSize; } +}; + +} // namespace Boardcore diff --git a/src/shared/algorithms/AirBrakes/TrajectoryPoint.h b/src/shared/algorithms/AirBrakes/TrajectoryPoint.h new file mode 100644 index 0000000000000000000000000000000000000000..18e880d67efeddd34fc3456228392b6f184da7b7 --- /dev/null +++ b/src/shared/algorithms/AirBrakes/TrajectoryPoint.h @@ -0,0 +1,89 @@ +/* Copyright (c) 2021-2022 Skyward Experimental Rocketry + * Author: Vincenzo Santomarco, Alberto Nidasio + * + * 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 <algorithms/NAS/NASState.h> +#include <math.h> +#include <utils/Constants.h> + +#include <Eigen/Eigen> + +namespace Boardcore +{ + +class TrajectoryPoint +{ +public: + float z; ///< Vertical position [m]. + float vz; ///< Vertical velocity [m/s]. + + TrajectoryPoint() : TrajectoryPoint(0, 0) {} + + TrajectoryPoint(float z, float vz) : z(z), vz(vz) {} + + /** + * @brief Returns the distance squared between the two points. + */ + static float distanceSquared(TrajectoryPoint a, TrajectoryPoint b) + { + return powf(a.z - b.z, 2) + powf(a.vz - b.vz, 2); + } + + /** + * @brief Returns the distance in height between the two given points. + */ + static float zDistance(TrajectoryPoint a, TrajectoryPoint b) + { + return abs(a.z - b.z); + } + + /** + * @brief Returns the distance in vertical speed between the two points. + */ + static float vzDistance(TrajectoryPoint a, TrajectoryPoint b) + { + return abs(a.vz - b.vz); + } +}; + +/** + * @brief Trajectory point with timestamp and velocity module. + */ +class TimedTrajectoryPoint : public TrajectoryPoint +{ +public: + uint64_t timestamp; + float vMod; + + TimedTrajectoryPoint() : TrajectoryPoint(), timestamp(0), vMod(0) {} + + explicit TimedTrajectoryPoint(NASState state) + : TrajectoryPoint(-state.d, -state.vn), timestamp(state.timestamp), + vMod(Eigen::Vector3f{state.vn, state.ve, state.vd}.norm()) + { + } + + float getMac() { return vMod / (Constants::CO + Constants::ALPHA * z); } +}; + +} // namespace Boardcore diff --git a/src/shared/algorithms/AirBrakes/TrajectorySet.h b/src/shared/algorithms/AirBrakes/TrajectorySet.h new file mode 100644 index 0000000000000000000000000000000000000000..b720af10fd1379062a566590cb77f8a9a94c4d29 --- /dev/null +++ b/src/shared/algorithms/AirBrakes/TrajectorySet.h @@ -0,0 +1,44 @@ +/* Copyright (c) 2021-2022 Skyward Experimental Rocketry + * Author: Vincenzo Santomarco, Alberto Nidasio + * + * 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 "Trajectory.h" + +namespace Boardcore +{ + +class TrajectorySet +{ +public: + Trajectory* trajectories; + uint16_t trjSize; + + TrajectorySet(Trajectory trajectories[], uint16_t trjSize) + : trajectories(trajectories), trjSize(trjSize) + { + } + + uint32_t length() { return trjSize; } +}; + +} // namespace Boardcore diff --git a/src/shared/algorithms/Algorithm.h b/src/shared/algorithms/Algorithm.h index 56d31830cdc7218ecd795ab34e003e57261a13d8..441f9116a221724878630c89760dda8b2ef2c4f6 100644 --- a/src/shared/algorithms/Algorithm.h +++ b/src/shared/algorithms/Algorithm.h @@ -53,9 +53,7 @@ public: void update() { if (running) - { step(); - } } protected: diff --git a/src/shared/algorithms/PID.h b/src/shared/algorithms/PIController.h similarity index 71% rename from src/shared/algorithms/PID.h rename to src/shared/algorithms/PIController.h index 5f460f4381ee7e9e9e9aa16886dda6850ca620b6..c30e3e4099eeb9bf3b0bb55400e91cf394f34dd2 100644 --- a/src/shared/algorithms/PID.h +++ b/src/shared/algorithms/PIController.h @@ -34,9 +34,9 @@ class PIController { public: - PIController(double Kp, double Ki, double Ts = 1, - double uMin = -std::numeric_limits<double>::infinity(), - double uMax = std::numeric_limits<double>::infinity()) + PIController(float Kp, float Ki, float Ts = 1, + float uMin = -std::numeric_limits<float>::infinity(), + float uMax = std::numeric_limits<float>::infinity()) : Kp(Kp), Ki(Ki), Ts(Ts), uMin(uMin), uMax(uMax) { } @@ -44,26 +44,23 @@ public: /** * @brief Update the PI internal state. * */ - double update(double error) + float update(float error) { - - lastP = Kp * error; - if (!saturation) - { i = i + Ki * Ts * error; - } - double u = lastP + i; + float u = Kp * error + i; lastOutput = antiWindUp(u); return lastOutput; } + float antiWindUp(float u) { return antiWindUp(u, uMin, uMax); } + /** * @brief Anti-windup mechanism. */ - double antiWindUp(double u) + float antiWindUp(float u, float uMin, float uMax) { if (u < uMin) { @@ -83,23 +80,20 @@ public: return u; } - double getI() { return i; } - - double getLastP() { return lastP; } + float getI() { return i; } - double getLastOutput() { return lastOutput; } + float getLastOutput() { return lastOutput; } bool isSaturated() { return saturation; } - double Kp; // Proportional factor. - double Ki; // Integral factor. - double Ts; // Sampling period. - double uMin, uMax; // Anti-windup limits. + float Kp; // Proportional factor. + float Ki; // Integral factor. + float Ts; // Sampling period. + float uMin, uMax; // Anti-windup limits. private: - double i = 0; // Integral contribution. - double lastP = 0; // Last computer proportional contribution. - double lastOutput; // Last computed controller output. + float i = 0; // Integral contribution. + float lastOutput; // Last computed controller output. bool saturation = false; }; diff --git a/src/shared/utils/AeroUtils/AeroUtils.h b/src/shared/utils/AeroUtils/AeroUtils.h index 80abb8dac650fc6054e359b34e65442bf1402d41..19e3a5a6bdd6f00bef4825bba4cd2b09667bf401 100644 --- a/src/shared/utils/AeroUtils/AeroUtils.h +++ b/src/shared/utils/AeroUtils/AeroUtils.h @@ -36,7 +36,7 @@ namespace Aeroutils * given pressure, using International Standard Atmosphere model. * * @warning This function is valid for altitudes below 11000 meters above sea - * level + * level. * @warning This function provides a relative altitude from the reference * altitude. It does not provide altitude above mean sea level unless the * reference is, in fact, the sea level. diff --git a/src/shared/utils/Constants.h b/src/shared/utils/Constants.h index ddc1e810901159f6b92d95041a8a3606dd8ef939..6f8aaa90e9f80f266c4f26e1910776b1df3bc4ea 100644 --- a/src/shared/utils/Constants.h +++ b/src/shared/utils/Constants.h @@ -39,6 +39,11 @@ static constexpr float R = 287.05f; // Air gas constant [J/Kg/K] static constexpr float n = g / (R * a); static constexpr float nInv = (R * a) / g; +static constexpr float CO = 340.3; // Sound speed at ground altitude [m/s] +static constexpr float ALPHA = -3.871e-3; // Sound speed gradient [1/s] +static constexpr float RHO_0 = 1.225; // Air density at sea level [kg/m^3] +static constexpr float Hn = 10400.0; // Scale height [m] + static constexpr const float MSL_PRESSURE = 101325.0f; // [Pa] static constexpr const float MSL_TEMPERATURE = 288.15f; // [Kelvin] diff --git a/src/tests/algorithms/Kalman/test-kalman-benchmark.cpp b/src/tests/algorithms/Kalman/test-kalman-benchmark.cpp index d690705b8d795c7e5904f7063746f2911cc42a20..52ca7e81c5ea91644604209d62d87c177f02ca6f 100644 --- a/src/tests/algorithms/Kalman/test-kalman-benchmark.cpp +++ b/src/tests/algorithms/Kalman/test-kalman-benchmark.cpp @@ -88,8 +88,6 @@ int main() { float time; // Current time as read from csv file float T; // Time elapsed between last sample and current one - uint64_t tick1; - uint64_t tick2; time = TIME[i]; T = time - lastTime; @@ -100,15 +98,11 @@ int main() y(0) = INPUT[i]; - tick1 = TimestampTimer::getTimestamp(); - filter.predict(F); if (!filter.correct(y)) printf("Correction failed at iteration : %u \n", i); - tick2 = TimestampTimer::getTimestamp(); - lastTime = time; if (filter.getState()(1) < 0 && !apogeeDetected)