package tc.oc.pgm.utils; import java.util.ArrayDeque; import java.util.Queue; public class RollingAverageFilter { /** * A queue that can be used to smooth out numeric samples over time. */ private final int windowSize; private final double temporalBias; private final Queue<Double> samples; public RollingAverageFilter(int windowSize, double temporalBias) { /** * Create a filter with the given fixed window size. * This will be the maximum number of samples that * the queue will retain. The temporalBias is the weight * ratio between successive samples. Values greater than * one will give recent samples more weight. */ this.windowSize = windowSize; this.temporalBias = temporalBias; this.samples = new ArrayDeque<>(windowSize); } public double total() { /** * Return the filtered "total" of all samples in the window. * This is simply the average times the window size. In this * way, this method can return a consistently useful value * even if the filter is not always full. */ return this.average() * this.windowSize; } public double average() { /** * Return the weighted average of all samples in the window, * accounting for the temporalBias parameter. */ if(this.samples.isEmpty()) { return 0D; } else { double total = 0D, totalWeight = 0D, weight = 1D; for(Double n : this.samples) { weight *= this.temporalBias; totalWeight += weight; total += n * weight; } return total / totalWeight; } } public void sample(double n) { /** * Append a sample to the filter */ if(this.samples.size() == this.windowSize) { this.samples.remove(); } this.samples.add(n); } public void clear() { /** * Empty the filter of all samples */ this.samples.clear(); } public int size() { return this.samples.size(); } }