kopia lustrzana https://github.com/vsamy/DiFipp
Need merge check.
rodzic
0033d2fa72
commit
ef7b6dfba1
|
@ -29,8 +29,8 @@ endif()
|
||||||
add_compile_options("-D_USE_MATH_DEFINES")
|
add_compile_options("-D_USE_MATH_DEFINES")
|
||||||
|
|
||||||
# Eigen
|
# Eigen
|
||||||
# set(Eigen_REQUIRED "eigen3 >= 3.3")
|
set(Eigen_REQUIRED "eigen3 >= 3.3")
|
||||||
# search_for_eigen()
|
search_for_eigen()
|
||||||
|
|
||||||
add_subdirectory(include)
|
add_subdirectory(include)
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "GenericFilter.h"
|
#include "GenericFilter.h"
|
||||||
|
#include "typedefs.h"
|
||||||
#include <complex>
|
#include <complex>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace fratio {
|
namespace fratio {
|
||||||
|
|
||||||
// https://www.dsprelated.com/showarticle/1119.php
|
// https://www.dsprelated.com/showarticle/1119.php
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Butterworth : public GenericFilter<T> {
|
class Butterworth : public DigitalFilter<T> {
|
||||||
public:
|
public:
|
||||||
T PI = static_cast<T>(M_PI);
|
T PI = static_cast<T>(M_PI);
|
||||||
|
|
||||||
|
@ -39,8 +39,9 @@ private:
|
||||||
size_t m_order;
|
size_t m_order;
|
||||||
T m_fc;
|
T m_fc;
|
||||||
T m_fs;
|
T m_fs;
|
||||||
|
Eigen::VectorX<std::complex<T>> m_poles;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace fratio
|
} // namespace fratio
|
||||||
|
|
||||||
#include "Butterworth.inl"
|
#include "Butterworth.tpp"
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "GenericFilter.h"
|
#include "GenericFilter.h"
|
||||||
|
#include "typedefs.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace fratio {
|
namespace fratio {
|
||||||
|
|
||||||
|
@ -9,23 +11,18 @@ class DigitalFilter : public GenericFilter<T> {
|
||||||
public:
|
public:
|
||||||
DigitalFilter() = default;
|
DigitalFilter() = default;
|
||||||
DigitalFilter(const std::vector<T>& aCoeff, const std::vector<T>& bCoeff)
|
DigitalFilter(const std::vector<T>& aCoeff, const std::vector<T>& bCoeff)
|
||||||
|
{
|
||||||
|
setCoeffs(aCoeff, bCoeff);
|
||||||
|
}
|
||||||
|
DigitalFilter(const Eigen::VectorX<T>& aCoeff, const Eigen::VectorX<T>& bCoeff)
|
||||||
: GenericFilter<T>(aCoeff, bCoeff)
|
: GenericFilter<T>(aCoeff, bCoeff)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCoeff(const std::vector<double>& aCoeff, const std::vector<double>& bCoeff)
|
|
||||||
{
|
|
||||||
checkCoeff(aCoeff, bCoeff);
|
|
||||||
|
|
||||||
m_aCoeff = aCoeff;
|
|
||||||
m_bCoeff = bCoeff;
|
|
||||||
resetFilter();
|
|
||||||
|
|
||||||
normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t aOrder() const noexcept { return m_aCoeff.size(); }
|
size_t aOrder() const noexcept { return m_aCoeff.size(); }
|
||||||
size_t bOrder() const noexcept { return m_bCoeff.size(); }
|
size_t bOrder() const noexcept { return m_bCoeff.size(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace fratio
|
} // namespace fratio
|
||||||
|
|
||||||
|
#include "DigitalFilter.tpp"
|
|
@ -1,7 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "type_checks.h"
|
#include "type_checks.h"
|
||||||
|
#include "typedefs.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace fratio {
|
namespace fratio {
|
||||||
|
@ -11,29 +13,40 @@ class GenericFilter {
|
||||||
static_assert(std::is_floating_point<T>::value && !std::is_const<T>::value, "Only accept non-complex floating point types.");
|
static_assert(std::is_floating_point<T>::value && !std::is_const<T>::value, "Only accept non-complex floating point types.");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
T stepFilter(T data);
|
static std::string filterStatus(FilterStatus status);
|
||||||
std::vector<T> filter(const std::vector<T>& data);
|
|
||||||
|
public:
|
||||||
|
// Careful: Only an assert check for the filter status
|
||||||
|
T stepFilter(const T& data);
|
||||||
|
Eigen::VectorX<T> filter(const Eigen::VectorX<T>& data);
|
||||||
|
bool getFilterResults(Eigen::Ref<Eigen::VectorX<T>> results, const Eigen::VectorX<T>& data);
|
||||||
void resetFilter();
|
void resetFilter();
|
||||||
|
|
||||||
void getCoeff(std::vector<T>& aCoeff, std::vector<T>& bCoeff) const noexcept;
|
bool setCoeffs(const std::vector<T>& aCoeff, const std::vector<T>& bCoeff);
|
||||||
|
bool setCoeffs(const Eigen::VectorX<T>& aCoeff, const Eigen::VectorX<T>& bCoeff);
|
||||||
|
void getCoeffs(std::vector<T>& aCoeff, std::vector<T>& bCoeff) const;
|
||||||
|
void getCoeffs(Eigen::Ref<Eigen::VectorX<T>> aCoeff, Eigen::Ref<Eigen::VectorX<T>> bCoeff) const;
|
||||||
|
FilterStatus status() const noexcept { return m_status; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GenericFilter() = default;
|
GenericFilter() = default;
|
||||||
GenericFilter(const std::vector<T>& aCoeff, const std::vector<T>& bCoeff);
|
GenericFilter(const Eigen::VectorX<T>& aCoeff, const Eigen::VectorX<T>& bCoeff);
|
||||||
virtual ~GenericFilter() = default;
|
virtual ~GenericFilter() = default;
|
||||||
|
|
||||||
void checkCoeff(const std::vector<T>& aCoeff, const std::vector<T>& bCoeff);
|
void normalizeCoeffs();
|
||||||
void normalize();
|
template <typename T2>
|
||||||
|
bool checkCoeffs(const T2& aCoeff, const T2& bCoeff);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<T> m_aCoeff;
|
FilterStatus m_status;
|
||||||
std::vector<T> m_bCoeff;
|
Eigen::VectorX<T> m_aCoeff;
|
||||||
|
Eigen::VectorX<T> m_bCoeff;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<T> m_filteredData;
|
Eigen::VectorX<T> m_filteredData;
|
||||||
std::vector<T> m_rawData;
|
Eigen::VectorX<T> m_rawData;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace fratio
|
} // namespace fratio
|
||||||
|
|
||||||
#include "GenericFilter.inl"
|
#include "GenericFilter.tpp"
|
||||||
|
|
|
@ -1,20 +1,27 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "GenericFilter.h"
|
#include "DigitalFilter.h"
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
namespace fratio {
|
namespace fratio {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class MovingAverage : public GenericFilter<T> {
|
class MovingAverage : public DigitalFilter<T> {
|
||||||
public:
|
public:
|
||||||
MovingAverage() = default;
|
MovingAverage() = default;
|
||||||
MovingAverage(size_t windowSize)
|
MovingAverage(size_t windowSize)
|
||||||
: GenericFilter<T>({ 1 }, std::vector<T>(windowSize, T(1) / windowSize))
|
: DigitalFilter<T>(Eigen::VectorX<T>::Constant(1, T(1)), Eigen::VectorX<T>::Constant(windowSize, T(1) / windowSize)))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void setWindowSize(size_t windowSize) { setCoeff({ 1 }, std::vector<T>(windowSize, 1 / windowSize)); }
|
void setWindowSize(size_t windowSize) { setCoeffs(Eigen::VectorX<T>::Constant(1, T(1)), Eigen::VectorX<T>::Constant(windowSize, T(1) / windowSize)); }
|
||||||
size_t windowSize() const noexcept { return m_bCoeff.size(); }
|
size_t windowSize() const noexcept { return bOrder(); }
|
||||||
|
: DigitalFilter<T>(Eigen::VectorX<T>::Constant(1, T(1)), Eigen::VectorX<T>::Constant(windowSize, T(1) / windowSize)))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void setWindowSize(size_t windowSize) { setCoeffs(Eigen::VectorX<T>::Constant(1, T(1)), Eigen::VectorX<T>::Constant(windowSize, T(1) / windowSize)); }
|
||||||
|
size_t windowSize() const noexcept { return bOrder(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace fratio
|
} // namespace fratio
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "type_checks.h"
|
#include "type_checks.h"
|
||||||
|
#include "typedefs.h"
|
||||||
#include <complex>
|
#include <complex>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace fratio {
|
namespace fratio {
|
||||||
|
|
||||||
|
@ -11,21 +11,32 @@ struct VietaAlgo {
|
||||||
static_assert(std::is_arithmetic<internal::complex_sub_type_t<T>>::value, "This struct can only accept arithmetic types or complex.");
|
static_assert(std::is_arithmetic<internal::complex_sub_type_t<T>>::value, "This struct can only accept arithmetic types or complex.");
|
||||||
|
|
||||||
// Vieta's computation: https://en.wikipedia.org/wiki/Vieta%27s_formulas
|
// Vieta's computation: https://en.wikipedia.org/wiki/Vieta%27s_formulas
|
||||||
static std::vector<T> polyCoeffFromRoot(const std::vector<T>& poles);
|
static Eigen::VectorX<T> polyCoeffFromRoot(const Eigen::VectorX<T>& poles);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::vector<T> VietaAlgo<T>::polyCoeffFromRoot(const std::vector<T>& poles)
|
Eigen::VectorX<T> VietaAlgo<T>::polyCoeffFromRoot(const Eigen::VectorX<T>& poles)
|
||||||
{
|
{
|
||||||
std::vector<T> coeff(poles.size() + 1, 0);
|
Eigen::VectorX<T> coeffs = Eigen::VectorX<T>::Zero(poles.size() + 1);
|
||||||
coeff[0] = 1;
|
coeffs(0) = T(1);
|
||||||
for (size_t i = 0; i < poles.size(); ++i) {
|
for (size_t i = 0; i < poles.size(); ++i) {
|
||||||
for (size_t k = i + 1; k > 0; --k) {
|
for (size_t k = i + 1; k > 0; --k) {
|
||||||
coeff[k] = coeff[k] - poles[i] * coeff[k - 1];
|
coeffs(k) -= poles(i) * coeffs(k - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Check for equation c(k) = sum(i=k-1, poles.size() : p(i)) * c(k-1), k>=1
|
||||||
|
// size_t pSize = poles.size();
|
||||||
|
// for (size_t k = 1; k < coeffs.size(); ++k)
|
||||||
|
// coeffs(k) -= poles.tail(pSize - (k - 1)).sum() * coeffs(k - 1);
|
||||||
|
|
||||||
return coeff;
|
// Maybe better
|
||||||
|
// T sum = poles.sum();
|
||||||
|
// for (size_t k = 1; k < coeffs.size(); ++k) {
|
||||||
|
// coeffs(k) -= sum * coeffs(k - 1);
|
||||||
|
// sum -= poles(k - 1);
|
||||||
|
// }
|
||||||
|
|
||||||
|
return coeffs;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace fratio
|
} // namespace fratio
|
||||||
|
|
Ładowanie…
Reference in New Issue