// Copyright (c) 2023 Oleg Kalachev // Repository: https://github.com/okalachev/flix // Attitude estimation from gyro and accelerometer #include "quaternion.h" #include "vector.h" #include "lpf.h" #include "util.h" #define WEIGHT_ACC 0.003 #define RATES_LFP_ALPHA 0.2 // cutoff frequency ~ 40 Hz LowPassFilter ratesFilter(RATES_LFP_ALPHA); void estimate() { applyGyro(); applyAcc(); } void applyGyro() { // filter gyro to get angular rates rates = ratesFilter.update(gyro); // apply rates to attitude attitude = Quaternion::rotate(attitude, Quaternion::fromRotationVector(rates * dt)); } void applyAcc() { // test should we apply accelerometer gravity correction float accNorm = acc.norm(); landed = !motorsActive() && abs(accNorm - ONE_G) < ONE_G * 0.1f; if (!landed) return; // calculate accelerometer correction Vector up = Quaternion::rotateVector(Vector(0, 0, 1), attitude); Vector correction = Vector::rotationVectorBetween(acc, up) * WEIGHT_ACC; // apply correction attitude = Quaternion::rotate(attitude, Quaternion::fromRotationVector(correction)); }