diff --git a/app/other/airbraker/src/lut.cpp b/app/other/airbraker/src/lut.cpp index 6af2eacdf..30d141995 100644 --- a/app/other/airbraker/src/lut.cpp +++ b/app/other/airbraker/src/lut.cpp @@ -68,7 +68,11 @@ float CalcActuatorEffort(float altitude, float velocity) { float z_hat_min = 0; float z_hat_max = 0; boundsLUT(altitude, &z_hat_min, &z_hat_max); - float q = (velocity - z_hat_min) / (z_hat_max - z_hat_min); + const float span = z_hat_max - z_hat_min; + if (span <= 0.0F) { + return 0.0F; + } + float q = (velocity - z_hat_min) / span; if (q > 1) { return 1; } else if (q < 0) { @@ -77,4 +81,4 @@ float CalcActuatorEffort(float altitude, float velocity) { return q; } -} // namespace NModel \ No newline at end of file +} // namespace NModel diff --git a/app/other/airbraker/src/main.cpp b/app/other/airbraker/src/main.cpp index 00119c394..af4a5a8ef 100644 --- a/app/other/airbraker/src/main.cpp +++ b/app/other/airbraker/src/main.cpp @@ -7,12 +7,11 @@ #include "n_storage.hpp" #include "servo.hpp" +#include #include #include #include #include -#include - #include LOG_MODULE_REGISTER(main, CONFIG_APP_AIRBRAKE_LOG_LEVEL); @@ -34,12 +33,8 @@ uint32_t packet_timestamp() { return 0; \ } -NTypes::GyroscopeData unbiasGyro(const NTypes::GyroscopeData &data, const NTypes::GyroscopeData &bias){ - return { - .X = data.X - bias.X, - .Y = data.Y - bias.Y, - .Z = data.Z - bias.Z - }; +NTypes::GyroscopeData unbiasGyro(const NTypes::GyroscopeData &data, const NTypes::GyroscopeData &bias) { + return {.X = data.X - bias.X, .Y = data.Y - bias.Y, .Z = data.Z - bias.Z}; } int main() { @@ -128,7 +123,6 @@ int main() { float altMeters = NModel::AltitudeMetersFromPressureKPa(packet.pressureRaw) - groundLevelASLMeters; float vertical = GetUpAxis(packet.accelRaw); - NTypes::GyroscopeData unbiasedGyro = unbiasGyro(packet.gyro, bias); NModel::FeedGyro(packet.timestamp, unbiasedGyro); NModel::FillPacketWithOrientationMatrix(packet.orientationMatrix); @@ -148,8 +142,6 @@ int main() { NStorage::WriteFlightPacket(i, &packet); - - // Write preboost if needed if (preboostWriteHead < NUM_STORED_PREBOOST_PACKETS) { NStorage::WritePreboostPacket(preboostWriteHead, NPreBoost::GetPreBoostPacketPtr(preboostWriteHead)); @@ -161,7 +153,7 @@ int main() { CancelFlight(); // happy beep for reco team - while(true){ + while (true) { NBuzzer::SetBuzzer(true); k_msleep(200); NBuzzer::SetBuzzer(false); @@ -182,13 +174,12 @@ void CancelFlight() { } bool IsFlightCancelled() { return atomic_get(&flightCancelled) == 1; } - -float GetUpAxis(const NTypes::AccelerometerData &xyz){ - NTypes::AccelerometerData out{0,0,0}; +float GetUpAxis(const NTypes::AccelerometerData &xyz) { + NTypes::AccelerometerData out{0, 0, 0}; RotateIMUVectorToRocketVector(xyz, out); return out.Z; } -void RotateIMUVectorToRocketVector(const NTypes::AccelerometerData &xyz, NTypes::AccelerometerData &out){ +void RotateIMUVectorToRocketVector(const NTypes::AccelerometerData &xyz, NTypes::AccelerometerData &out) { zsl_quat p{.r = 0, .i = xyz.X, .j = xyz.Y, .k = xyz.Z}; // q p q* @@ -202,7 +193,7 @@ void RotateIMUVectorToRocketVector(const NTypes::AccelerometerData &xyz, NTypes: out.Z = output.k; } -void RotateRocketVectorToIMUVector(const NTypes::AccelerometerData &xyz, NTypes::AccelerometerData &out){ +void RotateRocketVectorToIMUVector(const NTypes::AccelerometerData &xyz, NTypes::AccelerometerData &out) { zsl_quat p{.r = 0, .i = xyz.X, .j = xyz.Y, .k = xyz.Z}; // q p q* diff --git a/app/other/airbraker/src/n_model.cpp b/app/other/airbraker/src/n_model.cpp index 029daa093..d6b0f4626 100644 --- a/app/other/airbraker/src/n_model.cpp +++ b/app/other/airbraker/src/n_model.cpp @@ -2,195 +2,265 @@ #include "math/matrix.hpp" #include "n_autocoder_types.h" -#include "quantile_lut_data.h" #include "n_preboost.hpp" +#include "quantile_lut_data.h" #include -namespace NModel -{ -const char* GetMatlabLUTName() -{ - return LUT_NAME; +namespace NModel { +namespace { +constexpr float kCosMaxTilt = 0.8660254037844386F; +constexpr float kDefaultGyroDeltaS = 0.01F; +constexpr float kMaxGyroDeltaS = 0.05F; + +struct Vec3 { + float x; + float y; + float z; +}; + +struct Quaternion { + float w; + float x; + float y; + float z; +}; + +float ClampUnit(float v) { + if (v > 1.0F) { + return 1.0F; + } + if (v < -1.0F) { + return -1.0F; + } + return v; +} + +float Dot3(const Vec3& a, const Vec3& b) { return (a.x * b.x) + (a.y * b.y) + (a.z * b.z); } + +Vec3 Cross3(const Vec3& a, const Vec3& b) { + return { + .x = (a.y * b.z) - (a.z * b.y), + .y = (a.z * b.x) - (a.x * b.z), + .z = (a.x * b.y) - (a.y * b.x), + }; +} + +Quaternion QuaternionMultiply(const Quaternion& lhs, const Quaternion& rhs) { + return { + .w = (lhs.w * rhs.w) - (lhs.x * rhs.x) - (lhs.y * rhs.y) - (lhs.z * rhs.z), + .x = (lhs.w * rhs.x) + (lhs.x * rhs.w) + (lhs.y * rhs.z) - (lhs.z * rhs.y), + .y = (lhs.w * rhs.y) - (lhs.x * rhs.z) + (lhs.y * rhs.w) + (lhs.z * rhs.x), + .z = (lhs.w * rhs.z) + (lhs.x * rhs.y) - (lhs.y * rhs.x) + (lhs.z * rhs.w), + }; +} + +Quaternion NormalizeQuaternion(const Quaternion& q) { + const float normSq = (q.w * q.w) + (q.x * q.x) + (q.y * q.y) + (q.z * q.z); + if (normSq == 0.0F) { + return {1.0F, 0.0F, 0.0F, 0.0F}; + } + + const float invNorm = 1.0F / std::sqrt(normSq); + return { + .w = q.w * invNorm, + .x = q.x * invNorm, + .y = q.y * invNorm, + .z = q.z * invNorm, + }; +} + +Quaternion QuaternionDeltaFromGyro(const NTypes::GyroscopeData& gyro, float deltaSeconds) { + const float rx = gyro.X * deltaSeconds; + const float ry = gyro.Y * deltaSeconds; + const float rz = gyro.Z * deltaSeconds; + const float rotationMagnitudeSq = (rx * rx) + (ry * ry) + (rz * rz); + const float rotationMagnitude = std::sqrt(rotationMagnitudeSq); + + if (rotationMagnitude == 0.0F) { + return {1.0F, 0.0F, 0.0F, 0.0F}; + } + + const float halfAngle = 0.5F * rotationMagnitude; + const float vectorScale = std::sin(halfAngle) / rotationMagnitude; + return { + .w = std::cos(halfAngle), + .x = rx * vectorScale, + .y = ry * vectorScale, + .z = rz * vectorScale, + }; } -const char* GetMatlabLUTDate() -{ - return LUT_CREATION_DATE; + +Vec3 RotateVectorByQuaternion(const Quaternion& q, const Vec3& v) { + const Vec3 u{q.x, q.y, q.z}; + const Vec3 uv = Cross3(u, v); + const Vec3 uuv = Cross3(u, uv); + return { + .x = v.x + (2.0F * ((q.w * uv.x) + uuv.x)), + .y = v.y + (2.0F * ((q.w * uv.y) + uuv.y)), + .z = v.z + (2.0F * ((q.w * uv.z) + uuv.z)), + }; +} + +const Vec3& InitialRocketZAxisInIMUSpace() { + static const Vec3 initial = [] { + NTypes::AccelerometerData zInIMUSpace{}; + RotateRocketVectorToIMUVector({0, 0, 1}, zInIMUSpace); + return Vec3{zInIMUSpace.X, zInIMUSpace.Y, zInIMUSpace.Z}; + }(); + return initial; } +} // namespace + +const char* GetMatlabLUTName() { return LUT_NAME; } +const char* GetMatlabLUTDate() { return LUT_CREATION_DATE; } using StateTransitionT = Matrix<4, 4>; -const StateTransitionT state_transition_matrix{ { // aka F - KALMAN_STATE_TRANSITION_INITIALIZER } }; +const StateTransitionT state_transition_matrix{{// aka F + KALMAN_STATE_TRANSITION_INITIALIZER}}; -const Matrix<2, 4> kalman_output_matrix{ { // aka H - KALMAN_OUTPUT_INITIALIZER } }; -const Matrix<4, 2> kalman_gain{ { KALMAN_GAIN_INITIALIZER } }; +const Matrix<2, 4> kalman_output_matrix{{// aka H + KALMAN_OUTPUT_INITIALIZER}}; +const Matrix<4, 2> kalman_gain{{KALMAN_GAIN_INITIALIZER}}; -static Matrix<4, 1> kalman_state({ KALMAN_INITIAL_STATE_INITIALIZER }); +static Matrix<4, 1> kalman_state({KALMAN_INITIAL_STATE_INITIALIZER}); -static Matrix<2, 1> lastInnovation{ { 0, 0 } }; -static Matrix<3, 3> gyroOrientation = Matrix<3, 3>::Identity(); +static Matrix<2, 1> lastInnovation{{0, 0}}; +static Quaternion gyroOrientation{1.0F, 0.0F, 0.0F, 0.0F}; static bool everWentOutOfBounds = false; Matrix<4, 1> kalmanPredictAndUpdate(const Matrix<4, 1>& state, const float altitudeMeters, - const float verticalAccelerationMS2) -{ - Matrix<2, 1> sensorIn = Matrix<2, 1>::Column({ altitudeMeters, verticalAccelerationMS2 }); + const float verticalAccelerationMS2) { + Matrix<2, 1> sensorIn = Matrix<2, 1>::Column({altitudeMeters, verticalAccelerationMS2}); - // change via physics model - Matrix<4, 1> fx = state_transition_matrix * state; + // change via physics model + Matrix<4, 1> fx = state_transition_matrix * state; - // change via sensors - Matrix<2, 1> innovation = sensorIn - (kalman_output_matrix * fx); - lastInnovation = innovation; + // change via sensors + Matrix<2, 1> innovation = sensorIn - (kalman_output_matrix * fx); + lastInnovation = innovation; - Matrix<4, 1> correction = kalman_gain * innovation; + Matrix<4, 1> correction = kalman_gain * innovation; - return fx + correction; + return fx + correction; } -void FeedKalman(float altitudeMeters, float verticalAccelerationMS2) -{ - kalman_state = kalmanPredictAndUpdate(kalman_state, altitudeMeters, verticalAccelerationMS2); +void FeedKalman(float altitudeMeters, float verticalAccelerationMS2) { + kalman_state = kalmanPredictAndUpdate(kalman_state, altitudeMeters, verticalAccelerationMS2); } -KalmanState LastKalmanState() -{ - return { - .estAltitude = kalman_state.Get(0, 0), - .estVelocity = kalman_state.Get(1, 0), - .estAcceleration = kalman_state.Get(2, 0), - .estBias = kalman_state.Get(3, 0), - }; +KalmanState LastKalmanState() { + return { + .estAltitude = kalman_state.Get(0, 0), + .estVelocity = kalman_state.Get(1, 0), + .estAcceleration = kalman_state.Get(2, 0), + .estBias = kalman_state.Get(3, 0), + }; } #define CUSTOM_ATMOSPHERE 1 #ifdef CUSTOM_ATMOSPHERE -float AltitudeMetersFromPressureKPa(float kPa) -{ - float x = kPa * 1000; - float sum = 0; - float xn = x; - for (size_t i = 1; i < AUTOGEN_ATMOSPHERE_NUM_COEFFECIENTS; i++) - { - const float coeff = ATMOSPHERE[i]; - sum += coeff * xn; - xn *= x; - } - return sum + ATMOSPHERE[0]; +float AltitudeMetersFromPressureKPa(float kPa) { + const float x = kPa * 1000.0F; + float sum = ATMOSPHERE[AUTOGEN_ATMOSPHERE_NUM_COEFFECIENTS - 1]; + for (size_t i = AUTOGEN_ATMOSPHERE_NUM_COEFFECIENTS - 1; i-- > 0;) { + sum = (sum * x) + ATMOSPHERE[i]; + } + return sum; } #else -float AltitudeMetersFromPressureKPa(float pressure_kpa) -{ - float pressure = pressure_kpa * 10; - float altitude = (1 - powf(pressure / 1013.25F, 0.190284F)) * (float)(145366.45 * 0.3048); - return altitude; +float AltitudeMetersFromPressureKPa(float pressure_kpa) { + float pressure = pressure_kpa * 10; + float altitude = (1 - powf(pressure / 1013.25F, 0.190284F)) * (float) (145366.45 * 0.3048); + return altitude; } #endif -Matrix<3, 3> expGyro(float w_1, float w_2, float w_3, float t) -{ - w_1 *= t; - w_2 *= t; - w_3 *= t; - - float w_1² = w_1 * w_1; - float w_2² = w_2 * w_2; - float w_3² = w_3 * w_3; - float w_1w_2 = w_1 * w_2; - float w_1w_3 = w_1 * w_3; - float w_2w_3 = w_2 * w_3; - // clang-format off - Matrix<3,3> A{{ - 0, -w_3, w_2, - w_3, 0, -w_1, - -w_2, w_1, 0, - }}; - Matrix<3,3> A²{{ - -(w_2² + w_3²), w_1w_2, w_1w_3, - w_1w_2, -(w_1²+w_3²), w_2w_3, - w_1w_3, w_2w_3, -(w_1²+w_2²), - }}; - - // clang-format on - float norm_sqred = w_1² + w_2² + w_3²; - float norm = std::sqrt(norm_sqred); - - // proof via desmos, this is what happens. (sinx/x = 1 (1-cosx)/x = 0 ) - float s = (norm == 0) ? 1 : (std::sin(norm) / norm); - float c = (norm == 0) ? 0 : ((1 - std::cos(norm)) / (norm_sqred)); - - Matrix<3, 3> I = Matrix<3, 3>::Identity(); - - auto eᴬᵗ = I + A * s + A² * c; - return eᴬᵗ; -} - -float deg2rad(float d) -{ - return d / 180.0F * 3.14159F; -} -float rad2deg(float d) -{ - return d * 180.0F / 3.14159F; +Matrix<3, 3> expGyro(float w_1, float w_2, float w_3, float t) { + const float w_1ᵗ = w_1 * t; + const float w_2ᵗ = w_2 * t; + const float w_3ᵗ = w_3 * t; + + const float w_1² = w_1ᵗ * w_1ᵗ; + const float w_2² = w_2ᵗ * w_2ᵗ; + const float w_3² = w_3ᵗ * w_3ᵗ; + const float w_1w_2 = w_1ᵗ * w_2ᵗ; + const float w_1w_3 = w_1ᵗ * w_3ᵗ; + const float w_2w_3 = w_2ᵗ * w_3ᵗ; + + const float θ² = w_1² + w_2² + w_3²; + const float θ = std::sqrt(θ²); + const float s = (θ == 0.0F) ? 1.0F : (std::sin(θ) / θ); + const float c = (θ == 0.0F) ? 0.0F : ((1.0F - std::cos(θ)) / θ²); + + return Matrix<3, 3>{{ + 1.0F - c * (w_2² + w_3²), + c * w_1w_2 - s * w_3ᵗ, + c * w_1w_3 + s * w_2ᵗ, + c * w_1w_2 + s * w_3ᵗ, + 1.0F - c * (w_1² + w_3²), + c * w_2w_3 - s * w_1ᵗ, + c * w_1w_3 - s * w_2ᵗ, + c * w_2w_3 + s * w_1ᵗ, + 1.0F - c * (w_1² + w_2²), + }}; } +float deg2rad(float d) { return d / 180.0F * 3.14159F; } +float rad2deg(float d) { return d * 180.0F / 3.14159F; } + static uint32_t lastGyroIntegrationMsSinceBoot = 0; -void FeedGyro(uint32_t msSinceBoot, const NTypes::GyroscopeData& gyro) -{ - float t = 0.01; - if (lastGyroIntegrationMsSinceBoot != 0) - { - const int32_t deltaMs = (int32_t)(msSinceBoot - lastGyroIntegrationMsSinceBoot); - t = static_cast(deltaMs) / 1000.F; - } - lastGyroIntegrationMsSinceBoot = msSinceBoot; - Matrix<3, 3> eAT = expGyro(gyro.X, gyro.Y, gyro.Z, t); - gyroOrientation = gyroOrientation * eAT; - NTypes::AccelerometerData zInIMUSpace; - RotateRocketVectorToIMUVector({ 0, 0, 1 }, zInIMUSpace); - // initial and startAxis are dependent on orientation_quat of imu - - Matrix<3, 1> initial{ { zInIMUSpace.X, zInIMUSpace.Y, zInIMUSpace.Z } }; - Matrix<3, 1> now = gyroOrientation * initial; - NTypes::AccelerometerData rotatedUsInRocketSpace{ 0, 0, 1 }; - RotateIMUVectorToRocketVector({ now.Get(0, 0), now.Get(1, 0), now.Get(2, 0) }, rotatedUsInRocketSpace); - - // initial = rotate([0 0 1] by quaternion) - // now = rotate initial by gyroOrientation - - auto dot = [](const Matrix<3, 1>& a, const Matrix<3, 1>& b) { - return a.Get(0, 0) * b.Get(0, 0) + a.Get(1, 0) * b.Get(1, 0) + a.Get(2, 0) * b.Get(2, 0); - }; - - float normOfNow = std::sqrt(initial.Get(0,0)*initial.Get(0,0) + initial.Get(1,0)*initial.Get(1,0) + initial.Get(2,0)*initial.Get(2,0)); - Matrix<3, 1> normedNow = initial * (1.F / normOfNow); - float offStart = acos(dot(initial, normedNow)); - bool outOfBounds = offStart > deg2rad(30); - everWentOutOfBounds |= outOfBounds; -} - -int GetOrientation() -{ - return 0; -} -bool EverWentOutOfBounds() -{ - return everWentOutOfBounds; -} - -void FillPacketWithOrientationMatrix(float* arr) -{ - for (size_t i = 0; i < 9; i++) - { - arr[i] = gyroOrientation.Get(i / 3, i % 3); - } -} - -void FillPacketWithKalmanInformation(float* inno, KalmanState &state) -{ - inno[0] = lastInnovation.Get(0, 0); - inno[1] = lastInnovation.Get(1, 0); - state = LastKalmanState(); -} - -} // namespace NModel +void FeedGyro(uint32_t msSinceBoot, const NTypes::GyroscopeData& gyro) { + float t = kDefaultGyroDeltaS; + if (lastGyroIntegrationMsSinceBoot != 0) { + const int32_t deltaMs = (int32_t) (msSinceBoot - lastGyroIntegrationMsSinceBoot); + if (deltaMs > 0) { + t = static_cast(deltaMs) / 1000.F; + if (t > kMaxGyroDeltaS) { + t = kMaxGyroDeltaS; + } + } + } + lastGyroIntegrationMsSinceBoot = msSinceBoot; + const Quaternion delta = QuaternionDeltaFromGyro(gyro, t); + gyroOrientation = NormalizeQuaternion(QuaternionMultiply(gyroOrientation, delta)); + + const Vec3& initial = InitialRocketZAxisInIMUSpace(); + const Vec3 now = RotateVectorByQuaternion(gyroOrientation, initial); + const float cosOffStart = ClampUnit(Dot3(initial, now)); + const bool outOfBounds = cosOffStart < kCosMaxTilt; + everWentOutOfBounds |= outOfBounds; +} + +int GetOrientation() { return 0; } +bool EverWentOutOfBounds() { return everWentOutOfBounds; } + +void FillPacketWithOrientationMatrix(float* arr) { + const float ww = gyroOrientation.w * gyroOrientation.w; + const float xx = gyroOrientation.x * gyroOrientation.x; + const float yy = gyroOrientation.y * gyroOrientation.y; + const float zz = gyroOrientation.z * gyroOrientation.z; + const float wx = gyroOrientation.w * gyroOrientation.x; + const float wy = gyroOrientation.w * gyroOrientation.y; + const float wz = gyroOrientation.w * gyroOrientation.z; + const float xy = gyroOrientation.x * gyroOrientation.y; + const float xz = gyroOrientation.x * gyroOrientation.z; + const float yz = gyroOrientation.y * gyroOrientation.z; + + arr[0] = ww + xx - yy - zz; + arr[1] = 2.0F * (xy - wz); + arr[2] = 2.0F * (xz + wy); + arr[3] = 2.0F * (xy + wz); + arr[4] = ww - xx + yy - zz; + arr[5] = 2.0F * (yz - wx); + arr[6] = 2.0F * (xz - wy); + arr[7] = 2.0F * (yz + wx); + arr[8] = ww - xx - yy + zz; +} + +void FillPacketWithKalmanInformation(float* inno, KalmanState& state) { + inno[0] = lastInnovation.Get(0, 0); + inno[1] = lastInnovation.Get(1, 0); + state = LastKalmanState(); +} + +} // namespace NModel diff --git a/app/other/airbraker/src/n_preboost.cpp b/app/other/airbraker/src/n_preboost.cpp index d26f892cd..96a02209f 100644 --- a/app/other/airbraker/src/n_preboost.cpp +++ b/app/other/airbraker/src/n_preboost.cpp @@ -44,14 +44,14 @@ void SubmitPreBoostPacket(const Packet &packet) { preboostPackets.AddSample(packet); Packet *newestSampleForGyroBias = &preboostPackets.OldestSample(); gyroBiasAverager.Feed({newestSampleForGyroBias->gyro}); - + // Grab ground level altitude from most recent if we're before the circular buffer is initialized if (preboostPackets.OldestSample().pressureRaw == 0) { groundLevelPressure = packet.pressureRaw; } else { groundLevelPressure = preboostPackets.OldestSample().pressureRaw; } - groundLevelASLMeters = NModel::AltitudeMetersFromPressureKPa(groundLevelPressure); + groundLevelASLMeters = NModel::AltitudeMetersFromPressureKPa(groundLevelPressure); } NTypes::GyroscopeData GetGyroBias() { return gyroBiasAverager.Avg().internal; } diff --git a/app/other/airbraker/src/n_sensing.cpp b/app/other/airbraker/src/n_sensing.cpp index 5a59984d6..47df19603 100644 --- a/app/other/airbraker/src/n_sensing.cpp +++ b/app/other/airbraker/src/n_sensing.cpp @@ -33,7 +33,8 @@ int InitSensors() { return 0; } -int MeasureSensors(float &tempC, float &pressureKPa, NTypes::AccelerometerData &accelMs2, NTypes::GyroscopeData &gyroDps) { +int MeasureSensors(float &tempC, float &pressureKPa, NTypes::AccelerometerData &accelMs2, + NTypes::GyroscopeData &gyroDps) { // todo, can make this less noisy by kicking off fetch, then doing other stuff, then reading int bret = sensor_sample_fetch(barom_dev); if (bret < 0) { diff --git a/app/other/airbraker/src/n_storage.cpp b/app/other/airbraker/src/n_storage.cpp index 428351f98..581adfd2a 100644 --- a/app/other/airbraker/src/n_storage.cpp +++ b/app/other/airbraker/src/n_storage.cpp @@ -236,8 +236,8 @@ uint32_t GetDataPartitionAddress() { return FLIGHT_PARTITION_OFFSET; } uint32_t GetParamPartitionSize() { return PARAM_PARTITION_SIZE; } uint32_t GetDataPartitionSize() { return FLIGHT_PARTITION_SIZE; } -int ReadDataBlock(uint32_t dataAddr, uint32_t size, uint8_t*data){ - if (dataAddr > FLIGHT_PARTITION_SIZE){ +int ReadDataBlock(uint32_t dataAddr, uint32_t size, uint8_t *data) { + if (dataAddr > FLIGHT_PARTITION_SIZE) { // out of bounds return -1; } diff --git a/app/other/airbraker/src/shell.cpp b/app/other/airbraker/src/shell.cpp index f6cf30a1c..68ffa6f4c 100644 --- a/app/other/airbraker/src/shell.cpp +++ b/app/other/airbraker/src/shell.cpp @@ -1,9 +1,9 @@ #include "common.hpp" +#include "n_boost.hpp" #include "n_buzzer.hpp" #include "n_model.hpp" #include "n_sensing.hpp" #include "n_storage.hpp" -#include "n_boost.hpp" #include "servo.hpp" #include @@ -409,7 +409,7 @@ static int cmd_fakeboost(const struct shell *shell, size_t argc, char **argv) { } long seconds = 0; bool parsed = parse_long(argv[1], &seconds); - if (!parsed){ + if (!parsed) { shell_error(shell, "Invalid number of seconds to wait for"); }