To begin with, lets talk about what are the goals of using a filter. In the simplest terms I can think of, the purpose of a filter is to remove from a mixture some part that is unwanted while allowing the desirable part to pass through unaffected. If you think about a filter for drinking water, you would expect it to remove dirt, rust, and other impurities while allowing only clean water to pass through. When talking about filtering data, we want to remove undesired signals while allowing the desired signal to pass through with as little alteration as possible.
When looking at a signal coming from an accelerometer which is mounted on a quadcopter, there is a large potential for noise in the actual acceleration signal. If the motors or propellers are out of balance, the the shaking from them will show up in the accelerometer data. Even in an perfect environment, the accelerometer will naturally have noise of its own in its signal. So if we are going to use the acceleration data, it needs to be free of errors or else whatever we use the data for will be tainted.
To make things more complicated, a quadrotor needs fast data to keep the aircraft stable. We don't have all day for the processor to work on the data and remove the error. In an 16Mhz Arduino, we have the processing power of a 25 year old desktop (which is amazing in it's own right) so nothing we do can be super complicated. My smartphone is 100x more powerful (or even more if you include the graphics chip).
Lets start looking at data and see what all this really means.
Fig. 1 - Raw Accelerometer Data
In figure 1 above, I have plotted a graph of the raw data from the accelerometer. In this data I held the sensor and made one slow oscillation followed by four quick oscillations. For any one who likes nice pretty lines and curves, this graph is not for you. There are a lot of small wiggles that make the data look very spiky. If we are going to use this data we want to get rid of the spikiness and try to make it smooth while still following the the original data as close as possible.
Any time a signal has many spikes that happen very often, it would be considered a high frequency signal. The noise in the above picture looks like it has a high frequency. In contrast, the part of the signal we want looks like it moves in slow waves. This suggests that the data we want is a low frequency. If we want to keep the low frequency data while throwing away the high frequency noise, then we might want to use a low-pass filter. A low pass filter does exactly what its name implies, it allows the low frequencies to pass while blocking the high frequencies. We can look at the graph below and see how well it works.
|Fig 2 - Raw data and a Low Pass Filter|
Above we see in figure 2 what an exponential decay low pass filter looks like when applied to our rough looking raw data. Clearly we have eliminated the high frequency spiky look. Unfortunately, there are two problems with this solution. The first is that the filtered data appears to have been shifted to the right. This indicates that the data is being delayed by the filter which is typical of this kind of filter when it is set to have a strong filtering effect. The second issue is that the data doesn't seem to follow the original data very well. If you look at the four fast oscillation, the red line doesn't seem to reach as high as it should while also not reaching as low as it should. Reducing the strength of this filter would reduce both of these problems, but also allow more noise back into the signal.
After playing with the low pass filter for a while, I concluded that I needed another type of filter as the side effects of the only using a low pass filter were killing the real signal I wanted to preserve. In the spirit of doing things the hard way, I started looking at lists of filters to see if any of them looked like itt could do a better job than the LPF. After looking for a little while I tripped across what is referred to as the Median-Filter. It looked like it had the potential to do exactly what I needed ignore the noise while following the main signal closely. I then did an internet search for "accelerometer data median filter" and found out that this is a very common filter to use for cleaning up accelerometer data. Oops, I could have saved a lot of time with a little research. Below is a graph showing the results.
|Fig 3 - Raw data and a Low Pass Filter|
In figure 3 above, you can see that the median filter does a very good job of following the data while ignoring the noise. I have paired it with a very light low pass filter to help smooth some of the edges that a median filter can naturally create. This filter no longer shifts our data to the right by a significant amount so we can conclude that is is not delaying the signal very much. You can also see that even during the fast oscillations the peak of the filtered data is very close to the same height as the unfiltered data. I have created a graph to make it easy to compare this to the previous aggressive low pass filter.
|Fig 4 - Both Filters|
Clearly the median filter (red line) is doing a much better job of representing the signal we actually want when compared to the low pass filter (yellow line).
|Fig 4 - Final Result|
Here are some random final notes. I wrote the sliding median function myself as I wanted to make sure it ran as fast as possible and I wanted the challenge. There is a library available to do it as well for anyone who doesn't want to go through the work of writing it. I am currently using a 7 sample sliding window for my median filter which seems to be working well with the 800Hz sample rate coming from my accelerometer. Due to the time required to send the data back to the computer while sampling, the above data doesn't represent a true 800Hz sample rate as the serial print function takes a huge amount of time.
That is all for now. Let me know if you have any questions.
Thanks for reading and please sign up on the right if you want to be automatically notified when I post more updates.
<< Previous Quadrotor Post | Next Quadrotor Post >>