reverting version

This commit is contained in:
Dmitry Borisenko
2020-09-02 22:34:49 +03:00
parent 70096c71c8
commit 2e8ea582d2
286 changed files with 29912 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
#pragma once
#include <filters/alfaBeta.h>
#include <filters/kalman.h>
#include <filters/linear.h>
#include <filters/median.h>
#include <filters/median3.h>
#include <filters/runningAverage.h>
/*
GyverFilters - библиотека с некоторыми удобными фильтрами:
- GFilterRA - компактная альтернатива фильтра экспоненциальное бегущее среднее (Running Average)
- GMedian3 - быстрый медианный фильтр 3-го порядка (отсекает выбросы)
- GMedian - медианный фильтр N-го порядка. Порядок настраивается в GyverFilters.h - MEDIAN_FILTER_SIZE
- GABfilter - альфа-бета фильтр (разновидность Калмана для одномерного случая)
- GKalman - упрощённый Калман для одномерного случая (на мой взгляд лучший из фильтров)
- GLinear - линейная аппроксимация методом наименьших квадратов для двух массивов
Версии
- 1.6 от 12.11.2019
- 1.7: исправлен GLinear
- 1.8: небольшие улучшения
- 2.0:
- Улучшен и исправлен median и median3
- Улучшен linear
- Смотрите примеры! Использование этих фильтров чуть изменилось
*/

View File

@@ -0,0 +1,37 @@
#pragma once
#include <math.h>
// альфа-бета фильтр
class GABfilter {
public:
// период дискретизации (измерений), process variation, noise variation
GABfilter(float delta, float sigma_process, float sigma_noise) {setParameters(delta, sigma_process, sigma_noise);}
// период дискретизации (измерений), process variation, noise variation
void setParameters(float delta, float sigma_process, float sigma_noise) {
dt = delta;
float lambda = (float)sigma_process * dt * dt / sigma_noise;
float r = (4 + lambda - (float)sqrt(8 * lambda + lambda * lambda)) / 4;
a = (float)1 - r * r;
b = (float)2 * (2 - a) - 4 * (float)sqrt(1 - a);
}
// возвращает фильтрованное значение
float filtered(float value) {
xm = value;
xk = xk_1 + ((float) vk_1 * dt );
vk = vk_1;
rk = xm - xk;
xk += (float)a * rk;
vk += (float)( b * rk ) / dt;
xk_1 = xk;
vk_1 = vk;
return xk_1;
}
private:
float dt;
float xk_1, vk_1, a, b;
float xk, vk, rk;
float xm;
};

View File

@@ -0,0 +1,38 @@
#pragma once
#include <math.h>
// упрощённый Калман для одномерного случая
class GKalman {
public:
// разброс измерения, разброс оценки, скорость изменения значений
GKalman(float mea_e, float est_e, float q) { setParameters(mea_e, est_e, q); }
// разброс измерения, скорость изменения значений (разброс измерения принимается равным разбросу оценки)
GKalman(float mea_e, float q) {GKalman::setParameters(mea_e, mea_e, q);}
// разброс измерения, разброс оценки, скорость изменения значений
void setParameters(float mea_e, float est_e, float q) {
_err_measure = mea_e;
_err_estimate = est_e;
_q = q;
}
// разброс измерения, скорость изменения значений (разброс измерения принимается равным разбросу оценки)
void setParameters(float mea_e, float q) {setParameters(mea_e, mea_e, q);}
// возвращает фильтрованное значение
float filtered(float value) {
float _kalman_gain, _current_estimate;
_kalman_gain = _err_estimate / (_err_estimate + _err_measure);
_current_estimate = _last_estimate + _kalman_gain * (value - _last_estimate);
_err_estimate = (1.0 - _kalman_gain)*_err_estimate + fabs(_last_estimate-_current_estimate)*_q;
_last_estimate=_current_estimate;
return _current_estimate;
}
private:
float _err_measure = 0.0;
float _err_estimate = 0.0;
float _q = 0.0;
float _last_estimate = 0.0;
};

View File

@@ -0,0 +1,30 @@
#pragma once
#include <Arduino.h>
// линейная аппроксимация методом наименьших квадратов
template < typename TYPE >
class GLinear {
public:
GLinear(){};
void compute(TYPE *x_array, TYPE *y_array, int arrSize) { // аппроксимировать
int32_t sumX = 0, sumY = 0, sumX2 = 0, sumXY = 0;
arrSize /= sizeof(int);
for (int i = 0; i < arrSize; i++) { // для всех элементов массива
sumX += x_array[i];
sumY += (long)y_array[i];
sumX2 += x_array[i] * x_array[i];
sumXY += (long)y_array[i] * x_array[i];
}
a = (long)arrSize * sumXY; // расчёт коэффициента наклона приямой
a = a - (long)sumX * sumY;
a = (float)a / (arrSize * sumX2 - sumX * sumX);
b = (float)(sumY - (float)a * sumX) / arrSize;
delta = a * arrSize; // расчёт изменения
}
float getA() {return a;} // получить коэффициент А
float getB() {return b;} // получить коэффициент В
float getDelta() {return delta;} // получить аппроксимированное изменение
private:
float a, b, delta;
};

View File

@@ -0,0 +1,35 @@
#pragma once
// медианный фильтр N-го порядка
template < int SIZE, typename TYPE >
class GMedian {
public:
TYPE filtered(TYPE newVal) {
buffer[_count] = newVal;
if ((_count < _numRead - 1) && (buffer[_count] > buffer[_count + 1])) {
for (int i = _count; i < _numRead - 1; i++) {
if (buffer[i] > buffer[i + 1]) {
float buff = buffer[i];
buffer[i] = buffer[i + 1];
buffer[i + 1] = buff;
}
}
} else {
if ((_count > 0) and (buffer[_count - 1] > buffer[_count])) {
for (int i = _count; i > 0; i--) {
if (buffer[i] < buffer[i - 1]) {
float buff = buffer[i];
buffer[i] = buffer[i - 1];
buffer[i - 1] = buff;
}
}
}
}
if (++_count >= _numRead) _count = 0;
return buffer[(int)_numRead / 2];
}
private:
TYPE buffer[SIZE];
byte _count = 0;
byte _numRead = SIZE;
};

View File

@@ -0,0 +1,30 @@
#pragma once
// быстрый медианный фильтр 3-го порядка
template < typename TYPE >
class GMedian3 {
public:
TYPE filtered(TYPE value) { // возвращает фильтрованное значение
buffer[_counter] = value;
if (++_counter > 2) _counter = 0;
TYPE middle;
if ((buffer[0] <= buffer[1]) && (buffer[0] <= buffer[2])) {
middle = (buffer[1] <= buffer[2]) ? buffer[1] : buffer[2];
}
else {
if ((buffer[1] <= buffer[0]) && (buffer[1] <= buffer[2])) {
middle = (buffer[0] <= buffer[2]) ? buffer[0] : buffer[2];
}
else {
middle = (buffer[0] <= buffer[1]) ? buffer[0] : buffer[1];
}
}
return middle;
}
private:
TYPE buffer[3];
uint8_t _counter = 0;
};

View File

@@ -0,0 +1,43 @@
#include <filters/runningAverage.h>
GFilterRA::GFilterRA() {}
GFilterRA::GFilterRA(float coef, uint16_t interval) {
_coef = coef;
_filterInterval = interval;
}
GFilterRA::GFilterRA(float coef) {
_coef = coef;
}
void GFilterRA::setCoef(float coef) {
_coef = coef;
}
void GFilterRA::setStep(uint16_t interval) {
_filterInterval = interval;
}
float GFilterRA::filteredTime(int16_t value) {
if (millis() - _filterTimer >= _filterInterval) {
_filterTimer = millis();
return GFilterRA::filtered(value);
}
}
float GFilterRA::filteredTime(float value) {
if (millis() - _filterTimer >= _filterInterval) {
_filterTimer = millis();
return GFilterRA::filtered(value);
}
}
float GFilterRA::filtered(int16_t value) {
_lastValue += (float)(value - _lastValue) * _coef;
return _lastValue;
}
float GFilterRA::filtered(float value) {
_lastValue += (float)(value - _lastValue) * _coef;
return _lastValue;
}

View File

@@ -0,0 +1,24 @@
#pragma once
#include <Arduino.h>
// экспоненциальное бегущее среднее
class GFilterRA
{
public:
GFilterRA(); // инициализация фильтра
GFilterRA(float coef); // расширенная инициализация фильтра (коэффициент)
GFilterRA(float coef, uint16_t interval); // расширенная инициализация фильтра (коэффициент, шаг фильтрации)
void setCoef(float coef); // настройка коэффициента фильтрации (0.00 - 1.00). Чем меньше, тем плавнее
void setStep(uint16_t interval); // установка шага фильтрации (мс). Чем меньше, тем резче фильтр
float filteredTime(int16_t value); // возвращает фильтрованное значение с опорой на встроенный таймер
float filtered(int16_t value); // возвращает фильтрованное значение
float filteredTime(float value); // возвращает фильтрованное значение с опорой на встроенный таймер
float filtered(float value); // возвращает фильтрованное значение
private:
float _coef = 0.0, _lastValue = 0.0;
uint32_t _filterTimer = 0;
uint16_t _filterInterval = 0;
};