I have implemented several implementations of a linear Kalman filter tracking a sine wave. I have a Python and a C implementation that both work.
However I have also developed a version that uses a fixed point implementation and it works, but I am seeing an odd effect where it initially seems to fit and then diverges from the output of the other Kalman filter codes.
See the plots below:
I was wondering if anyone has some intuition for what might be going wrong in the fixed point implementation?
Hopefully you're long past this problem now, but, in case not - here's what I usually have to do with a fixed-point KF. Problems arise from the limited range of values available. If we set the fixed-point such that the initial covariance matrix is representable, we often do not have a lot of bits to the right of the decimal point and to represent the gain and state update for the solution once it begins to converge.
That's a long way of stating the obvious - we like floating point for filters - and in particular since the covariance matrix is squared standard deviations - it is stepping through orders-of-magnitude 'quickly' if you will, while the state update is not squared - so we are in a bind trying to select a single fixed-point location that allows us to reasonably represent the squared covariance elements and the not-squared state update.
So I often end-up with a gear shift or two - I've used up to '5-speed' fixed-point KF's in the past. When I get to the end of the time update step - I have the largest values for the covariance I am going to get for that cycle. Measurement processing will only decrease the covariance. If my Kalman filter fixed-point representation is more than 2 bits larger than I need for the covariance, I shift left and change the fixed-point on the fly. This keeps a reasonable number of bits for the gain and state update values.
This is in effect a poor-man's floating point, but I have only one decimal point location for all the filter elements. I use some hysteresis to keep from shifting all the time. When I get that working properly - I cannot distinguish the fixed and floating point results - which is more or less what we should expect as it's "floating the point".