Düzgün GPS verileri


148

GPS verileriyle çalışıyorum, her saniye değerleri alıyorum ve harita üzerinde mevcut konumu görüntülüyorum. Sorun, bazen (özellikle doğruluk düşük olduğunda) değerlerin çok değişmesi ve mevcut konumun haritadaki uzak noktalar arasında "atlamasına" neden olmasıdır.

Bundan kaçınmak için yeterince kolay bir yöntem merak ediyordum. İlk fikir olarak, değerleri belirli bir eşiğin ötesinde doğrulukla atmayı düşündüm, ama sanırım yapmanın başka daha iyi yolları var. Programların bunu gerçekleştirme olağan yolu nedir?


Hız ve eğim gibi ilişkili (türevsel) değerleri hesaplamaya çalışırken, özellikle yüksek örnekleme oranlı izleme günlükleri için çok süreksiz olan (zamanın tamsayı [bir saniye] çözünürlüğü olduğundan) "GPS gürültüsünün" kötü etkilerini hissediyorum.
heltonbiker

4
(ayrıca, ana yollarda ilerliyorsanız, iyi bir [doğru, kesin] yol haritası veri kümesine sahip olmanız koşuluyla "yollara
hızlıca geçiş

Ben de en iyi doğruluk için bu sorunla karşı karşıyayım.
ViruMax

Yanıtlar:


81

İşte tam olarak bu durum için kullanılabilecek basit bir Kalman filtresi. Android cihazlarda yaptığım bazı çalışmalardan geldi.

Genel Kalman filtre teorisi, kovaryans matrisleriyle temsil edilen tahminlerin doğruluğu ile, vektörlerin tahminleriyle ilgilidir. Bununla birlikte, Android cihazlarda konumu tahmin etmek için genel teori çok basit bir duruma indirgenir. Android konum sağlayıcıları, konumu, metre cinsinden ölçülen tek bir sayı olarak belirtilen doğrulukla birlikte enlem ve boylam olarak verir. Bu, bir kovaryans matrisi yerine Kalman filtresindeki doğruluğun, Kalman filtresindeki konum iki sayı ile ölçülmesine rağmen tek bir sayı ile ölçülebileceği anlamına gelir. Ayrıca enlem, boylam ve metrelerin etkili bir şekilde tüm farklı birimler olduğu gerçeği göz ardı edilebilir, çünkü Kalman filtresine ölçekleme faktörleri koyarsanız hepsini aynı birimlere dönüştürürseniz,

Kod iyileştirilebilir, çünkü mevcut konumun en iyi tahmininin bilinen son konum olduğunu varsayar ve eğer biri hareket ediyorsa, daha iyi bir tahmin üretmek için Android sensörlerini kullanmak mümkün olmalıdır. Kodun, saniyede metre olarak ifade edilen ve yeni konum tahmini olmadığında doğruluğun ne kadar hızlı azaldığını açıklayan tek bir Q parametresi vardır. Daha yüksek bir Q parametresi, doğruluğun daha hızlı azaldığı anlamına gelir. Kalman filtreleri, doğruluk beklenenden biraz daha hızlı azaldığında genellikle daha iyi çalışır, bu nedenle bir Android telefonla dolaşmak için, genellikle daha yavaş yürümeme rağmen, Q = saniyede 3 metrenin iyi çalıştığını görüyorum. Ancak hızlı bir arabada seyahat ediyorsanız, tabii ki çok daha büyük bir sayı kullanılmalıdır.

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;
        }
    }
}

1
Varyans hesaplaması şu şekilde olmamalıdır: varyans + = TimeInc_milisaniye * TimeInc_milisaniye * Q_metres_per_second * Q_metres_per_second / 1000000
Horacio

4
@Horacio, neden böyle düşündüğünü biliyorum ama hayır! Matematiksel olarak, buradaki belirsizlik bir Wiener süreci tarafından modelleniyor (bkz. En.wikipedia.org/wiki/Wiener_process ) ve bir Wiener süreci ile varyans zamanla doğrusal olarak büyüyor. Değişken , o Wikipedia makalesindeki "İlgili işlemler" bölümündeki değişkene Q_metres_per_secondkarşılık gelir sigma. Q_metres_per_secondstandart bir sapmadır ve metre cinsinden ölçülür, bu nedenle birimleridir, metre / saniye değil metre. 1 saniye geçtikten sonra dağılımın standart sapmasına karşılık gelir.
Stokastik olarak

3
Bu yaklaşımı ve kodu denedim, ancak toplam mesafeyi çok kısalttı. Çok belirsiz yaptı.
Andreas Rudolph

1
@ user2999943 evet, onLocationChanged () 'den aldığınız koordinatları işlemek için kodu kullanın.
Stokastik olarak

2
@Koray doğruluk bilginiz yoksa Kalman filtresi kullanamazsınız. Kalman filtresinin yapmaya çalıştığı şey için tamamen temeldir.
Stokastik olarak

75

Aradığınız şeyin adı Kalman Filtresi . Gezinme verilerini düzeltmek için sıklıkla kullanılır . Mutlaka önemsiz değildir ve yapabileceğiniz çok fazla ayar vardır, ancak bu çok standart bir yaklaşımdır ve iyi çalışır. C ++ uygulaması olan bir KFilter kitaplığı mevcuttur.

Bir sonraki geri dönüşüm en küçük karelere uyacaktı . Bir Kalman filtresi, hızları hesaba katarak verileri yumuşatır, oysa en küçük kareler uydurma yaklaşımı yalnızca konumsal bilgileri kullanır. Yine de uygulanması ve anlaşılması kesinlikle daha kolaydır. Görünüşe göre GNU Bilimsel Kütüphanesi bunun bir uygulamasına sahip olabilir .


1
Teşekkürler Chris. Evet, biraz arama yaparken Kalman hakkında bir şeyler okudum, ama kesinlikle matematik bilgimin biraz ötesinde. Okunması (ve anlaşılması) kolay olan veya daha iyisi, bazı uygulamaların mevcut olduğu herhangi bir örnek kodun farkında mısınız? (C / C ++ / Java)
Al.

1
@Al Maalesef Kalman filtreleriyle tek teşhirim işten kaynaklanıyor, bu yüzden size gösteremeyeceğim harika ve zarif bir kodum var.
Chris Arguin

Sorun değil :-) Bakmaya çalıştım ama bir nedenden ötürü bu Kalman şeyi kara büyü gibi görünüyor. Çok sayıda teori sayfası var ama kod yok ya da çok az .. Teşekkürler, diğer yöntemleri deneyeceğim.
Al.

2
kalman.sourceforge.net/index.php burada Kalman filtresinin C ++ uygulamasıdır.
Rostyslav Druzhchenko

1
@ChrisArguin Hoş geldiniz. Sonuç iyi ise lütfen bana bildirin.
Rostyslav Druzhchenko

11

Bu biraz geç gelebilir ...

Bu KalmanLocationManager for Android yazdım , en yaygın iki konum sağlayıcısını, Ağ ve GPS'yi, verileri kalman filtreler ve bir LocationListener(iki 'gerçek' sağlayıcı gibi) güncellemeler sunar .

Bunu çoğunlukla okumalar arasında "interpolasyon" yapmak için kullanıyorum - örneğin her 100 milisaniyede bir güncellemeleri (konum tahminleri) almak için (bir saniyelik maksimum gps hızı yerine), bu da konumumu canlandırırken bana daha iyi bir kare hızı sağlıyor.

Aslında, her boyut için üç kalman filtresi kullanır: enlem, boylam ve yükseklik. Zaten bağımsızlar.

Bu, matris matematiğini çok daha kolay hale getirir: bir 6x6 durum geçiş matrisi kullanmak yerine, 3 farklı 2x2 matris kullanıyorum. Aslında kodda matrisleri hiç kullanmıyorum. Çözülmüş tüm denklemler ve tüm değerler ilkeldir (çift).

Kaynak kodu çalışıyor ve bir demo etkinliği var. Bazı yerlerde javadoc eksikliği için özür dilerim, yetişeceğim.


1
Kitaplık kodunuzu kullanmaya çalıştım, bazı istenmeyen sonuçlar aldım, yanlış bir şey yapıp yapmadığımdan emin değilim ... (Aşağıda resim url'si, mavi filtrelenmiş konumların yolu, turuncu ham konumlardır) app.box. com / s / w3uvaz007glp2utvgznmh8vlggvaiifk
umesh

Ortalamadan (turuncu çizgi) 'büyüdüğünü' gördüğünüz ani artışlar, ağ sağlayıcı güncellemelerine benziyor. Hem ham ağ hem de GPS güncellemelerini çizmeyi deneyebilir misiniz? Neyi başarmaya çalıştığınıza bağlı olarak, ağ güncellemesi olmadan daha iyi durumda olabilirsiniz. Btw, bu ham portakal güncellemelerini nereden alıyorsun?
villoren

1
turuncu noktalar gps sağlayıcısından, mavi ise
Kalman'dan

Bu verileri bana bir metin biçiminde gönderebilir misin? Her konum güncellemesinde Location.getProvider () alan kümesi bulunur. Tüm Location.toString () ile sadece bir dosya.
villoren

9

Her seferinde konum değişikliğinden hızı hesaplamamalısınız. GPS yanlış konumlara sahip olabilir, ancak doğru hıza sahiptir (5 km / saatin üzerinde). Bu nedenle, GPS konum damgasındaki hızı kullanın. Ve dahası, çoğu zaman işe yarasa da, bunu elbette yapmamalısınız.

GPS konumları, teslim edildiği şekliyle zaten Kalman filtrelendi, muhtemelen iyileştiremezsiniz, son işlemlerde genellikle GPS yongası ile aynı bilgilere sahip değilsiniz.

Düzeltebilirsiniz, ancak bu aynı zamanda hatalara da neden olur.

Cihaz hareketsiz durduğunda pozisyonları kaldırdığınızdan emin olun, bu, bazı cihazların / Konfigürasyonların kaldırmadığı atlama pozisyonlarını kaldırır.


5
Bunun için biraz referans verebilir misiniz lütfen?
ivyleavedtoadflax

1
Bu cümlelerde pek çok bilgi ve mesleki deneyim var, tam olarak hangi cümle için referans istiyorsun? hız için: doppler efekti ve GPS arayın. dahili Kalman? Bu temel GPS bilgisidir, GPS çipinin dahili olarak nasıl çalıştığını açıklayan her makale veya kitap. smootig hataları: her zaman düzeltme, hatalara neden olur. hareketsiz durmak? denemek.
AlexWien

2
Hareketsiz dururken "etrafta zıplamak" tek hata kaynağı değildir. Konumun etrafta sıçradığı sinyal yansımaları da (örneğin dağlardan) vardır. GPS çiplerim (örn. Garmin Dakota 20, SonyEricsson Neo) bunu filtrelemedi ... Ve gerçekte şaka olan GPS sinyallerinin barometrik basınçla birleştirilmediği zamanki yükseklik değeridir. Bu değerler filtrelenmemiş veya filtrelenmemiş değerleri görmek istemiyorum.
hgoebl

1
@AlexWien GPS, bir andaki bir noktadan toleransa kadar olan mesafeyi hesaplayarak size kalınlığa sahip bir küre, bir uydu etrafında ortalanmış bir kabuk verir . Bu kabuk hacminde bir yerdesiniz. Bu mermi hacimlerinden üçünün kesişimi size bir konum hacmi verir ve bunun merkezi sizin hesaplanmış konumunuzdur. Bildirilen bir dizi konumunuz varsa ve sensörün hareketsiz olduğunu biliyorsanız, ağırlık merkezini hesaplamak çok daha fazla mermiyi etkili bir şekilde keser ve hassasiyeti artırır. Bu durumda hata azaltılır .
Peter Wone

6
"GPS konumları, teslim edildiği şekliyle zaten Kalman filtrelendi, muhtemelen iyileştiremezsiniz". Modern akıllı telefonlar için bunu doğrulayan bir kaynağı işaret edebilirseniz (örneğin), bu çok yararlı olacaktır. Bunun kanıtını kendim göremiyorum. Bir cihazın işlenmemiş konumlarının basit Kalman filtrelemesi bile bunun doğru olmadığını kuvvetle gösterir. İşlenmemiş yerler düzensiz bir şekilde dans ederken, filtrelenmiş yerler çoğunlukla gerçek (bilinen) konuma yakın tutulur.
sobri

6

Genellikle ivmeölçer kullanırım. Kısa sürede ani bir pozisyon değişikliği, yüksek hızlanma anlamına gelir. Bu ivmeölçer telemetrisine yansıtılmazsa, bunun nedeni neredeyse kesin olarak konumu hesaplamak için kullanılan "en iyi üç" uydudaki bir değişikliktir (buna GPS ışınlaması diyorum).

Bir varlık dururken ve GPS ışınlaması nedeniyle zıplarken, ağırlık merkezini aşamalı olarak hesaplarsanız, daha büyük ve daha büyük bir mermi kümesini etkili bir şekilde keserek hassasiyeti artırırsınız.

Varlık hareketsizken bunu yapmak için, hız, yön ve doğrusal ve rotasyonel (jiroskoplarınız varsa) hızlanma verilerine dayalı olarak olası bir sonraki konumunu ve yönünü tahmin etmeniz gerekir. Bu, aşağı yukarı ünlü K filtresinin yaptığı şeydir. GPS modülü dışında her şeyi içeren bir AHRS ve bir bağlantı jakı ile donanımdaki her şeyi yaklaşık 150 $ 'a alabilirsiniz. Kart üzerinde kendi CPU ve Kalman filtrelemesine sahiptir; sonuçlar istikrarlı ve oldukça iyi. Atalet rehberliği, titreşime karşı oldukça dirençlidir, ancak zamanla sürüklenir. GPS titremeye meyillidir, ancak zamanla kaymaz, pratikte birbirlerini telafi etmek için yapılmıştır.


4

Daha az matematik / teori kullanan bir yöntem, bir seferde 2, 5, 7 veya 10 veri noktasını örneklemek ve aykırı olanları belirlemektir. Aykırı değerin bir Kalman Filtresinden daha az doğru bir ölçüsü, noktalar arasındaki tüm çift yönlü mesafeleri almak ve diğerlerinden en uzak olanı atmak için aşağıdaki algoritmayı kullanmaktır . Genellikle bu değerler, değiştirdiğiniz dıştaki değere en yakın değerle değiştirilir.

Örneğin

Beş numune noktasında A, B, C, D, E yumuşatma

ATOTAL = mesafelerin TOPLAMI AB AC AD AE

BTOTAL = mesafelerin TOPLAMI AB BC BD BE

CTOTAL = mesafelerin TOPLAMI AC BC CD CE

DTOTAL = mesafelerin TOPLAMI DA DB DC DE

ETOTAL = mesafelerin TOPLAMI EA EB EC DE

BTOTAL en büyükse, BD = min {AB, BC, BD, BE} ise B noktasını D ile değiştirirsiniz

Bu yumuşatma, aykırı değerleri belirler ve konumsal çizgiyi düzeltmek için D noktası yerine BD'nin orta noktası kullanılarak artırılabilir. Kilometreniz değişebilir ve matematiksel olarak daha titiz çözümler mevcuttur.


Teşekkürler, ben de bir şans vereceğim. Şu anki konumu düzeltmek istediğime dikkat edin, çünkü bu görüntülenen ve bazı verileri almak için kullanılıyor. Geçmiş konularla ilgilenmiyorum. İlk fikrim ağırlıklı araçlar kullanmaktı, ancak yine de en iyisinin ne olduğunu görmem gerekiyor.
Al.

1
Al, bu bir tür ağırlıklı araçlar gibi görünüyor. Herhangi bir düzleştirme yapmak istiyorsanız "geçmiş" noktaları kullanmanız gerekecektir, çünkü sistemin nerede düzeltileceğini de bilmek için mevcut konumdan daha fazlasına sahip olması gerekir. GPS'iniz saniyede bir veri noktası alıyorsa ve kullanıcınız ekrana beş saniyede bir bakıyorsa, farkına varmadan 5 veri noktasını kullanabilirsiniz! Hareketli bir ortalama da yalnızca bir dp gecikebilir.
Karl

4

En küçük karelerin sığmasına gelince, deneyebileceğiniz birkaç şey daha:

  1. En küçük karelerin sığması, doğrusal olması gerektiği anlamına gelmez. Verilere ikinci dereceden bir eğriyi en küçük karelere sığdırabilirsiniz, bu durumda bu, kullanıcının hızlandığı bir senaryoya uyacaktır. (En küçük kareler ile koordinatları bağımlı değişken ve zamanı bağımsız değişken olarak kullanmayı kastettiğimi unutmayın.)

  2. Veri noktalarını rapor edilen doğruluğa göre ağırlıklandırmayı da deneyebilirsiniz. Doğruluk düşük ağırlıkta olduğunda bu veri noktaları daha düşüktür.

  3. Denemek isteyebileceğiniz başka bir şey, tek bir noktayı görüntülemek yerine, doğruluk düşükse, bir daire veya kullanıcının bildirilen doğruluğa dayalı olabileceği aralığı belirten bir şey göstermektir. (Bu, iPhone'un yerleşik Google Haritalar uygulamasının yaptığı şeydir.)


3

Ayrıca bir spline da kullanabilirsiniz. Sahip olduğunuz değerleri besleyin ve bilinen noktalarınız arasındaki noktaları hesaplayın. Bunu en küçük kareler uydurma, hareketli ortalama veya kalman filtresi (diğer cevaplarda belirtildiği gibi) ile ilişkilendirmek size "bilinen" noktalarınız arasındaki noktaları hesaplama yeteneği verir.

Bilinenler arasındaki değerleri enterpolasyon yapabilmek, size hoş bir geçiş ve daha yüksek bir aslına sahipseniz hangi verilerin mevcut olacağına dair / makul / yaklaşık bir sonuç verir. http://en.wikipedia.org/wiki/Spline_interpolation

Farklı spline'lar farklı özelliklere sahiptir. En yaygın olarak gördüğüm Akima ve Cubic spline'lar.

Dikkate alınması gereken diğer bir algoritma, GPS verilerinin basitleştirilmesinde oldukça yaygın olarak kullanılan Ramer-Douglas-Peucker hattı basitleştirme algoritmasıdır. ( http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm )



0

İlgilenen herkes CoffeeScript ile eşleştirildi. ** edit -> omurgayı kullandığım için de özür dilerim ama anladınız.

Özniteliklere sahip bir işaretçiyi kabul etmek için biraz değiştirildi

{enlem: item.lat, boylam: item.lng, tarih: yeni Tarih (item.effective_at), doğruluk: item.gps_accuracy}

MIN_ACCURACY = 1

# mapped from http://stackoverflow.com/questions/1134579/smooth-gps-data

class v.Map.BeaconFilter

  constructor: ->
    _.extend(this, Backbone.Events)

  process: (decay,beacon) ->

    accuracy     = Math.max beacon.accuracy, MIN_ACCURACY

    unless @variance?
      # if variance nil, inititalise some values
      @variance     = accuracy * accuracy
      @timestamp_ms = beacon.date.getTime();
      @lat          = beacon.latitude
      @lng          = beacon.longitude

    else

      @timestamp_ms = beacon.date.getTime() - @timestamp_ms

      if @timestamp_ms > 0
        # time has moved on, so the uncertainty in the current position increases
        @variance += @timestamp_ms * decay * decay / 1000;
        @timestamp_ms = beacon.date.getTime();

      # 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
      _k  = @variance / (@variance + accuracy * accuracy)
      @lat = _k * (beacon.latitude  - @lat)
      @lng = _k * (beacon.longitude - @lng)

      @variance = (1 - _k) * @variance

    [@lat,@lng]

Bu düzenlemek için çalıştı, ama geçen hatlarında bir yazım hatası var @latve @lngayarlanır. +==
Şunun

0

Java kodunu @Stochastically'den Kotlin'e dönüştürdüm

class KalmanLatLong
{
    private val MinAccuracy: Float = 1f

    private var Q_metres_per_second: Float = 0f
    private var TimeStamp_milliseconds: Long = 0
    private var lat: Double = 0.toDouble()
    private var lng: Double = 0.toDouble()
    private var variance: Float =
        0.toFloat() // P matrix.  Negative means object uninitialised.  NB: units irrelevant, as long as same units used throughout

    fun KalmanLatLong(Q_metres_per_second: Float)
    {
        this.Q_metres_per_second = Q_metres_per_second
        variance = -1f
    }

    fun get_TimeStamp(): Long { return TimeStamp_milliseconds }
    fun get_lat(): Double { return lat }
    fun get_lng(): Double { return lng }
    fun get_accuracy(): Float { return Math.sqrt(variance.toDouble()).toFloat() }

    fun SetState(lat: Double, lng: Double, accuracy: Float, TimeStamp_milliseconds: Long)
    {
        this.lat = lat
        this.lng = lng
        variance = accuracy * accuracy
        this.TimeStamp_milliseconds = TimeStamp_milliseconds
    }

    /// <summary>
    /// Kalman filter processing for lattitude and longitude
    /// /programming/1134579/smooth-gps-data/15657798#15657798
    /// </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>
    fun Process(lat_measurement: Double, lng_measurement: Double, accuracy: Float, TimeStamp_milliseconds: Long)
    {
        var accuracy = accuracy
        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

            val 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.toFloat() * 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
            val 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
        }
    }
}

0

İşte ihtiyaç duyan herkes için @ Stochastically'nin Java uygulamasının bir Javascript uygulaması:

class GPSKalmanFilter {
  constructor (decay = 3) {
    this.decay = decay
    this.variance = -1
    this.minAccuracy = 1
  }

  process (lat, lng, accuracy, timestampInMs) {
    if (accuracy < this.minAccuracy) accuracy = this.minAccuracy

    if (this.variance < 0) {
      this.timestampInMs = timestampInMs
      this.lat = lat
      this.lng = lng
      this.variance = accuracy * accuracy
    } else {
      const timeIncMs = timestampInMs - this.timestampInMs

      if (timeIncMs > 0) {
        this.variance += (timeIncMs * this.decay * this.decay) / 1000
        this.timestampInMs = timestampInMs
      }

      const _k = this.variance / (this.variance + (accuracy * accuracy))
      this.lat += _k * (lat - this.lat)
      this.lng += _k * (lng - this.lng)

      this.variance = (1 - _k) * this.variance
    }

    return [this.lng, this.lat]
  }
}

Kullanım örneği:

   const kalmanFilter = new GPSKalmanFilter()
   const updatedCoords = []

    for (let index = 0; index < coords.length; index++) {
      const { lat, lng, accuracy, timestampInMs } = coords[index]
      updatedCoords[index] = kalmanFilter.process(lat, lng, accuracy, timestampInMs)
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.