文章目录
说明
滑动平均模板类
#pragma once
#include <queue>
#include <list>
namespace ns_filter {
template <typename T, int M>
class SMA
{
public:
static_assert(M>1, "SMA require window width>1");
SMA() :_last_flt_value{ 0 } {};
~SMA() {};
T apply(const T& raw) {
_queue.push(raw);
if (_queue.size() > M) {
_last_flt_value += ((raw - _queue.front()) / M);
_queue.pop();
} else {
_last_flt_value = (_last_flt_value * (_queue.size() - 1) + raw) / _queue.size();
}
return _last_flt_value;
}
private:
std::queue<T> _queue;
T _last_flt_value{0};
};
template <typename T, int M>
class WMA
{
public:
static_assert(M > 1, "WMA require window width>1");
WMA() {};
~WMA() {};
T apply(const T& raw) {
_ls.push_back(raw);
if (_ls.size() > M) {
_ls.pop_front();
}
int sz = _ls.size();
int den = sz * (sz + 1) / 2;
int w = 1;
T sum{0};
for (auto v : _ls) {
sum += (w * v);
++w;
}
return sum/den;
}
private:
std::list<T> _ls;
};
template <typename T>
class EMA
{
public:
EMA() = delete;
EMA(double alpha) { _alpha = alpha; };
~EMA() {};
T apply(const T& raw) {
if (_initlized == false) {
_last_y = raw;
_initlized = true;
}
else {
_last_y = _alpha * _last_y + (1 - _alpha) * raw;
}
return _last_y;
}
private:
T _last_y;
double _alpha = 0.1f;
bool _initlized = false;
};
}
使用与测试
测试代码
#include "gtest/gtest.h"
#include "lowPassFilter.h"
TEST(Testfilter, TestEMA) {
ns_filter::EMA<double> flt2(0.1);
double r = flt2.apply(1);
EXPECT_TRUE(abs(r - 1) < 1e-5);
r = flt2.apply(2);
EXPECT_TRUE(abs(r - 1.9) < 1e-5);
r = flt2.apply(4);
EXPECT_TRUE(abs(r - 0.19-3.6) < 1e-5);
r = flt2.apply(3);
EXPECT_TRUE(abs(r - 0.019-0.36-2.7) < 1e-5);
}
TEST(Testfilter, TestSMA) {
ns_filter::SMA<double> flt(3);
double r = flt.apply(1);
EXPECT_TRUE(abs(r - 1) < 1e-5);
r = flt.apply(2);
EXPECT_TRUE(abs(r - 1.5) < 1e-5);
r = flt.apply(4);
EXPECT_TRUE(abs(r - 7.0 / 3) < 1e-5);
r = flt.apply(3);
EXPECT_TRUE(abs(r - 3) < 1e-5);
}
TEST(Testfilter, TestWMA) {
ns_filter::WMA<double> flt2(3);
double r = flt2.apply(1);
EXPECT_TRUE(abs(r - 1) < 1e-5);
r = flt2.apply(2);
EXPECT_TRUE(abs(r - 5.0 / 3) < 1e-5);
r = flt2.apply(4);
EXPECT_TRUE(abs(r - (1 + 4 + 12) * 1.0 / (1 + 2 + 3)) < 1e-5);
r = flt2.apply(3);
EXPECT_TRUE(abs(r - (2 + 8 + 9) * 1.0 / (1 + 2 + 3)) < 1e-5);
}
google test测试结果
visual studio 和 cygwin下测试结果如下,