154 votes

Données GPS lisses

Je suis en train de travailler avec les données GPS, l'obtention de valeurs de chaque seconde et d'affichage de la position actuelle sur une carte. Le problème, c'est que parfois (spécialement lorsque la précision est faible) les valeurs varient beaucoup, faire de la position actuelle à un "saut" entre des points éloignés dans la carte.

Je me demandais à propos de certaines assez facile méthode pour éviter cela. Comme une première idée, j'ai pensé à rejeter les valeurs avec précision-delà d'un certain seuil, mais je suppose qu'il ya quelques autres de meilleures façons de faire. Quelle est la manière habituelle des programmes de réaliser cela?

91voto

Stochastically Points 4305

Voici un simple filtre de Kalman qui pourrait être utilisé pour exactement cette situation. Il est venu de quelques travaux que j'ai réalisés sur les appareils Android.

Générale filtre de Kalman théorie est tout au sujet des estimations pour les vecteurs, avec la précision des estimations représentés par des matrices de covariance. Toutefois, pour l'estimation d'emplacement sur les appareils Android, la théorie générale se réduit à un cas très simple. Android localisation des fournisseurs de donner l'emplacement de la latitude et de la longitude, avec une précision qui est spécifié comme un numéro unique mesuré en mètres. Cela signifie qu'au lieu de la matrice de covariance, la précision dans le filtre de Kalman peut être mesurée par un numéro unique, même si l'emplacement dans le filtre de Kalman est mesurée par deux nombres. Aussi le fait que la latitude, la longitude et la m sont de manière efficace toutes les différentes unités peuvent être ignorés, parce que si vous mettez des facteurs d'échelle dans le filtre de Kalman pour les convertir dans les mêmes unités, alors que ces facteurs d'échelle fin jusqu'à l'annulation lors de la conversion des résultats dans les unités d'origine.

Le code pourrait être améliorée, car elle 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 Android capteurs pour produire une meilleure estimation. Le code a un seul paramètre libre Q, exprimée en mètres par seconde), qui décrit la façon dont rapidement la précision se désintègre en l'absence de nouvelles estimations de localisation. Plus Q paramètre signifie que la précision se désintègre rapidement. Filtres de Kalman fonctionnent généralement mieux lorsque la précision de désintégrations un peu plus rapide que l'on pourrait attendre, donc, pour se promener avec un téléphone Android, je trouve que Q=3 mètres par seconde travaille très bien, même si en général je marche plus lentement que. Mais si vous voyagez dans une voiture rapide, un plus grand nombre 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;
        }
    }
}

80voto

Chris Arguin Points 6469

Ce que vous cherchez s'appelle un Filtre de Kalman. Il est fréquemment utilisé pour lisser les données de navigation. Il n'est pas forcément triviale, et il y a beaucoup de réglage, vous pouvez le faire, mais c'est une approche standard et fonctionne bien. Il y a un KFilter bibliothèque disponible qui est une implémentation C++.

Ma prochaine de secours seraient moindres carrés ajustement. Un filtre de Kalman facilitera la prise de données de vitesses en compte, alors qu'un ajustement des moindres carrés approche juste de l'utilisation des informations de position. Pourtant, il est certainement plus simple à mettre en œuvre et à comprendre. Il ressemble à la Bibliothèque Scientifique GNU peut avoir une mise en œuvre de cette.

4voto

KarateSnowMachine Points 397

Revenons aux filtres de Kalman ... J'ai trouvé une implémentation en C pour un filtre de Kalman pour les données GPS ici: http://github.com/lacker/ikalman Je ne l'ai pas encore essayée, mais cela semble prometteur.

4voto

Alex319 Points 998

Comme pour l'ajustement des moindres carrés, ici sont un couple d'autres choses à expérimenter:

  1. Juste parce que c'est moins de carrés ajustement ne signifie pas qu'il doit être linéaire. Vous pouvez la méthode des moindres carrés-ajustement d'une courbe quadratique pour les données, alors il serait possible d'adapter un scénario dans lequel l'utilisateur s'accélère. (À noter que par la méthode des moindres carrés en forme que je peux dire en utilisant les coordonnées que la variable dépendante et le temps comme variable indépendante.)

  2. Vous pouvez également essayer de pondération des données de points basé sur le rapport de la précision. Lorsque la précision est faible poids de ces points de données plus bas.

  3. Une autre chose que vous pourriez vouloir essayer est plutôt que d'afficher un point, si la précision est faible afficher un cercle ou quelque chose indiquant la zone dans laquelle l'utilisateur pourrait être basé sur la précision. (C'est ce que l'iPhone intégré dans l'application Google Maps.)

3voto

Aidos Points 1440

Vous pouvez également utiliser une spline. Se nourrir dans les valeurs que vous avez et d'interpoler les points entre vos points connus. La liaison avec un des moindres carrés de l'ajustement, la moyenne mobile ou le filtre de kalman (comme mentionné dans d'autres réponses) vous donne la possibilité de calculer les points entre votre "connu" des points.

Être capable d'interpoler les valeurs entre vos appelés vous donne une belle transition en douceur et un /raisonnable/ approximation de ce que les données devaient être présents si vous avez eu une haute fidélité. http://en.wikipedia.org/wiki/Spline_interpolation

Différents splines ont des caractéristiques différentes. Celui j'ai vu les plus couramment utilisés sont Akima et des splines Cubiques.

Un autre algorithme à considérer est l'Ramer-Douglas-Peucker ligne de simplification de l'algorithme, il est assez couramment utilisé dans la simplification des données GPS. (http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X