Movement Smoothing
I stumbled on a problem while working with servos and analog user input.
Data from accelerometers, gyros or the Leap Motion controller is usually
for lack of better words, fuzzy. Pass this "fuzzy" data directly to
a pair of servos and you get shaky servos.
Shaky servos
Fuzzy data has been plaguing anyone who charts finance data for some time. A simple search will render a few posible solutions, some simple, some complex. I went with simple.
Moving averages
From Wikipedia: "Is a calculation to analyze data points by creating a series of averages of different subsets of the full data set." In other words: Pick a maximum amount of data points as a sample size and average them, as you get new data you drop the oldest if it exceeds the maximum size. Simple and effective.
In Code:
var buffer = [],
maxSample = 5,
data = [12, 18, 13, 15, 10, 20, 13, 15, 16, 17, 18, 19, 20],
result = [];
var smooth = function(val) {
var sum;
//add the new value.
buffer.push(val);
//if the max sample size has been reached, drop the tail
if (buffer.length >= maxSample) {
buffer.shift();
}
//sum and average out.
sum = buffer.reduce(function(x, y) {
return x + y;
});
return Math.floor(sum / buffer.length);
};
//run the test.
data.forEach(function(val) {
result.push(smooth(val));
});
//produces:
//[12, 15, 14, 14, 14, 14, 14, 14, 16, 15, 16, 17, 18]
//compare to original:
//[12, 18, 13, 15, 10, 20, 13, 15, 16, 17, 18, 19, 20];
Sample size
Choosing a sample size is an important decision, larger samples will introduce lag and smaller will leave noise. The goldilocks zone for my servo problems was a sample size of five, it reduced noise while not introducing any discernible lag.