Add Central filtrering.

topic/diffentiators v1.3.0
Vincent Samy 2019-10-28 17:23:25 +09:00
rodzic 75e8924949
commit 3320b425bd
4 zmienionych plików z 105 dodań i 32 usunięć

Wyświetl plik

@ -50,6 +50,35 @@ public:
: GenericFilter<T>(aCoeff, bCoeff) : GenericFilter<T>(aCoeff, bCoeff)
{ {
} }
void setCoefficients(vectX_t<T>&& aCoeff, vectX_t<T>&& bCoeff)
{
setCoeffs(std::forward(aCoeff), std::forward(bCoeff));
}
};
/*! \brief Basic centered digital filter.
*
* This filter allows you to set any centered digital filter based on its coefficients.
* \tparam T Floating type.
*/
template <typename T>
class CenteredDigitalFilter : public GenericFilter<T> {
public:
/*! \brief Default uninitialized constructor. */
CenteredDigitalFilter() = default;
/*! \brief Constructor.
* \param aCoeff Denominator coefficients of the filter in decreasing order.
* \param bCoeff Numerator coefficients of the filter in decreasing order.
*/
CenteredDigitalFilter(const vectX_t<T>& aCoeff, const vectX_t<T>& bCoeff)
: GenericFilter<T>(aCoeff, bCoeff, Type::Centered)
{
}
void setCoefficients(vectX_t<T>&& aCoeff, vectX_t<T>&& bCoeff)
{
setCoeffs(std::forward(aCoeff), std::forward(bCoeff));
setType(Type::Centered);
}
}; };
} // namespace difi } // namespace difi

Wyświetl plik

@ -35,6 +35,9 @@
namespace difi { namespace difi {
// TODO: noexcept(Function of gsl variable)
// TODO: constructor with universal refs
/*! \brief Low-level filter. /*! \brief Low-level filter.
* *
* It creates the basic and common functions of all linear filter that can written as a digital filter. * It creates the basic and common functions of all linear filter that can written as a digital filter.
@ -49,6 +52,12 @@ template <typename T>
class GenericFilter { 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:
enum class Type {
OneSided,
Centered
};
public: public:
/*! \brief Filter a new data. /*! \brief Filter a new data.
* *
@ -64,16 +73,11 @@ public:
* \return Filtered signal. * \return Filtered signal.
*/ */
vectX_t<T> filter(const vectX_t<T>& data); vectX_t<T> filter(const vectX_t<T>& data);
/*! \brief Filter a signal and store in a user-defined Eigen vector.
*
* Useful if the length of the signal is known in advance.
* \param[out] results Filtered signal.
* \param data Signal.
* \return False if vector's lengths do not match.
*/
void getFilterResults(Eigen::Ref<vectX_t<T>> results, const vectX_t<T>& data);
/*! \brief Reset the data and filtered data. */ /*! \brief Reset the data and filtered data. */
void resetFilter() noexcept; void resetFilter() noexcept;
/*!< \brief Return the filter type */
Type type() const noexcept { return (m_center == 0 ? Type::OneSided : Type::Centered); }
/*! \brief Get digital filter coefficients. /*! \brief Get digital filter coefficients.
* *
* It will automatically resize the given vectors. * It will automatically resize the given vectors.
@ -81,6 +85,10 @@ public:
* \param[out] bCoeff Numerator coefficients of the filter in decreasing order. * \param[out] bCoeff Numerator coefficients of the filter in decreasing order.
*/ */
void getCoeffs(vectX_t<T>& aCoeff, vectX_t<T>& bCoeff) const noexcept; void getCoeffs(vectX_t<T>& aCoeff, vectX_t<T>& bCoeff) const noexcept;
/*! \brief Return coefficients of the denominator polynome. */
const vectX_t<T>& aCoeff() const noexcept { return m_aCoeff; }
/*! \brief Return coefficients of the numerator polynome. */
const vectX_t<T>& bCoeff() const noexcept { return m_bCoeff; }
/*! \brief Return the order the denominator polynome order of the filter. */ /*! \brief Return the order the denominator polynome order of the filter. */
Eigen::Index aOrder() const noexcept { return m_aCoeff.size(); } Eigen::Index aOrder() const noexcept { return m_aCoeff.size(); }
/*! \brief Return the order the numerator polynome order of the filter. */ /*! \brief Return the order the numerator polynome order of the filter. */
@ -94,11 +102,18 @@ protected:
/*! \brief Constructor. /*! \brief Constructor.
* \param aCoeff Denominator coefficients of the filter in decreasing order. * \param aCoeff Denominator coefficients of the filter in decreasing order.
* \param bCoeff Numerator coefficients of the filter in decreasing order. * \param bCoeff Numerator coefficients of the filter in decreasing order.
* \param center
*/ */
GenericFilter(const vectX_t<T>& aCoeff, const vectX_t<T>& bCoeff); GenericFilter(const vectX_t<T>& aCoeff, const vectX_t<T>& bCoeff, Type type = Type::OneSided);
/*! \brief Default destructor. */ /*! \brief Default destructor. */
virtual ~GenericFilter() = default; virtual ~GenericFilter() = default;
/*! \brief Set type of filter (one-sided or centered)
*
* \param type The filter type.
* \warning bCoeff must be set before.
*/
void setType(Type type);
/*! \brief Set the new coefficients of the filters. /*! \brief Set the new coefficients of the filters.
* *
* It awaits a universal reference. * It awaits a universal reference.
@ -116,9 +131,10 @@ protected:
* \param bCoeff Numerator coefficients of the filter. * \param bCoeff Numerator coefficients of the filter.
* \return True if the filter status is set on READY. * \return True if the filter status is set on READY.
*/ */
void checkCoeffs(const vectX_t<T>& aCoeff, const vectX_t<T>& bCoeff); bool checkCoeffs(const vectX_t<T>& aCoeff, const vectX_t<T>& bCoeff, Type type);
private: private:
Eigen::Index m_center = 0; /*!< Center of the filter. 0 is a one-sided filter. Default is 0. */
bool m_isInitialized = false; /*!< Initialization state of the filter. Default is false */ bool m_isInitialized = false; /*!< Initialization state of the filter. Default is false */
vectX_t<T> m_aCoeff; /*!< Denominator coefficients of the filter */ vectX_t<T> m_aCoeff; /*!< Denominator coefficients of the filter */
vectX_t<T> m_bCoeff; /*!< Numerator coefficients of the filter */ vectX_t<T> m_bCoeff; /*!< Numerator coefficients of the filter */

Wyświetl plik

@ -44,25 +44,18 @@ T GenericFilter<T>::stepFilter(const T& data)
m_rawData[0] = data; m_rawData[0] = data;
m_filteredData[0] = 0; m_filteredData[0] = 0;
m_filteredData[0] = m_bCoeff.dot(m_rawData) - m_aCoeff.dot(m_filteredData); m_filteredData[m_center] = m_bCoeff.dot(m_rawData) - m_aCoeff.dot(m_filteredData);
return m_filteredData[0]; return m_filteredData[m_center];
} }
template <typename T> template <typename T>
vectX_t<T> GenericFilter<T>::filter(const vectX_t<T>& data) vectX_t<T> GenericFilter<T>::filter(const vectX_t<T>& data)
{
vectX_t<T> results(data.size());
getFilterResults(results, data);
return results;
}
template <typename T>
void GenericFilter<T>::getFilterResults(Eigen::Ref<vectX_t<T>> results, const vectX_t<T>& data)
{ {
Expects(m_isInitialized); Expects(m_isInitialized);
Expects(results.size() == data.size()); vectX_t<T> results(data.size());
for (Eigen::Index i = 0; i < data.size(); ++i) for (Eigen::Index i = 0; i < data.size(); ++i)
results(i) = stepFilter(data(i)); results(i) = stepFilter(data(i));
return results;
} }
template <typename T> template <typename T>
@ -72,13 +65,20 @@ void GenericFilter<T>::resetFilter() noexcept
m_rawData.setZero(m_bCoeff.size()); m_rawData.setZero(m_bCoeff.size());
} }
template <typename T>
void GenericFilter<T>::setType(Type type)
{
Expects(type == Type::Centered ? m_bCoeff.size() > 2 && m_bCoeff.size() % 2 == 1 : true);
m_center = (type == Type::OneSided ? 0 : (m_bCoeff.size() - 1) / 2);
}
template <typename T> template <typename T>
template <typename T2> template <typename T2>
void GenericFilter<T>::setCoeffs(T2&& aCoeff, T2&& bCoeff) void GenericFilter<T>::setCoeffs(T2&& aCoeff, T2&& bCoeff)
{ {
static_assert(std::is_convertible_v<T2, vectX_t<T>>, "The coefficients types should be convertible to vectX_t<T>"); static_assert(std::is_convertible_v<T2, vectX_t<T>>, "The coefficients types should be convertible to vectX_t<T>");
checkCoeffs(aCoeff, bCoeff); Expects(checkCoeffs(aCoeff, bCoeff, (m_center == 0 ? Type::OneSided : Type::Centered)));
m_aCoeff = aCoeff; m_aCoeff = aCoeff;
m_bCoeff = bCoeff; m_bCoeff = bCoeff;
normalizeCoeffs(); normalizeCoeffs();
@ -96,13 +96,14 @@ void GenericFilter<T>::getCoeffs(vectX_t<T>& aCoeff, vectX_t<T>& bCoeff) const n
// Protected functions // Protected functions
template <typename T> template <typename T>
GenericFilter<T>::GenericFilter(const vectX_t<T>& aCoeff, const vectX_t<T>& bCoeff) GenericFilter<T>::GenericFilter(const vectX_t<T>& aCoeff, const vectX_t<T>& bCoeff, Type type)
: m_aCoeff(aCoeff) : m_aCoeff(aCoeff)
, m_bCoeff(bCoeff) , m_bCoeff(bCoeff)
, m_filteredData(aCoeff.size()) , m_filteredData(aCoeff.size())
, m_rawData(bCoeff.size()) , m_rawData(bCoeff.size())
{ {
checkCoeffs(aCoeff, bCoeff); Expects(checkCoeffs(aCoeff, bCoeff, type));
m_center = (type == Type::OneSided ? 0 : (bCoeff.size() - 1) / 2);
normalizeCoeffs(); normalizeCoeffs();
resetFilter(); resetFilter();
m_isInitialized = true; m_isInitialized = true;
@ -120,11 +121,10 @@ void GenericFilter<T>::normalizeCoeffs()
} }
template <typename T> template <typename T>
void GenericFilter<T>::checkCoeffs(const vectX_t<T>& aCoeff, const vectX_t<T>& bCoeff) bool GenericFilter<T>::checkCoeffs(const vectX_t<T>& aCoeff, const vectX_t<T>& bCoeff, Type type)
{ {
Expects(aCoeff.size() > 0); bool centering = (type == Type::Centered ? (bCoeff.size() % 2 == 1) : true);
Expects(std::abs(aCoeff[0]) > std::numeric_limits<T>::epsilon()); return aCoeff.size() > 0 && std::abs(aCoeff[0]) > std::numeric_limits<T>::epsilon() && bCoeff.size() > 0 && centering;
Expects(bCoeff.size() > 0);
} }
} // namespace difi } // namespace difi

Wyświetl plik

@ -60,4 +60,32 @@ public:
int windowSize() const noexcept { return bOrder(); } int windowSize() const noexcept { return bOrder(); }
}; };
/*! \brief Centered moving average digital filter.
*
* This is a specialization of a digital filter in order to use a centered moving average.
* \tparam T Floating type.
*/
template <typename T>
class CenteredMovingAverage : public DigitalFilter<T> {
public:
/*! \brief Default uninitialized constructor. */
CenteredMovingAverage() = default;
/*! \brief Constructor.
* \param windowSize Size of the moving average window.
*/
CenteredMovingAverage(int windowSize)
{
setWindowSize(windowSize);
}
/*! \brief Set the size of the moving average window. */
void setWindowSize(int windowSize)
{
Expects(windowSize > 2 && windowSize % 2 == 1);
setCoeffs(vectX_t<T>::Constant(1, T(1)), vectX_t<T>::Constant(windowSize, T(1) / windowSize));
setType(Type::Centered);
}
/*! \brief Get the size of the moving average window. */
int windowSize() const noexcept { return bOrder(); }
};
} // namespace difi } // namespace difi