Voici un simple filtre de Kalman qui pourrait être utilisé exactement dans cette situation. Cela vient d'un travail que j'ai effectué sur les appareils Android.
La théorie générale des filtres de Kalman concerne les estimations des vecteurs, la précision des estimations étant représentée par des matrices de covariance. Cependant, pour estimer l'emplacement sur les appareils Android, la théorie générale se réduit à un cas très simple. Les fournisseurs de localisation Android donnent l'emplacement sous forme de latitude et de longitude, avec une précision qui est spécifiée sous la forme d'un nombre unique mesuré en mètres. Cela signifie qu'au lieu d'une matrice de covariance, la précision du filtre de Kalman peut être mesurée par un seul nombre, même si l'emplacement dans le filtre de Kalman est mesuré par deux nombres. De plus, le fait que la latitude, la longitude et les mètres soient effectivement des unités différentes peut être ignoré, car si vous mettez des facteurs de mise à l'échelle dans le filtre de Kalman pour les convertir tous dans les mêmes unités,
Le code pourrait être amélioré, car il suppose que la meilleure estimation de l'emplacement actuel est le dernier emplacement connu, et si quelqu'un se déplace, il devrait être possible d'utiliser les capteurs d'Android pour produire une meilleure estimation. Le code a un seul paramètre libre Q, exprimé en mètres par seconde, qui décrit la vitesse à laquelle la précision diminue en l'absence de toute nouvelle estimation d'emplacement. Un paramètre Q plus élevé signifie que la précision diminue plus rapidement. Les filtres de Kalman fonctionnent généralement mieux lorsque la précision diminue un peu plus rapidement que ce à quoi on pourrait s'attendre, donc pour me promener avec un téléphone Android, je trouve que Q = 3 mètres par seconde fonctionne bien, même si je marche généralement plus lentement que cela. Mais si vous voyagez dans une voiture rapide, un nombre beaucoup plus important doit évidemment être utilisé.
public class KalmanLatLong {
private final float MinAccuracy = 1;
private float Q_metres_per_second;
private long TimeStamp_milliseconds;
private double lat;
private double lng;
private float variance; // P matrix. Negative means object uninitialised. NB: units irrelevant, as long as same units used throughout
public KalmanLatLong(float Q_metres_per_second) { this.Q_metres_per_second = Q_metres_per_second; variance = -1; }
public long get_TimeStamp() { return TimeStamp_milliseconds; }
public double get_lat() { return lat; }
public double get_lng() { return lng; }
public float get_accuracy() { return (float)Math.sqrt(variance); }
public void SetState(double lat, double lng, float accuracy, long TimeStamp_milliseconds) {
this.lat=lat; this.lng=lng; variance = accuracy * accuracy; this.TimeStamp_milliseconds=TimeStamp_milliseconds;
}
/// <summary>
/// Kalman filter processing for lattitude and longitude
/// </summary>
/// <param name="lat_measurement_degrees">new measurement of lattidude</param>
/// <param name="lng_measurement">new measurement of longitude</param>
/// <param name="accuracy">measurement of 1 standard deviation error in metres</param>
/// <param name="TimeStamp_milliseconds">time of measurement</param>
/// <returns>new state</returns>
public void Process(double lat_measurement, double lng_measurement, float accuracy, long TimeStamp_milliseconds) {
if (accuracy < MinAccuracy) accuracy = MinAccuracy;
if (variance < 0) {
// if variance < 0, object is unitialised, so initialise with current values
this.TimeStamp_milliseconds = TimeStamp_milliseconds;
lat=lat_measurement; lng = lng_measurement; variance = accuracy*accuracy;
} else {
// else apply Kalman filter methodology
long TimeInc_milliseconds = TimeStamp_milliseconds - this.TimeStamp_milliseconds;
if (TimeInc_milliseconds > 0) {
// time has moved on, so the uncertainty in the current position increases
variance += TimeInc_milliseconds * Q_metres_per_second * Q_metres_per_second / 1000;
this.TimeStamp_milliseconds = TimeStamp_milliseconds;
// TO DO: USE VELOCITY INFORMATION HERE TO GET A BETTER ESTIMATE OF CURRENT POSITION
}
// Kalman gain matrix K = Covarariance * Inverse(Covariance + MeasurementVariance)
// NB: because K is dimensionless, it doesn't matter that variance has different units to lat and lng
float K = variance / (variance + accuracy * accuracy);
// apply K
lat += K * (lat_measurement - lat);
lng += K * (lng_measurement - lng);
// new Covarariance matrix is (IdentityMatrix - K) * Covarariance
variance = (1 - K) * variance;
}
}
}