[Ars Control Lab page] [Andrea Pupa] [Italo Almirante]
This repo implements several signals/commands filters as c++ classes, under the same namespace.
To install the library, follow the instructions below (jump the workspace command line if you already have it):
mdkir -p your_catkin_ws/src
cd your_catkin_ws/src
git clone git@github.com:ARSControl/filters_c.git
cd ..
catkin_build
Alternatively, you can compile using the command
catkin_make
The available filters are:
butterworth_filter
hystheresis
mobile_average_filter
rc_filter
-
Buttherworth Filter:
It's a low pass filter which implements the following formulas:
low_pass_filter_coeff = 2; // default value scale_term_ = 1.0 / (1.0 + low_pass_filter_coeff); // averages all measurements feedback_term_ = 1.0 - low_pass_filter_coeff; // weight of previous filter x_f[k] = scale_term_*{x[k] + x[k-1] - f*x_f[k-1]};where x_f[k] is the filtered measurement at the instant k, x_f[k-1] is the filtered measurement at the instant k-1, x[k] is the measurement at the instant k and x[k-1] is the measurement at the instant k-1.
The bigger the coefficient, the more you consider the last filtered signal(s). The lower it is, the more you consider the last not-filtered signal(s).
-
Hysteresis:
It's a filter which nulls one of the dimensions of the signal when it overcomes a given threshold. If such a signal is over the value for a certain number of times, the hysteresis is turned off.
-
Mobile Average Filter:
It's a low pass filter which implements the following formulas:
X[i] = X[i+1] for i = 0 ... window_size - 1; X[window_size] = x[k]; x_f[k] = X*c for i = 0 ... window_size;where x_f[k] is the filtered signal at instant k, x[k] is the measurement at instant k, X is the matrices with the last "window_size" measurements (the windows are on the rows and the dimensions on the columns), and "c" is a vector of coefficients which weights the importance given to the last "window_size" measurements (by default, they are set all as equally important, and they sum to 1 to grant the correct averaging computation).
-
RC Filter:
It's the standard implementation of the low-pass RC filter. It depends on params "fs" (cut off frequency) and "ts" (sampling time of the filter's calculations). Two options are implemented to give the chance to make a faster (and approximate) formula or a slower (and more accurate) one. See "Use a filter" section for details. The two aforementioned formulas deal with the factor "alpha" which regulates the filter, here below explained:
alpha = 1 - std::exp(-2 * M_PI * fs * ts); // Simplified version alpha = (2 * M_PI * ts * fs) / ( 2 * M_PI * ts* fs + 1); // Extended versionAfter the above parameters are set, the filtering occurs as below:
x_f[k] = x_f[k-1] + (x[k] - x_f[k-1]) * alpha;where x_f[k] is the filtered signal at instant k, x_f[k-1] is the filtered signal at instant k-1 and x[k] is the new signal measured.
To include the library, write the following line in your "package.xml" file within your personal package
<depend>filters</depend>
and the following line in your "CMakeLists.txt" file within your personal package.
find_package(filters)
To create and use a filter within your code, you can find their corresponding attributes in the "src" and "include" folders. The instantiation of a filter object should be done in your header file with the following lines:
#include <filters/RCFilter.h>
filters::RCFilter *filter_;
To use the variable "filter_" in your source file, call:
filter_ = new filters::RCFilter(<attribute_1>, <attribute_2>, ...);
-
Buttherworth Filter:
ButterworthFilter(int dim, double low_pass_filter_coeff);Use the above line to call a Butterworth filter were "dim" is the dimension of the data to filter (e.g. if you have a state described as [x,y], your dimension is 2) and "low_pass_filter_coeff" is the coefficient which implements the filter. Its default (and suggested) value is 2.
To apply the filter in your code, apply the following code:
filter_ = new filters::ButterworthFilter(your_dim, your_coeff); /* Get your measurement */ Eigen::VectorXd measurement = get_your_measurement(); Eigen::VectorXd filtered_measurement = filter_.filter(measurement);To reset the filter:
Eigen::VectorXd reset_data = Eigen::VectorXd::Zero(dim); filter_->reset(reset_data); -
Hysteresis:
Hysteresis(int dim, double onThreshold, int offWindow); Hysteresis(int dim, Eigen::VectorXd onThreshold, Eigen::VectorXd offWindow);Use the above line to call a Hysteresis filter were "dim" is the dimension of the data to filter (e.g. if you have a state described as [x,y], your dimension is 2) "onThreshold" is the threshold to activate the filter and "offWindow" is the number of samples required to turn off hysteresis.
To apply the filter in your code, apply the following code:
filter_ = new filters::Hysteresis(your_dim, your_onThreshold, your_offWindow); /* Get your measurement */ Eigen::VectorXd measurement = get_your_measurement(); Eigen::VectorXd filtered_measurement = filter_.apply(measurement);To reset the filter:
Eigen::VectorXd reset_data = Eigen::VectorXd::Zero(dim); filter_->reset(reset_data); -
Mobile Average Filter:
MobileAverageFilter(int dim, int window, Eigen::VectorXd coefficients);Use the above line to call a Mobile Average filter were "dim" is the dimension of the data to filter (e.g. if you have a state described as [x,y], your dimension is 2), "window" is the number of last measurements to filter, and "coefficients" are the weight to average such measurements.
To apply the filter in your code, apply the following code:
filter_ = new filters::MobileAverageFilter(your_dim, your_window_size, your_coeff); /* Get your measurement */ Eigen::VectorXd measurement = get_your_measurement(); Eigen::VectorXd filtered_measurement = filter_.filter(measurement);To reset the filter:
Eigen::VectorXd reset_data = Eigen::VectorXd::Zero(dim); filter_->reset(reset_data); -
RC Filter:
RCFilter(int dim, double cut_off_frequency, double sampling_time, bool simplified = false);Use the above line to call a RCFilter filter were "dim" is the dimension of the data to filter (e.g. if you have a state described as [x,y], your dimension is 2), "cut_off_frequency" is the upper frequency of the filter and "sampling_time" is its time sample for calculations. The attribute "simplified" is done to have the possibility to implement a faster approximated formula.
To apply the filter in your code, apply the following code:
filter_ = new filters::RCFilter(your_dim, your_freq, your_ts); /* Get your measurement */ Eigen::VectorXd measurement = get_your_measurement(); Eigen::VectorXd filtered_measurement = filter_.filter(measurement);To reset the filter:
Eigen::VectorXd reset_data = Eigen::VectorXd::Zero(dim); filter_->reset(reset_data);
If you want to speed your code running performances, you can add the following lines to the "CMakeLists".txt of this package:
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
Or alternatively:
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
Your code should run faster, despite the longer compiler time needed. By default, O3 is set. You can maually comment it, but it's strongly suggested to use it.
Please if you have any issue in compiling the nodes or using it, you can open an issue on git or send me an email at my email address: andrea.pupa@unimore.it.