27 float accelFilterAlpha,
28 float minimumClimbVelocity_mps)
29 : vve_(velocityEstimator),
30 filteredDecel_mps2_(0.0F),
31 alpha_(clamp(accelFilterAlpha, 0.0F, 1.0F)),
32 minimumClimbVelocity_mps_(minimumClimbVelocity_mps),
42 const uint32_t currentTimestamp = vve_.getTimestamp();
43 const float velocity = vve_.getEstimatedVelocity();
44 const float acceleration = vve_.getInertialVerticalAcceleration();
47 float decelSample = std::max(0.0F, -acceleration);
49 if (currentTimestamp > lastTs_) {
51 const float deltaVelocity_mps = velocity - lastVel_;
52 float estimatedDecel_mps2 = (deltaTime_s > 0.0F) ? std::max(0.0F, -deltaVelocity_mps / deltaTime_s) : 0.0F;
53 decelSample = kOneHalf * (decelSample + estimatedDecel_mps2);
56 filteredDecel_mps2_ = alpha_ * decelSample + (1.0F - alpha_) * filteredDecel_mps2_;
58 if (velocity > minimumClimbVelocity_mps_ && filteredDecel_mps2_ > kMinValidDecel) {
59 tToApogee_ = velocity / filteredDecel_mps2_;
60 predApogeeTs_ = currentTimestamp +
static_cast<uint32_t
>(tToApogee_ * kMillisecondsPerSecond);
62 const float altitude = vve_.getEstimatedAltitude();
63 predApogeeAlt_ = altitude + velocity * tToApogee_ -
64 kOneHalf * filteredDecel_mps2_ * tToApogee_ * tToApogee_;
71 lastTs_ = currentTimestamp;
73 numWarmups_ = std::min(numWarmups_ + 1, kMaxWarmups);
77 const uint32_t currentTimestamp = vve_.getTimestamp();
78 const float velocity = vve_.getEstimatedVelocity();
79 const float acceleration = vve_.getInertialVerticalAcceleration();
81 float kEstimate = 0.0F;
82 if (std::fabs(velocity) > 1.0F) {
83 kEstimate = std::max(0.0F, -(acceleration + kGravity_mps2)) / (velocity * velocity);
86 filteredDecel_mps2_ = alpha_ * kEstimate + (1.0F - alpha_) * filteredDecel_mps2_;
87 const float dragToMassRatio = filteredDecel_mps2_;
89 if (velocity > minimumClimbVelocity_mps_ && dragToMassRatio > kMinValidDecel) {
90 const float terminalVelocity = std::sqrt(kGravity_mps2 / dragToMassRatio);
91 tToApogee_ = (terminalVelocity / kGravity_mps2) * std::atan(velocity / terminalVelocity);
92 const float deltaAltitude = (terminalVelocity * terminalVelocity / (2.0F * kGravity_mps2)) *
93 std::log1p((velocity * velocity) /
94 (terminalVelocity * terminalVelocity));
96 predApogeeTs_ = currentTimestamp +
static_cast<uint32_t
>(tToApogee_ * kMillisecondsPerSecond);
97 predApogeeAlt_ = vve_.getEstimatedAltitude() + deltaAltitude;
103 lastTs_ = currentTimestamp;
107 const uint32_t currentTimestamp_ms = vve_.getTimestamp();
108 const float altitude_m = vve_.getEstimatedAltitude();
109 const float velocity_mps = vve_.getEstimatedVelocity();
110 const float acceleration_mps2 = vve_.getInertialVerticalAcceleration();
112 constexpr size_t kFeatureCount = 10;
115 const std::array<float, kFeatureCount> coeffs = {
127 const float intercept = 308.64734694F;
131 const float decel = std::fabs(acceleration_mps2);
132 const float delta_h_simple = kOneHalf * (velocity_mps * velocity_mps) / decel;
136 const std::array<float, kFeatureCount> inputs = {
141 velocity_mps * velocity_mps,
142 velocity_mps * acceleration_mps2,
143 velocity_mps * delta_h_simple,
144 acceleration_mps2 * acceleration_mps2,
145 acceleration_mps2 * delta_h_simple,
146 delta_h_simple * delta_h_simple,
149 float apogeeRemaining_m = intercept;
150 for (
size_t i = 0; i < kFeatureCount; ++i) {
151 apogeeRemaining_m += coeffs[i] * inputs[i];
156 predApogeeAlt_ = altitude_m + apogeeRemaining_m;
159 tToApogee_ = velocity_mps / decel;
160 predApogeeTs_ = currentTimestamp_ms +
static_cast<uint32_t
>(tToApogee_ * kMillisecondsPerSecond);
164 lastTs_ = currentTimestamp_ms;
165 lastVel_ = velocity_mps;
166 numWarmups_ = std::min(numWarmups_ + 1, kMaxWarmups);
176 const float velocity = vve_.getEstimatedVelocity();
177 const float height = vve_.getEstimatedAltitude();
181 const float kVelocityEpsilon = 0.001F;
182 const float kVelocityScaleForAlpha = 150.0F;
183 const float kAlphaMin = 0.02F;
184 const float kAlphaMax = 0.25F;
185 const float kMinDragCoefficient = 0.00001F;
186 const float kApogeeFactor = 0.5F;
187 const float kBallisticDenominator = 2.0F;
190 if (velocity <= 0.0F)
192 predApogeeAlt_ = height;
198 const float acceleration = vve_.getInertialVerticalAcceleration();
201 const float kMeasured = -(acceleration + kGravity_mps2) /
202 (velocity * velocity + kVelocityEpsilon);
204 if (kMeasured > 0.0F && kMeasured < 1.0F)
206 float alpha = clamp(std::fabs(velocity) / kVelocityScaleForAlpha,
209 currentDragCoefficient_ = (1.0F - alpha) * currentDragCoefficient_ + alpha * kMeasured;
215 if (currentDragCoefficient_ > kMinDragCoefficient)
217 apogee = height + (kApogeeFactor / currentDragCoefficient_) *
218 logf((kGravity_mps2 + currentDragCoefficient_ * velocity * velocity) / kGravity_mps2);
223 apogee = height + (velocity * velocity) /
224 (kBallisticDenominator * kGravity_mps2);
227 predApogeeAlt_ = apogee;
234 const float estimatedVelocity = vve_.getEstimatedVelocity();
235 const float estimatedAltitude = vve_.getEstimatedAltitude();
236 const float inertialAccel = vve_.getInertialVerticalAcceleration();
238 const float kVelocityEpsilon = 0.001F;
239 const float kMinVelocityForDrag = 15.0F;
240 const float kAlpha = 0.05F;
241 const float kMaxDragCoefficient = 0.05F;
242 const float kDt = 0.01F;
243 const int kMaxSimSteps = 500;
246 if (estimatedVelocity <= 0.0F)
248 predApogeeAlt_ = estimatedAltitude;
254 if (estimatedVelocity > kMinVelocityForDrag)
256 const float measuredDrag =
257 -(inertialAccel + kGravity_mps2) / (estimatedVelocity * estimatedVelocity + kVelocityEpsilon);
259 if (measuredDrag > 0.0F && measuredDrag < kMaxDragCoefficient)
261 currentDragCoefficient_ =
262 (1.0F - kAlpha) * currentDragCoefficient_ +
263 kAlpha * measuredDrag;
268 float simAltitude = estimatedAltitude;
269 float simVelocity = estimatedVelocity;
271 for (
int step = 0; step < kMaxSimSteps; step++)
273 const float dragAcceleration = currentDragCoefficient_ * simVelocity * simVelocity;
274 const float totalAcceleration = -kGravity_mps2 - dragAcceleration;
276 simVelocity += totalAcceleration * kDt;
277 simAltitude += simVelocity * kDt;
279 if (simVelocity <= 0.0F)
285 predApogeeAlt_ = simAltitude;