WPILibC++ 2024.3.2
frc::LinearFilter< T > Class Template Reference

This class implements a linear, digital filter. More...

#include <frc/filter/LinearFilter.h>

Public Member Functions

 LinearFilter (std::span< const double > ffGains, std::span< const double > fbGains)
 Create a linear FIR or IIR filter. More...
 
 LinearFilter (std::initializer_list< double > ffGains, std::initializer_list< double > fbGains)
 Create a linear FIR or IIR filter. More...
 
void Reset ()
 Reset the filter state. More...
 
void Reset (std::span< const double > inputBuffer, std::span< const double > outputBuffer)
 Resets the filter state, initializing internal buffers to the provided values. More...
 
Calculate (T input)
 Calculates the next value of the filter. More...
 
LastValue () const
 Returns the last value calculated by the LinearFilter. More...
 

Static Public Member Functions

static LinearFilter< T > SinglePoleIIR (double timeConstant, units::second_t period)
 Creates a one-pole IIR low-pass filter of the form:
y[n] = (1 - gain) x[n] + gain y[n-1]
where gain = e-dt / T, T is the time constant in seconds. More...
 
static LinearFilter< T > HighPass (double timeConstant, units::second_t period)
 Creates a first-order high-pass filter of the form:
y[n] = gain x[n] + (-gain) x[n-1] + gain y[n-1]
where gain = e-dt / T, T is the time constant in seconds. More...
 
static LinearFilter< T > MovingAverage (int taps)
 Creates a K-tap FIR moving average filter of the form:
y[n] = 1/k (x[k] + x[k-1] + … + x[0]) More...
 
template<int Derivative, int Samples>
static LinearFilter< T > FiniteDifference (const wpi::array< int, Samples > stencil, units::second_t period)
 Creates a finite difference filter that computes the nth derivative of the input given the specified stencil points. More...
 
template<int Derivative, int Samples>
static LinearFilter< T > BackwardFiniteDifference (units::second_t period)
 Creates a backward finite difference filter that computes the nth derivative of the input given the specified number of samples. More...
 

Detailed Description

template<class T>
class frc::LinearFilter< T >

This class implements a linear, digital filter.

All types of FIR and IIR filters are supported. Static factory methods are provided to create commonly used types of filters.

Filters are of the form:
y[n] = (b0 x[n] + b1 x[n-1] + … + bP x[n-P]) - (a0 y[n-1] + a2 y[n-2] + … + aQ y[n-Q])

Where:
y[n] is the output at time "n"
x[n] is the input at time "n"
y[n-1] is the output from the LAST time step ("n-1")
x[n-1] is the input from the LAST time step ("n-1")
b0 … bP are the "feedforward" (FIR) gains
a0 … aQ are the "feedback" (IIR) gains
IMPORTANT! Note the "-" sign in front of the feedback term! This is a common convention in signal processing.

What can linear filters do? Basically, they can filter, or diminish, the effects of undesirable input frequencies. High frequencies, or rapid changes, can be indicative of sensor noise or be otherwise undesirable. A "low pass" filter smooths out the signal, reducing the impact of these high frequency components. Likewise, a "high pass" filter gets rid of slow-moving signal components, letting you detect large changes more easily.

Example FRC applications of filters:

  • Getting rid of noise from an analog sensor input (note: the roboRIO's FPGA can do this faster in hardware)
  • Smoothing out joystick input to prevent the wheels from slipping or the robot from tipping
  • Smoothing motor commands so that unnecessary strain isn't put on electrical or mechanical components
  • If you use clever gains, you can make a PID controller out of this class!

For more on filters, we highly recommend the following articles:
https://en.wikipedia.org/wiki/Linear_filter
https://en.wikipedia.org/wiki/Iir_filter
https://en.wikipedia.org/wiki/Fir_filter

Note 1: Calculate() should be called by the user on a known, regular period. You can use a Notifier for this or do it "inline" with code in a periodic function.

Note 2: For ALL filters, gains are necessarily a function of frequency. If you make a filter that works well for you at, say, 100Hz, you will most definitely need to adjust the gains if you then want to run it at 200Hz! Combining this with Note 1 - the impetus is on YOU as a developer to make sure Calculate() gets called at the desired, constant frequency!

Constructor & Destructor Documentation

◆ LinearFilter() [1/2]

template<class T >
frc::LinearFilter< T >::LinearFilter ( std::span< const double >  ffGains,
std::span< const double >  fbGains 
)
inline

Create a linear FIR or IIR filter.

Parameters
ffGainsThe "feedforward" or FIR gains.
fbGainsThe "feedback" or IIR gains.

◆ LinearFilter() [2/2]

template<class T >
frc::LinearFilter< T >::LinearFilter ( std::initializer_list< double >  ffGains,
std::initializer_list< double >  fbGains 
)
inline

Create a linear FIR or IIR filter.

Parameters
ffGainsThe "feedforward" or FIR gains.
fbGainsThe "feedback" or IIR gains.

Member Function Documentation

◆ BackwardFiniteDifference()

template<class T >
template<int Derivative, int Samples>
static LinearFilter< T > frc::LinearFilter< T >::BackwardFiniteDifference ( units::second_t  period)
inlinestatic

Creates a backward finite difference filter that computes the nth derivative of the input given the specified number of samples.

For example, a first derivative filter that uses two samples and a sample period of 20 ms would be


LinearFilter<double>::BackwardFiniteDifference<1, 2>(20_ms);
Template Parameters
DerivativeThe order of the derivative to compute.
SamplesThe number of samples to use to compute the given derivative. This must be one more than the order of derivative or higher.
Parameters
periodThe period in seconds between samples taken by the user.

◆ Calculate()

template<class T >
T frc::LinearFilter< T >::Calculate ( input)
inline

Calculates the next value of the filter.

Parameters
inputCurrent input value.
Returns
The filtered value at this step

◆ FiniteDifference()

template<class T >
template<int Derivative, int Samples>
static LinearFilter< T > frc::LinearFilter< T >::FiniteDifference ( const wpi::array< int, Samples >  stencil,
units::second_t  period 
)
inlinestatic

Creates a finite difference filter that computes the nth derivative of the input given the specified stencil points.

Stencil points are the indices of the samples to use in the finite difference. 0 is the current sample, -1 is the previous sample, -2 is the sample before that, etc. Don't use positive stencil points (samples from the future) if the LinearFilter will be used for stream-based online filtering (e.g., taking derivative of encoder samples in real-time).

Template Parameters
DerivativeThe order of the derivative to compute.
SamplesThe number of samples to use to compute the given derivative. This must be one more than the order of the derivative or higher.
Parameters
stencilList of stencil points.
periodThe period in seconds between samples taken by the user.

◆ HighPass()

template<class T >
static LinearFilter< T > frc::LinearFilter< T >::HighPass ( double  timeConstant,
units::second_t  period 
)
inlinestatic

Creates a first-order high-pass filter of the form:
y[n] = gain x[n] + (-gain) x[n-1] + gain y[n-1]
where gain = e-dt / T, T is the time constant in seconds.

Note: T = 1 / (2 pi f) where f is the cutoff frequency in Hz, the frequency below which the input starts to attenuate.

This filter is stable for time constants greater than zero.

Parameters
timeConstantThe discrete-time time constant in seconds.
periodThe period in seconds between samples taken by the user.

◆ LastValue()

template<class T >
T frc::LinearFilter< T >::LastValue ( ) const
inline

Returns the last value calculated by the LinearFilter.

Returns
The last value.

◆ MovingAverage()

template<class T >
static LinearFilter< T > frc::LinearFilter< T >::MovingAverage ( int  taps)
inlinestatic

Creates a K-tap FIR moving average filter of the form:
y[n] = 1/k (x[k] + x[k-1] + … + x[0])

This filter is always stable.

Parameters
tapsThe number of samples to average over. Higher = smoother but slower
Exceptions
std::runtime_errorif number of taps is less than 1.

◆ Reset() [1/2]

template<class T >
void frc::LinearFilter< T >::Reset ( )
inline

Reset the filter state.

◆ Reset() [2/2]

template<class T >
void frc::LinearFilter< T >::Reset ( std::span< const double >  inputBuffer,
std::span< const double >  outputBuffer 
)
inline

Resets the filter state, initializing internal buffers to the provided values.

These are the expected lengths of the buffers, depending on what type of linear filter used:

Type Input Buffer Size Output Buffer Size
Unspecified size of ffGains size of fbGains
Single Pole IIR 1 1
High-Pass 2 1
Moving Average taps 0
Finite Difference size of stencil 0
Backward Finite Difference Samples 0
Parameters
inputBufferValues to initialize input buffer.
outputBufferValues to initialize output buffer.
Exceptions
std::runtime_errorif size of inputBuffer or outputBuffer does not match the size of ffGains and fbGains provided in the constructor.

◆ SinglePoleIIR()

template<class T >
static LinearFilter< T > frc::LinearFilter< T >::SinglePoleIIR ( double  timeConstant,
units::second_t  period 
)
inlinestatic

Creates a one-pole IIR low-pass filter of the form:
y[n] = (1 - gain) x[n] + gain y[n-1]
where gain = e-dt / T, T is the time constant in seconds.

Note: T = 1 / (2 pi f) where f is the cutoff frequency in Hz, the frequency above which the input starts to attenuate.

This filter is stable for time constants greater than zero.

Parameters
timeConstantThe discrete-time time constant in seconds.
periodThe period in seconds between samples taken by the user.

The documentation for this class was generated from the following file: