There’s a passing resemblance between the complementary and the Kalman filters, so to start understanding Kalman, I changed variable names to ones I recognised.
Xn = gain * (Xn-1 + (gnow - gprev) * δt) + (1 - gain) * an
Xn+1 = gain * Xn-1 + (1 - gain) * Xn
The main differences are that the complementary filter is merging two sources of the same information based on a gain (< 1) whereas the Kalman is merging the previous processed and current sensor readings to predict the next value where the gain is dynamic but still less than one – and I didn’t get much further than that, because in writing this down, I spotted a crass (krass?) error in my complementary filter which could more than account for the flight problems.
Kalman will have to wait another day to shine!
I’ll update the code on GitHub as soon as it’s tested – the weather tomorrow looks to be in my favour.