kopia lustrzana https://github.com/vsamy/DiFipp
rodzic
75e8924949
commit
3320b425bd
|
@ -50,6 +50,35 @@ public:
|
|||
: 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
|
|
@ -35,6 +35,9 @@
|
|||
|
||||
namespace difi {
|
||||
|
||||
// TODO: noexcept(Function of gsl variable)
|
||||
// TODO: constructor with universal refs
|
||||
|
||||
/*! \brief Low-level 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 {
|
||||
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:
|
||||
/*! \brief Filter a new data.
|
||||
*
|
||||
|
@ -64,16 +73,11 @@ public:
|
|||
* \return Filtered signal.
|
||||
*/
|
||||
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. */
|
||||
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.
|
||||
*
|
||||
* It will automatically resize the given vectors.
|
||||
|
@ -81,6 +85,10 @@ public:
|
|||
* \param[out] bCoeff Numerator coefficients of the filter in decreasing order.
|
||||
*/
|
||||
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. */
|
||||
Eigen::Index aOrder() const noexcept { return m_aCoeff.size(); }
|
||||
/*! \brief Return the order the numerator polynome order of the filter. */
|
||||
|
@ -94,11 +102,18 @@ protected:
|
|||
/*! \brief Constructor.
|
||||
* \param aCoeff Denominator 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. */
|
||||
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.
|
||||
*
|
||||
* It awaits a universal reference.
|
||||
|
@ -116,9 +131,10 @@ protected:
|
|||
* \param bCoeff Numerator coefficients of the filter.
|
||||
* \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:
|
||||
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 */
|
||||
vectX_t<T> m_aCoeff; /*!< Denominator coefficients of the filter */
|
||||
vectX_t<T> m_bCoeff; /*!< Numerator coefficients of the filter */
|
||||
|
|
|
@ -44,25 +44,18 @@ T GenericFilter<T>::stepFilter(const T& data)
|
|||
|
||||
m_rawData[0] = data;
|
||||
m_filteredData[0] = 0;
|
||||
m_filteredData[0] = m_bCoeff.dot(m_rawData) - m_aCoeff.dot(m_filteredData);
|
||||
return m_filteredData[0];
|
||||
m_filteredData[m_center] = m_bCoeff.dot(m_rawData) - m_aCoeff.dot(m_filteredData);
|
||||
return m_filteredData[m_center];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
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(results.size() == data.size());
|
||||
vectX_t<T> results(data.size());
|
||||
for (Eigen::Index i = 0; i < data.size(); ++i)
|
||||
results(i) = stepFilter(data(i));
|
||||
return results;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -72,13 +65,20 @@ void GenericFilter<T>::resetFilter() noexcept
|
|||
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 T2>
|
||||
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>");
|
||||
|
||||
checkCoeffs(aCoeff, bCoeff);
|
||||
Expects(checkCoeffs(aCoeff, bCoeff, (m_center == 0 ? Type::OneSided : Type::Centered)));
|
||||
m_aCoeff = aCoeff;
|
||||
m_bCoeff = bCoeff;
|
||||
normalizeCoeffs();
|
||||
|
@ -96,13 +96,14 @@ void GenericFilter<T>::getCoeffs(vectX_t<T>& aCoeff, vectX_t<T>& bCoeff) const n
|
|||
// Protected functions
|
||||
|
||||
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_bCoeff(bCoeff)
|
||||
, m_filteredData(aCoeff.size())
|
||||
, m_rawData(bCoeff.size())
|
||||
{
|
||||
checkCoeffs(aCoeff, bCoeff);
|
||||
Expects(checkCoeffs(aCoeff, bCoeff, type));
|
||||
m_center = (type == Type::OneSided ? 0 : (bCoeff.size() - 1) / 2);
|
||||
normalizeCoeffs();
|
||||
resetFilter();
|
||||
m_isInitialized = true;
|
||||
|
@ -120,11 +121,10 @@ void GenericFilter<T>::normalizeCoeffs()
|
|||
}
|
||||
|
||||
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);
|
||||
Expects(std::abs(aCoeff[0]) > std::numeric_limits<T>::epsilon());
|
||||
Expects(bCoeff.size() > 0);
|
||||
bool centering = (type == Type::Centered ? (bCoeff.size() % 2 == 1) : true);
|
||||
return aCoeff.size() > 0 && std::abs(aCoeff[0]) > std::numeric_limits<T>::epsilon() && bCoeff.size() > 0 && centering;
|
||||
}
|
||||
|
||||
} // namespace difi
|
|
@ -60,4 +60,32 @@ public:
|
|||
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
|
||||
|
|
Ładowanie…
Reference in New Issue