Un algorithme qui estime en temps réel ce qu'on ne mesure pas directement, à partir de mesures bruitées. À chaque instant, il prédit l'état avec un modèle simple de la dynamique, puis corrige cette prédiction avec la nouvelle mesure, en pondérant selon la confiance accordée à chacune. Il est au cœur du GPS, de la navigation, et de nombreux modèles de séries temporelles.
En voiture dans un tunnel, vous savez où vous êtes à peu près grâce à votre vitesse. À la sortie, un panneau vous donne votre position ; vous corrigez votre estimation, sans l'effacer complètement si le panneau est flou.
À partir de l'état estimé (position, vitesse), le modèle prévoit l'état suivant : nouvelle position = position + vitesse × temps. L'incertitude grandit.
La mesure arrive (le point GPS). L'écart entre mesure et prédiction s'appelle l'innovation.
Le gain de Kalman décide quelle part de l'écart retenir : proche de 1 si la mesure est fiable, proche de 0 si elle est très bruitée. L'état corrigé et son incertitude servent au pas suivant.
Un véhicule de livraison roule autour de 50 km/h, avec des accélérations et des freinages. Le GPS donne sa position à 10 m près. Sa vitesse n'est pas mesurée. Le code simule 5 minutes de trajet, faute de jeu de données de géolocalisation.
Sur la simulation Python, l'erreur de position passe de 10 m (GPS brut) à 4,5 m. Surtout, la vitesse, qu'aucun capteur ne mesure, est estimée à 0,8 m/s près, alors que la calculer à partir de deux points GPS successifs donne des erreurs de près de 14 m/s.
En simulation, on connaît la vérité et on mesure l'erreur directement. Sur données réelles, on vérifie que les innovations (écarts mesure moins prédiction) sont centrées et sans structure : sinon le modèle ou les variances sont mal réglés.
En production, on utilise souvent un package : KFAS ou StructTS (base) en R, pykalman, filterpy ou statsmodels en Python. Les choix restent les mêmes.
Ce que le filtre sait de la physique : ici, la position avance de la vitesse à chaque seconde. Un modèle trop pauvre laisse des erreurs systématiques ; un modèle trop riche devient instable.
À quel point l'état peut changer de façon imprévue (accélérations, chocs). Q grand : le filtre suit vite mais reste nerveux. Q petit : il lisse beaucoup mais réagit en retard.
La précision du capteur, souvent donnée par le constructeur. C'est le rapport entre Q et R qui fixe le gain, donc le compromis entre réactivité et lissage.
L'état initial et son incertitude. Une incertitude initiale large laisse les premières mesures corriger vite. On écarte les premiers instants, le rodage, de l'évaluation.
# Suivi de livraison : filtre de Kalman en R
set.seed(42)
n <- 300; sigma_acc <- 0.3; sigma_gps <- 10 # 300 secondes, GPS précis à 10 m près
transition <- matrix(c(1, 0, 1, 1), 2, 2) # position += vitesse x 1 s
G <- c(0.5, 1) # effet d'une accélération
H <- c(1, 0) # le GPS ne mesure que la position
# Simulation : trajet réel (caché), départ à 14 m/s (50 km/h), et positions GPS bruitées
vrai <- matrix(0, n, 2)
vrai[1, ] <- c(0, 14)
for (i in 2:n) vrai[i, ] <- transition %*% vrai[i - 1, ] + G * rnorm(1, 0, sigma_acc)
gps <- vrai[, 1] + rnorm(n, 0, sigma_gps)
# Filtre : prédire avec la physique, puis corriger avec la mesure
Q <- sigma_acc^2 * outer(G, G)
R <- sigma_gps^2
x <- c(gps[1], 0); P <- diag(c(R, 100))
estim <- matrix(0, n, 2)
for (i in 1:n) {
if (i > 1) x <- as.vector(transition %*% x) # prédiction
if (i > 1) P <- transition %*% P %*% t(transition) + Q
K <- as.vector(P %*% H) / as.numeric(t(H) %*% P %*% H + R) # gain de Kalman
x <- x + K * (gps[i] - sum(H * x)) # correction
P <- P - outer(K, as.vector(H %*% P))
estim[i, ] <- x
}
# Erreurs moyennes après 30 secondes de rodage
rmse <- function(e) round(sqrt(mean(e[31:n]^2)), 2)
cat("Position, erreur GPS brut / Kalman (m) :",
rmse(gps - vrai[, 1]), "/", rmse(estim[, 1] - vrai[, 1]), "\n")
cat("Vitesse, erreur écart GPS / Kalman (m/s) :",
rmse(c(0, diff(gps)) - vrai[, 2]), "/", rmse(estim[, 2] - vrai[, 2]), "\n")
# Suivi de livraison : filtre de Kalman en Python
import numpy as np
rng = np.random.default_rng(42)
n, sigma_acc, sigma_gps = 300, 0.3, 10.0 # 300 secondes, GPS précis à 10 m près
transition = np.array([[1.0, 1.0], [0.0, 1.0]]) # position += vitesse x 1 s
G = np.array([0.5, 1.0]) # effet d'une accélération aléatoire
H = np.array([1.0, 0.0]) # le GPS ne mesure que la position
# Simulation : trajet réel (caché), départ à 14 m/s (50 km/h), et positions GPS bruitées
vrai = np.zeros((n, 2))
vrai[0] = [0.0, 14.0]
for t in range(1, n):
vrai[t] = transition @ vrai[t - 1] + G * rng.normal(0, sigma_acc)
gps = vrai[:, 0] + rng.normal(0, sigma_gps, n)
# Filtre : prédire avec la physique, puis corriger avec la mesure
Q, R = sigma_acc ** 2 * np.outer(G, G), sigma_gps ** 2
x, P = np.array([gps[0], 0.0]), np.diag([R, 100.0])
estim = np.zeros((n, 2))
for t in range(n):
if t > 0:
x, P = transition @ x, transition @ P @ transition.T + Q # prédiction
K = P @ H / (H @ P @ H + R) # gain de Kalman
x, P = x + K * (gps[t] - H @ x), P - np.outer(K, H @ P) # correction
estim[t] = x
# Erreurs moyennes après 30 secondes de rodage
rmse = lambda e: round(float(np.sqrt(np.mean(e[30:] ** 2))), 2)
print("Position, erreur GPS brut / Kalman (m) :",
rmse(gps - vrai[:, 0]), "/", rmse(estim[:, 0] - vrai[:, 0]))
print("Vitesse, erreur écart GPS / Kalman (m/s) :",
rmse(np.diff(gps, prepend=gps[0]) - vrai[:, 1]), "/", rmse(estim[:, 1] - vrai[:, 1]))
À estimer l'état d'un système qui évolue dans le temps à partir de mesures imparfaites : position et vitesse d'un véhicule, niveau réel d'un capteur, tendance d'une série. On l'utilise en navigation, en robotique, en finance et dans les modèles de séries temporelles.
C'est le poids donné à la nouvelle mesure pour corriger la prédiction. Il dépend de l'incertitude de la prédiction et du bruit de la mesure. Si la mesure est très précise, le gain est proche de 1 ; si elle est très bruitée, il est proche de 0.
Le filtre n'utilise que les mesures passées et présentes : il sert en temps réel. Le lisseur utilise toute la série, y compris les mesures postérieures, pour réestimer chaque instant après coup. Il est plus précis, mais seulement pour analyser l'historique.
Un filtre de Kalman sur un niveau aléatoire, une fois stabilisé, revient à un lissage exponentiel simple.
Voir la fiche → l'état caché discretMême logique d'état caché et de mesures bruitées, mais l'état est une catégorie (en marche, dégradé, en panne).
Voir la fiche → l'autre façon de voir une sérieUn ARIMA s'écrit aussi en espace d'états : les logiciels estiment ses paramètres avec un filtre de Kalman.
Voir la fiche →Dataistudio forme les équipes au machine learning et à l'IA, sur des cas concrets.
Nous utilisons des cookies de mesure d'audience et de suivi publicitaire pour comprendre la fréquentation du site et l'efficacité de nos annonces. Rien n'est déposé sans votre accord. En savoir plus