Skyward boardcore
Loading...
Searching...
No Matches
MEA.cpp
Go to the documentation of this file.
1/* Copyright (c) 2024 Skyward Experimental Rocketry
2 * Author: Davide Mor
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 "MEA.h"
24
26
27using namespace Boardcore;
28using namespace Eigen;
29
30MEA::Step::Step(float mainValveOpen) : mainValveOpen{mainValveOpen} {}
31
33{
34 withCCPressure(ccPressure.pressure);
35}
36
37void MEA::Step::withCCPressure(float ccPressure)
38{
39 this->ccPressure = ccPressure;
40 hasCCPressure = true;
41}
42
44{
45 withAcceleration(static_cast<Eigen::Vector<float, 3>>(acceleration));
46}
47
48void MEA::Step::withAcceleration(Eigen::Vector<float, 3> acceleration)
49{
50 this->acceleration = acceleration;
51 hasAcceleration = true;
52}
53
54void MEA::Step::withSpeedAndAlt(float verticalSpeed, float mslAltitude)
55{
56 this->verticalSpeed = verticalSpeed;
57 this->mslAltitude = mslAltitude;
58 hasSpeedAndAlt = true;
59}
60
61MEA::MEA(const Config& config)
62{
63 reset(config);
64 updateState();
65}
66
67void MEA::update(const Step& step)
68{
69 // First run the prediction step
70 predict(step);
71
72 // Run cc pressure correction
73 correctBaro(step);
74
75 // Compute applied force/mach/CD/rho
76 computeForce(step);
77
78 // Run accelerometer correction
79 correctAccel(step);
80
81 // Compute current mass
82 computeMass();
83
84 // Run apogee prediction
85 computeApogee(step);
86
87 // Finally update state
88 updateState();
89}
90
91MEAState MEA::getState() { return state; }
92
93void MEA::reset(const Config& config)
94{
95 F = config.F;
96 Q = config.Q;
97 G = config.G;
98 baroH = config.baroH;
99 baroR = config.baroR;
100 P = config.P;
101 x = {0, 0, config.initialMass};
102 mass = config.initialMass;
103 accelThresh = config.accelThresh;
104 speedThresh = config.speedThresh;
105 Kt = config.Kt;
106 alpha = config.alpha;
107 c = config.c;
108 coeffs = config.coeffs;
109 crossSection = config.crossSection;
110 ae = config.ae;
111 p0 = config.p0;
112 minMass = config.minMass;
113 maxMass = config.maxMass;
114 cdCorrectionFactor = config.cdCorrectionFactor;
115}
116
117void MEA::predict(const Step& step)
118{
119 x = F * x + G * step.mainValveOpen;
120 P = F * P * F.transpose() + Q;
121}
122
123void MEA::computeForce(const Step& step)
124{
125 if (!step.hasSpeedAndAlt)
126 return;
127
128 // NOTE: Here we assume that verticalSpeed roughly equals the total speed,
129 // so that we don't depend on N/E speed components, which can be quite
130 // unreliable in case of no GPS fix or during powered ascent
131 mach = Aeroutils::computeMach(-step.mslAltitude, step.verticalSpeed,
132 Constants::MSL_TEMPERATURE);
133
134 cd = Aeroutils::computeCd(coeffs, mach);
135 rho = Aeroutils::computeRho(-step.mslAltitude, Constants::MSL_TEMPERATURE);
136
137 // Dynamic pressure
138 q = 0.5f * rho * (step.verticalSpeed * step.verticalSpeed);
139
140 // Aerodynamic force component
141 force = q * crossSection * (cd * cdCorrectionFactor);
142
143 if (step.mslAltitude > 800)
144 {
145 // At high altitudes we need to compensate for low external pressure
146
147 // External pressure
148 float p = Aeroutils::relPressure(step.mslAltitude);
149 force -= (p0 - p) * ae;
150 }
151}
152
153void MEA::correctBaro(const Step& step)
154{
155 if (!step.hasCCPressure)
156 return;
157
158 float S = baroH * P * baroH.transpose() + baroR;
159
160 // If not invertible, do not invert it
161 if (S < 1e-3)
162 return;
163
164 Matrix<float, 3, 1> K = (P * baroH.transpose()) / S;
165
166 P = (Matrix<float, 3, 3>::Identity() - K * baroH) * P;
167 x = x + K * (step.ccPressure - baroH * x);
168}
169
170void MEA::correctAccel(const Step& step)
171{
172 if (!step.hasAcceleration || !step.hasSpeedAndAlt)
173 return;
174
175 // Do not correct at low speed/acceleration
176 if (step.acceleration.norm() < accelThresh ||
177 step.verticalSpeed < speedThresh)
178 {
179 return;
180 }
181
182 float y = (Kt * (float)(baroH * x) - force) / x(2);
183
184 Matrix<float, 1, 3> accelH =
185 Vector<float, 3>{Kt * baroH(0) / x(2), Kt * baroH(1) / x(2),
186 -(Kt * (float)(baroH * x) - force) / (x(2) * x(2))}
187 .transpose();
188
189 float accelR = alpha * q + c;
190
191 float S = accelH * P * accelH.transpose() + accelR;
192
193 // If not invertible, do not invert it
194 if (S < 1e-3)
195 return;
196
197 Matrix<float, 3, 1> K = (P * accelH.transpose()) / S;
198
199 P = (Matrix<float, 3, 3>::Identity() - K * accelH) * P;
200 x = x + K * (step.acceleration.x() - y);
201}
202
203void MEA::computeMass()
204{
205 // Clamp the used mass, so that we don't use bogus values in case the filter
206 // fails BAD
207 mass = std::max(std::min(x(2), maxMass), minMass);
208}
209
210void MEA::computeApogee(const Step& step)
211{
212 if (!step.hasSpeedAndAlt)
213 return;
214
215 // Simplified massive formula for apogee estimation.
216 // Warning: log1p(x) = log(1 + x)
217 float temp = ((rho * cd * crossSection) / mass);
218 apogee = step.mslAltitude +
219 1 / temp *
220 log1p(0.5 * (step.verticalSpeed * step.verticalSpeed * temp) /
221 Constants::g);
222}
223
224void MEA::updateState()
225{
227
228 state.x0 = x(0);
229 state.x1 = x(1);
230 state.x2 = x(2);
231
232 state.estimatedMass = mass;
233 state.estimatedPressure = baroH * x;
234 state.estimatedApogee = apogee;
235 state.estimatedForce = force;
236}
MEA(const Config &config)
Definition MEA.cpp:61
void update(const Step &step)
Definition MEA.cpp:67
void reset(const Config &config)
Resets the algorithm with the given configuration.
Definition MEA.cpp:93
MEAState getState()
Definition MEA.cpp:91
float computeMach(float d, float vtot, float t0)
Computes the mach relative to the speed at a certain altitude.
float computeCd(const AerodynamicCoeff &coeff, float mach)
Computes the CD from aerodynamic coefficients and mach.
float relPressure(float altitude, float pressureRef, float temperatureRef)
Returns the pressure given the altitude with respect to a reference pressure and temperature,...
Definition AeroUtils.cpp:41
float computeRho(float d, float t0)
Computes the rho (air density) of air at the given altitude.
Definition AeroUtils.cpp:86
uint64_t getTimestamp()
Returns the current timer value in microseconds.
Driver for the VN100S IMU.
Structure to handle accelerometer data.
Definition SensorData.h:119
Aeroutils::AerodynamicCoeff coeffs
Definition MEA.h:59
float cdCorrectionFactor
Definition MEA.h:68
Eigen::Vector< float, 3 > G
Definition MEA.h:41
Eigen::Matrix< float, 3, 3 > Q
Definition MEA.h:40
Eigen::Matrix< float, 3, 3 > F
Definition MEA.h:39
Eigen::Matrix< float, 3, 3 > P
Definition MEA.h:46
Eigen::Vector< float, 3 > baroH
Definition MEA.h:43
void withCCPressure(PressureData ccPressure)
Definition MEA.cpp:32
void withSpeedAndAlt(float verticalSpeed, float mslAltitude)
Definition MEA.cpp:54
void withAcceleration(AccelerometerData acceleration)
Definition MEA.cpp:43
Step(float mainValveOpen)
Definition MEA.cpp:30
float x0
first kalman state
Definition MEAData.h:41
float estimatedMass
Estimated rocket mass [kg].
Definition MEAData.h:37
uint64_t timestamp
Definition MEAData.h:34
float estimatedPressure
Estimated pressure in combustion chamber [Pa].
Definition MEAData.h:36
float x2
third kalman state representing the mass
Definition MEAData.h:43
float estimatedApogee
Estimated apogee in msl [m].
Definition MEAData.h:38
float estimatedForce
Estimated drag force [N].
Definition MEAData.h:39
float x1
second kalman state
Definition MEAData.h:42