#pragma once
#include <algorithm>
#include <vector>
#include <wpi/Algorithm.h>
#include <wpi/circular_buffer.h>
namespace frc {
template <class T>
class MedianFilter {
public:
constexpr explicit MedianFilter(size_t size)
: m_valueBuffer(size), m_size{size} {}
constexpr T Calculate(T next) {
wpi::insert_sorted(m_orderedValues, next);
size_t curSize = m_orderedValues.size();
if (curSize > m_size) {
m_orderedValues.erase(std::find(m_orderedValues.begin(),
m_orderedValues.end(),
m_valueBuffer.pop_back()));
--curSize;
}
m_valueBuffer.push_front(next);
if (curSize % 2 != 0) {
return m_orderedValues[curSize / 2];
} else {
return (m_orderedValues[curSize / 2 - 1] + m_orderedValues[curSize / 2]) /
2.0;
}
}
constexpr T LastValue() const { return m_valueBuffer.front(); }
constexpr void Reset() {
m_orderedValues.clear();
m_valueBuffer.reset();
}
private:
wpi::circular_buffer<T> m_valueBuffer;
std::vector<T> m_orderedValues;
size_t m_size;
};
}