Filtres linéaires

Le premier type de filtre (et le plus couramment utilisé) supporté par WPILib est un filtre linéaire - ou, plus précisément, un filtre linéaire invariable dans le temps (LTI).

An LTI filter is, put simply, a weighted moving average - the value of the output stream at any given time is a localized, weighted average of the inputs near that time. The difference between different types of LTI filters is thus reducible to the difference in the choice of the weighting function (also known as a « window function » or an « impulse response ») used. The mathematical term for this operation is convolution.

Il existe deux grandes « catégories » de réponses impulsionnelles: les réponses impulsionnelles infinies (IIR) et les réponses impulsionnelles finies (FIR).

Les réponses impulsionnelles infinies ont un « support » infini - c’est-à-dire qu’elles sont toutes non-égales à zéro sur une région infiniment grande. Cela signifie, en gros, qu’elles ont également une « mémoire » infinie - une fois qu’une valeur apparaît dans le flux d’entrée, elle influencera toutes les sorties suivantes, pour toujours. Ceci est généralement indésirable du point de vue strict du traitement du signal, cependant les filtres avec des réponses impulsionnelles infinies ont tendance à être très faciles à réaliser car ils peuvent être exprimés par de simples relations de récursivité.

Les réponses impulsionnelles finies ont un « support » fini - c’est-à-dire qu’elles sont non-égales à zéro sur une région limitée. Le filtre FIR « typique  » est une moyenne mobile plate - c’est-à-dire qu’il suffit de régler la sortie égale à la moyenne des n dernières entrées. Les filtres FIR ont tendance à avoir des propriétés plus souhaitables que les filtres IIR, mais leur calcul est plus long.

Linear filters are supported in WPILib through the LinearFilter class (Java, C++, , Python).

Création d’un LinearFilter

Note

La classe C ++ LinearFilter est basée sur le type de données utilisé pour l’entrée.

Note

Étant donné que les filtres ont une «mémoire», chaque flux d’entrée nécessite son propre objet filtre. N’essayez pas d’utiliser le même objet de filtre pour plusieurs flux d’entrée.

Bien qu’il soit possible d’instancier directement la classe LinearFilter pour créer un filtre personnalisé, il est beaucoup plus pratique (et courant) d’utiliser l’une des méthodes fournies dans WPIlib, à la place:

Filtre singlePoleIIR

Un graphique avec deux pics avec l’entrée suivant de près le signal cible.

The singlePoleIIR() factory method creates a single-pole infinite impulse response filter which performs exponential smoothing. This is the « go-to, » « first-try » low-pass filter in most applications; it is computationally trivial and works in most cases.

// Creates a new Single-Pole IIR filter
// Time constant is 0.1 seconds
// Period is 0.02 seconds - this is the standard FRC main loop period
LinearFilter filter = LinearFilter.singlePoleIIR(0.1, 0.02);
// Creates a new Single-Pole IIR filter
// Time constant is 0.1 seconds
// Period is 0.02 seconds - this is the standard FRC main loop period
frc::LinearFilter<double> filter = frc::LinearFilter<double>::SinglePoleIIR(0.1_s, 0.02_s);
from wpimath.filter import LinearFilter

# Creates a new Single-Pole IIR filter
# Time constant is 0.1 seconds
# Period is 0.02 seconds - this is the standard FRC main loop period
filter = LinearFilter.singlePoleIIR(0.1, 0.02)

Le paramètre « time constant » détermine « l’échelle de temps caractéristique » de la réponse impulsionnelle du filtre; le filtre annulera toute dynamique de signal se produisant sur des échelles de temps significativement plus courtes que définie par ce paramètre. De même, c’est aussi l’échelle de temps approximative du retard de phase généré. L’inverse de cette échelle de temps, multiplié par 2 pi, est la « fréquence de coupure » du filtre.

Le paramètre « période » est la période de temps entre les appels successifs de la méthode calculate() propre au filtre. Pour la grande majorité des implémentations, ce sera la période standard de boucle du robot principal, soit 20 mSec.

Filtre à moyenne mobile (movingAverage)

Un graphique avec deux pics avec l’entrée suivant de près le signal cible.

La méthode movingAverage crée un simple filtre à moyenne mobile. Il s’agit du filtre FIR passe-bas le plus simple possible et il est utile dans bon nombre des mêmes contextes que le filtre IIR unipolaire. Il est un peu plus long à calculer, mais se comporte généralement de manière un peu plus agréable.

// Creates a new flat moving average filter
// Average will be taken over the last 5 samples
LinearFilter filter = LinearFilter.movingAverage(5);
// Creates a new flat moving average filter
// Average will be taken over the last 5 samples
frc::LinearFilter<double> filter = frc::LinearFilter<double>::MovingAverage(5);
from wpimath.filter import LinearFilter

# Creates a new flat moving average filter
# Average will be taken over the last 5 samples
filter = LinearFilter.movingAverage(5)

Le paramètre « taps » est le nombre d’échantillons qui seront inclus dans la moyenne mobile. Cela se comporte de manière similaire au paramètre « time constant » ci-dessus - la constante de temps effective est le nombre d’échantillons multiplié par la période à laquelle calculate() est appelé (typiquement 20mSec).

Filter passe-haut (highPass)

Un graphique comportant deux pics excepté que le filtrage passe haut montre uniquement le taux de changement centré autour de 0.

La méthode highPass crée un simple filtre passe-haut à réponse impulsionnelle infinie de premier ordre. C’est le « pendant » du singlePoleIIR.

// Creates a new high-pass IIR filter
// Time constant is 0.1 seconds
// Period is 0.02 seconds - this is the standard FRC main loop period
LinearFilter filter = LinearFilter.highPass(0.1, 0.02);
// Creates a new high-pass IIR filter
// Time constant is 0.1 seconds
// Period is 0.02 seconds - this is the standard FRC main loop period
frc::LinearFilter<double> filter = frc::LinearFilter<double>::HighPass(0.1_s, 0.02_s);
from wpimath.filter import LinearFilter

# Creates a new high-pass IIR filter
# Time constant is 0.1 seconds
# Period is 0.02 seconds - this is the standard FRC main loop period
filter = LinearFilter.highPass(0.1, 0.02)

Le paramètre « time constant » détermine « l’échelle de temps caractéristique » de la réponse impulsionnelle du filtre; le filtre annulera toute dynamique de signal qui se produit sur des échelles de temps beaucoup plus longues que définie par ce paramètre. De même, il s’agit également de la durée approximative de l’avance de phase généré. L’inverse de cette échelle de temps, multiplié par 2 pi, est la « fréquence de coupure » du filtre.

Le paramètre « période » est la période de temps entre les appels successifs de la méthode calculate() propre au filtre. Pour la grande majorité des implémentations, ce sera la période standard de boucle du robot principal, soit 20 mSec.

Utilisation d’un LinearFilter

Note

Pour que le filtre créé obéisse au paramètre d’échelle de temps spécifié, et fonctionne correctement, sa fonction calculate() doit être appelée régulièrement à la période spécifiée. Si, pour une raison quelconque, une interruption significative des appels calculate() doit se produire, la méthode reset() du filtre doit être appelée avant de réutiliser le filtre.

Une fois votre filtre créé, son utilisation est simple - il suffit d’appeler la méthode calculate() avec l’entrée la plus récente pour obtenir la sortie filtrée:

// Calculates the next value of the output
filter.calculate(input);
// Calculates the next value of the output
filter.Calculate(input);
# Calculates the next value of the output
filter.calculate(input)