Skyward boardcore
Loading...
Searching...
No Matches
AirBrakesPI.cpp
Go to the documentation of this file.
1/* Copyright (c) 2021-2022 Skyward Experimental Rocketry
2 * Authors: Vincenzo Santomarco, Alberto Nidasio, Emilio Corigliano
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#include "AirBrakesPI.h"
24
25#include <logger/Logger.h>
26#include <math.h>
27#include <utils/Constants.h>
28
29#include <limits>
30
32#include "utils/Debug.h"
33
34using namespace std;
35
36namespace Boardcore
37{
38
40 std::function<TimedTrajectoryPoint()> getCurrentPosition,
41 const TrajectorySet& trajectorySet, const AirBrakesPIConfig& config,
42 std::function<void(float)> setActuator)
43 : getCurrentPosition(getCurrentPosition), config(config),
44 setActuator(setActuator), pi(config.KP, config.KI, config.TS),
45 trajectorySet(trajectorySet)
46{
47}
48
49bool AirBrakesPI::init() { return true; }
50
52{
53 if (running)
54 return;
55
56 lastPosition = getCurrentPosition();
57 chooseTrajectory(lastPosition);
59}
60
62{
63 auto currentPosition = getCurrentPosition();
64
65 // Do nothing if we have no new data
66 if (lastPosition.timestamp >= currentPosition.timestamp)
67 return;
68
69 lastPosition = currentPosition;
70
71 auto setPoint = getSetpoint(currentPosition);
72 float rho = getRho(currentPosition.z);
73
74 float targetDrag = piStep(currentPosition, setPoint, rho);
75 float surface = getSurface(currentPosition, rho, targetDrag);
76 setActuator(surface / config.SURFACE);
77}
78
79float AirBrakesPI::getRho(float z)
80{
81 return Constants::RHO_0 * expf(-z / Constants::Hn);
82}
83
84float AirBrakesPI::getSurface(const TimedTrajectoryPoint& currentPosition,
85 float rho, float targetDrag)
86{
87 float bestDDrag = numeric_limits<float>::infinity();
88 float bestSurface = 0;
89
90 // TODO: Drags are monotone, here the algorithm can be more efficient
91 for (uint8_t step = 0; step < config.DRAG_STEPS; step++)
92 {
93 float surface = (step / (config.DRAG_STEPS - 1)) * config.SURFACE;
94
95 float extension = getExtension(surface);
96 float cd = getCD(currentPosition, extension);
97 float drag = getDrag(currentPosition, cd, rho);
98 float dDrag = abs(targetDrag - drag);
99
100 if (dDrag < bestDDrag)
101 {
102 bestDDrag = dDrag;
103 bestSurface = surface;
104 }
105 }
106
107 return bestSurface;
108}
109
110float AirBrakesPI::getExtension(float surface)
111{
112 // clang-format off
113 return
114 config.EXT_POL_1 * powf(surface, 4) +
115 config.EXT_POL_2 * powf(surface, 3) +
116 config.EXT_POL_3 * powf(surface, 2) +
117 config.EXT_POL_4 * surface;
118 // clang-format on
119}
120
121float AirBrakesPI::getCD(TimedTrajectoryPoint currentPosition, float extension)
122{
123 const float mach1 = currentPosition.getMac();
124 const float mach2 = powf(mach1, 2);
125 const float mach3 = powf(mach1, 3);
126 const float mach4 = powf(mach1, 4);
127 const float mach5 = powf(mach1, 5);
128 const float mach6 = powf(mach1, 6);
129
130 const float extension2 = powf(extension, 2);
131
132 // clang-format off
133 return
134 config.N000 +
135 config.N100 * mach1 +
136 config.N200 * mach2 +
137 config.N300 * mach3 +
138 config.N400 * mach4 +
139 config.N500 * mach5 +
140 config.N600 * mach6 +
141 config.N010 * extension +
142 config.N020 * extension2 +
143 config.N110 * extension * mach1 +
144 config.N120 * extension2 * mach1 +
145 config.N210 * extension * mach2 +
146 config.N220 * extension2 * mach2 +
147 config.N310 * extension * mach3 +
148 config.N320 * extension2 * mach3 +
149 config.N410 * extension * mach4 +
150 config.N420 * extension2 * mach4 +
151 config.N510 * extension * mach5 +
152 config.N520 * extension2 * mach5 +
153 config.N001 * currentPosition.z;
154 // clang-format on
155}
156
157float AirBrakesPI::getDrag(TimedTrajectoryPoint currentPosition, float cd,
158 float rho)
159{
160 return 0.5 * rho * config.S0 * cd * currentPosition.vz *
161 currentPosition.vMod;
162}
163
164void AirBrakesPI::chooseTrajectory(TrajectoryPoint currentPosition)
165{
166 float minDistance = numeric_limits<float>::infinity();
167 uint8_t trjIndexMin = trajectorySet.length() / 2;
168
169 for (uint8_t trjIndex = 0; trjIndex < trajectorySet.length(); trjIndex++)
170 {
171 Trajectory& trajectory = trajectorySet.trajectories[trjIndex];
172
173 for (uint32_t ptIndex = 0; ptIndex < trajectory.size(); ptIndex++)
174 {
175 TrajectoryPoint point = trajectory.points[ptIndex];
176 float distance =
177 TrajectoryPoint::distanceSquared(point, currentPosition);
178
179 if (distance < minDistance)
180 {
181 minDistance = distance;
182 trjIndexMin = trjIndex;
183 lastSelectedPointIndex = ptIndex;
184 chosenTrajectory = &trajectory;
185 }
186 }
187 }
188
189 chosenTrajectory = &(trajectorySet.trajectories[trjIndexMin]);
190}
191
192TrajectoryPoint AirBrakesPI::getSetpoint(TrajectoryPoint currentPosition)
193{
194 if (chosenTrajectory == nullptr)
195 return {};
196
197 float minDistance = numeric_limits<float>::infinity();
198
199 uint32_t end = chosenTrajectory->size();
200 for (uint32_t ptIndex = lastSelectedPointIndex; ptIndex < end; ptIndex++)
201 {
202 float distanceFromCurrentInput =
203 abs(chosenTrajectory->points[ptIndex].z - currentPosition.z);
204
205 if (distanceFromCurrentInput < minDistance)
206 {
207 minDistance = distanceFromCurrentInput;
208 lastSelectedPointIndex = ptIndex;
209 }
210 }
211
212 return chosenTrajectory->points[lastSelectedPointIndex];
213}
214
215float AirBrakesPI::piStep(TimedTrajectoryPoint currentPosition,
216 TrajectoryPoint setPoint, float rho)
217{
218 const float cdMin = getCD(currentPosition, 0);
219 const float dragMin = getDrag(currentPosition, cdMin, rho);
220
221 const float cdMax = getCD(currentPosition, config.EXTENSION);
222 const float dragMax = getDrag(currentPosition, cdMax, rho);
223
224 // Get target surface percentage
225 const float cdRef = getCD(currentPosition, chosenTrajectory->extension);
226 const float dragRef = getDrag(currentPosition, cdRef, rho);
227
228 // PI update
229 const float error = currentPosition.vz - setPoint.vz;
230 const float dragPi =
231 pi.antiWindUp(pi.update(error) + dragRef, dragMin, dragMax);
232
233 return dragPi;
234}
235
236} // namespace Boardcore
void begin()
This method chooses the trajectory the rocket will follow and starts the algorithm.
bool init() override
Initializes the Algorithm object, must be called as soon as the object is created.
void step() override
Looks for nearest point in the current chosen trajectory and moves the airbraks according to the curr...
AirBrakesPI(std::function< TimedTrajectoryPoint()> getCurrentPosition, const TrajectorySet &trajectorySet, const AirBrakesPIConfig &config, std::function< void(float)> setActuator)
void begin()
Starts the execution of the algorithm and set the running flag to true.
Definition Algorithm.h:42
void end()
Terminates the algorithm's execution and sets the running flag to false.
Definition Algorithm.h:48
std::atomic< bool > running
Definition Algorithm.h:68
float antiWindUp(float u)
float update(float error)
Update the PI internal state.
Trajectory point with timestamp and velocity module.
TrajectoryPoint * points
Definition Trajectory.h:34
float extension
AirBrakes target extension for this trajectory [m].
Definition Trajectory.h:33
float z
Vertical position [m].
static float distanceSquared(TrajectoryPoint a, TrajectoryPoint b)
Returns the distance squared between the two points.
uint32_t length() const
This file includes all the types the logdecoder script will decode.
Definition WIZ5500.h:318
float S0
Rocket surface [m^2].
float SURFACE
AirBrakes max surface [m^2].