Data GPS halus

145

Saya bekerja dengan data GPS, mendapatkan nilai setiap detik dan menampilkan posisi saat ini di peta. Masalahnya adalah bahwa kadang-kadang (khususnya ketika akurasi rendah) nilainya sangat bervariasi, membuat posisi saat ini untuk "melompat" antara titik-titik yang jauh di peta.

Saya bertanya-tanya tentang beberapa metode yang cukup mudah untuk menghindari ini. Sebagai ide pertama, saya berpikir untuk membuang nilai-nilai dengan akurasi di luar batas tertentu, tetapi saya kira ada beberapa cara lain yang lebih baik untuk dilakukan. Apa cara yang biasa dilakukan oleh program?

Al.
sumber
Saya merasakan efek buruk dari "GPS noise" ketika mencoba menghitung nilai terkait (turunan) seperti kecepatan dan kemiringan, yang sangat terputus-putus khususnya untuk tracklog tingkat sampel tinggi (karena waktu memiliki resolusi integer [satu detik]).
heltonbiker
4
(juga, jika Anda menavigasi melalui jalan utama, Anda dapat menggunakan algoritma "jepret ke jalan" asalkan Anda memiliki dataset peta jalan [benar, tepat] yang bagus. Hanya satu pemikiran)
heltonbiker
Saya menghadapi masalah ini untuk akurasi terbaik juga.
ViruMax

Jawaban:

80

Berikut adalah filter Kalman sederhana yang dapat digunakan untuk situasi ini. Itu berasal dari beberapa pekerjaan yang saya lakukan pada perangkat Android.

Teori filter General Kalman adalah semua tentang estimasi untuk vektor, dengan akurasi estimasi diwakili oleh matriks kovarians. Namun, untuk memperkirakan lokasi pada perangkat Android teori umum dikurangi menjadi kasus yang sangat sederhana. Penyedia lokasi Android memberikan lokasi sebagai garis lintang dan bujur, bersama dengan keakuratan yang ditentukan sebagai angka tunggal yang diukur dalam meter. Ini berarti bahwa alih-alih matriks kovarians, akurasi dalam filter Kalman dapat diukur dengan angka tunggal, meskipun lokasi dalam filter Kalman diukur dengan dua angka. Juga fakta bahwa garis lintang, bujur dan meter secara efektif semua unit yang berbeda dapat diabaikan, karena jika Anda memasukkan faktor penskalaan ke dalam filter Kalman untuk mengubahnya semuanya menjadi unit yang sama,

Kode dapat ditingkatkan, karena mengasumsikan bahwa perkiraan terbaik dari lokasi saat ini adalah lokasi terakhir yang diketahui, dan jika seseorang bergerak, mungkin saja menggunakan sensor Android untuk menghasilkan perkiraan yang lebih baik. Kode memiliki satu parameter bebas Q, dinyatakan dalam meter per detik, yang menggambarkan seberapa cepat akurasi meluruh tanpa adanya perkiraan lokasi baru. Parameter Q yang lebih tinggi berarti bahwa akurasi meluruh lebih cepat. Filter Kalman umumnya bekerja lebih baik ketika akurasi meluruh sedikit lebih cepat daripada yang mungkin diharapkan, jadi untuk berjalan-jalan dengan ponsel Android saya menemukan bahwa Q = 3 meter per detik berfungsi dengan baik, meskipun saya biasanya berjalan lebih lambat dari itu. Tetapi jika bepergian dengan mobil cepat, jumlah yang jauh lebih besar harus digunakan.

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;
        }
    }
}
Secara stokastik
sumber
1
Seharusnya perhitungan varians tidak menjadi: varians + = TimeInc_milliseconds * TimeInc_milliseconds * Q_metres_per_second * Q_metres_per_second / 1000000
Horacio
4
@Horacio, saya tahu mengapa Anda berpikir begitu, tapi tidak! Secara matematis, ketidakpastian di sini dimodelkan oleh proses Wiener (lihat en.wikipedia.org/wiki/Wiener_process ) dan dengan proses Wiener varians tumbuh secara linear seiring waktu. Variabel Q_metres_per_secondsesuai dengan variabel sigmadi bagian "Proses terkait" di artikel Wikipedia itu. Q_metres_per_secondadalah standar deviasi dan diukur dalam meter, jadi meter dan bukan meter / detik adalah unitnya. Ini sesuai dengan standar deviasi distribusi setelah 1 detik berlalu.
Stochastically
3
Saya mencoba pendekatan ini dan kode, tetapi akhirnya memperpendek jarak total terlalu banyak. Membuatnya terlalu tidak tepat.
Andreas Rudolph
1
@ user2999943 ya, gunakan kode untuk memproses koordinat yang Anda dapatkan dari onLocationChanged ().
Stochastically
2
@Koray jika Anda tidak memiliki info akurasi maka Anda tidak dapat menggunakan filter Kalman. Ini sangat mendasar untuk apa yang coba dilakukan oleh filter Kalman.
Stochastically
75

Apa yang Anda cari disebut Filter Kalman . Ini sering digunakan untuk memuluskan data navigasi . Ini tidak selalu sepele, dan ada banyak penyetelan yang dapat Anda lakukan, tetapi ini adalah pendekatan yang sangat standar dan berfungsi dengan baik. Ada perpustakaan KFilter yang tersedia yang merupakan implementasi C ++.

Fallback saya berikutnya akan menjadi kotak paling cocok . Filter Kalman akan memuluskan data dengan mempertimbangkan kecepatan, sedangkan pendekatan kuadrat terkecil hanya akan menggunakan informasi posisi. Namun, jelas lebih mudah untuk diimplementasikan dan dipahami. Sepertinya Perpustakaan Ilmiah GNU mungkin memiliki implementasi ini.

Chris Arguin
sumber
1
Terimakasih Chris. Ya, saya membaca tentang Kalman saat melakukan pencarian, tapi itu pasti sedikit di luar pengetahuan matematika saya. Apakah Anda mengetahui adanya kode sampel yang mudah dibaca (dan dimengerti!), Atau lebih baik, beberapa implementasi tersedia? (C / C ++ / Java)
Al.
1
@Al Sayangnya, satu-satunya paparan saya dengan filter Kalman adalah melalui pekerjaan, jadi saya memiliki beberapa kode yang sangat elegan dan tidak dapat saya tunjukkan.
Chris Arguin
Tidak masalah :-) Saya mencoba mencari tetapi untuk beberapa alasan sepertinya hal Kalman ini adalah ilmu hitam. Banyak halaman teori tetapi tidak ada kode sama sekali .. Terima kasih, akan mencoba metode lain.
Al.
2
kalman.sourceforge.net/index.php di sini adalah implementasi C ++ dari filter Kalman.
Rostyslav Druzhchenko
1
@ChrisArguin Anda dipersilakan. Beri tahu saya jika hasilnya baik.
Rostyslav Druzhchenko
11

Ini mungkin datang agak terlambat ...

Saya menulis KalmanLocationManager untuk Android ini, yang membungkus dua penyedia lokasi paling umum, Jaringan dan GPS, kalman-filter data, dan memberikan pembaruan ke LocationListener(seperti dua penyedia 'nyata').

Saya menggunakannya sebagian besar untuk "interpolasi" antara pembacaan - untuk menerima pembaruan (prediksi posisi) setiap 100 milis misalnya (bukannya laju gps maksimum satu detik), yang memberi saya frame rate yang lebih baik ketika menjiwai posisi saya.

Sebenarnya, ia menggunakan tiga filter kalman, aktif untuk setiap dimensi: lintang, bujur dan ketinggian. Lagipula mereka mandiri.

Ini membuat matematika matriks jauh lebih mudah: daripada menggunakan satu matriks transisi keadaan 6x6, saya menggunakan 3 matriks 2x2 berbeda. Sebenarnya dalam kode, saya tidak menggunakan matriks sama sekali. Memecahkan semua persamaan dan semua nilai adalah primitif (ganda).

Kode sumber berfungsi, dan ada aktivitas demo. Maaf karena kurangnya javadoc di beberapa tempat, saya akan menyusul.

villoren
sumber
1
Saya mencoba menggunakan kode lib Anda, saya mendapat beberapa hasil yang tidak diinginkan, saya tidak yakin jika saya melakukan sesuatu yang salah ... (Di bawah ini adalah url gambar, biru adalah lintasan lokasi yang disaring, oranye adalah lokasi mentah) app.box. com / s / w3uvaz007glp2utvgznmh8vlggvaiifk
umesh
Lonjakan yang Anda lihat 'tumbuh' dari mean (garis oranye) terlihat seperti pembaruan penyedia jaringan. Dapatkah Anda mencoba merencanakan pembaruan jaringan mentah dan gps? Mungkin Anda akan lebih baik tanpa pembaruan jaringan, tergantung pada apa yang ingin Anda capai. Btw, dari mana Anda mendapatkan pembaruan oranye mentah itu?
villoren
1
titik oranye dari penyedia gps, dan yang biru dari Kalman, saya membuat log di peta
umesh
Bisakah Anda mengirim saya data itu dalam beberapa format teks? Setiap pembaruan lokasi memiliki set bidang Location.getProvider (). Hanya satu file dengan semua Location.toString ().
villoren
9

Anda tidak harus menghitung kecepatan dari perubahan posisi per waktu. GPS mungkin memiliki posisi yang tidak akurat, tetapi memiliki kecepatan yang akurat (di atas 5km / jam). Jadi gunakan kecepatan dari cap lokasi GPS. Dan lebih jauh Anda tidak harus melakukannya dengan tentu saja, meskipun itu berfungsi sebagian besar waktu.

Posisi GPS, seperti yang disampaikan, sudah difilter Kalman, Anda mungkin tidak dapat meningkatkan, dalam postprocessing biasanya Anda tidak memiliki informasi yang sama seperti chip GPS.

Anda dapat memuluskannya, tetapi ini juga menimbulkan kesalahan.

Pastikan bahwa Anda menghapus posisi ketika perangkat diam, ini menghapus posisi melompat, bahwa beberapa perangkat / Konfigurasi tidak menghapus.

AlexWien
sumber
5
Bisakah Anda memberikan beberapa referensi untuk ini?
ivyleavedtoadflax
1
Ada banyak info dan banyak pengalaman profesional dalam kalimat itu, Kalimat mana yang Anda inginkan untuk referensi? untuk kecepatan: mencari efek doppler dan GPS. Kalman internal? Ini adalah pengetahuan dasar GPS, setiap kertas atau buku yang menjelaskan bagaimana chip GPS bekerja secara internal. smootig-errors: selalu menghaluskan memperkenalkan erros. berdiri diam? coba itu.
AlexWien
2
"Melompat-lompat" saat berdiri diam bukan satu-satunya sumber kesalahan. Ada juga pantulan sinyal (misalnya dari gunung) di mana posisi melompat. Chip GPS saya (mis. Garmin Dakota 20, SonyEricsson Neo) belum memfilter ini ... Dan yang sebenarnya adalah lelucon adalah nilai elevasi dari sinyal GPS ketika tidak dikombinasikan dengan tekanan barometrik. Nilai-nilai ini tidak difilter atau saya tidak ingin melihat nilai-nilai tanpa filter.
hgoebl
1
@AlexWien GPS menghitung jarak dari satu titik pada satu waktu ke toleransi yang memberi Anda bola dengan ketebalan, cangkang yang berpusat di sekitar satelit. Anda berada di suatu tempat dalam volume shell ini. Perpotongan tiga volume shell ini memberi Anda volume posisi, yang pusatnya adalah posisi Anda yang dihitung. Jika Anda memiliki satu set posisi yang dilaporkan dan Anda tahu sensor dalam keadaan diam, menghitung centroid secara efektif memotong lebih banyak cangkang, meningkatkan presisi. Kesalahan dalam hal ini berkurang .
Peter Wone
6
"Posisi GPS, seperti yang disampaikan, sudah difilter Kalman, Anda mungkin tidak dapat meningkatkan". Jika Anda dapat menunjuk ke sumber yang mengkonfirmasi ini untuk smartphone modern (misalnya), itu akan sangat berguna. Saya tidak bisa melihat buktinya sendiri. Bahkan pemfilteran Kalman sederhana dari lokasi mentah perangkat sangat menunjukkan itu tidak benar. Lokasi mentah menari-nari tak menentu, sedangkan lokasi yang disaring paling sering berada di dekat lokasi nyata (dikenal).
sobri
6

Saya biasanya menggunakan accelerometer. Perubahan posisi yang tiba-tiba dalam waktu singkat menyiratkan akselerasi tinggi. Jika ini tidak tercermin dalam telemetri accelerometer, hampir pasti karena perubahan pada satelit "tiga terbaik" yang digunakan untuk menghitung posisi (yang saya sebut sebagai teleportasi GPS).

Ketika sebuah aset dalam keadaan diam dan melompat-lompat karena GPS teleporting, jika Anda secara progresif menghitung centroid Anda secara efektif memotong set kerang yang lebih besar dan lebih besar, meningkatkan presisi.

Untuk melakukan ini ketika aset tidak diam, Anda harus memperkirakan kemungkinan posisi dan orientasi berikutnya berdasarkan kecepatan, heading, linier, dan data percepatan rotasi (jika Anda memiliki gyro). Ini kurang lebih apa yang dilakukan oleh filter K yang terkenal. Anda bisa mendapatkan semuanya dalam perangkat keras untuk sekitar $ 150 pada AHRS yang mengandung segalanya kecuali modul GPS, dan dengan jack untuk menghubungkan satu. Ini memiliki CPU dan Kalman filtering on board; hasilnya stabil dan cukup baik. Bimbingan inersia sangat tahan terhadap jitter tetapi hanyut dengan waktu. GPS rentan terhadap jitter tetapi tidak melayang dengan waktu, mereka praktis dibuat untuk saling mengimbangi.

Peter Wone
sumber
4

Salah satu metode yang menggunakan lebih sedikit matematika / teori adalah untuk sampel 2, 5, 7, atau 10 titik data sekaligus dan menentukan yang outlier. Ukuran outlier yang kurang akurat dibandingkan dengan Kalman Filter adalah menggunakan algoritma berikut untuk mengambil semua jarak pasangan yang bijaksana antara titik dan membuang yang paling jauh dari yang lain. Biasanya nilai-nilai itu diganti dengan nilai yang paling dekat dengan nilai outlying yang Anda ganti

Sebagai contoh

Menghaluskan pada lima titik sampel A, B, C, D, E

ATOTAL = SUM jarak AB AC AD AE

BTOTAL = SUM jarak AB BC BD BE

CTOTAL = SUM jarak AC BC CD CE

DTOTAL = SUM jarak DA DB DC DE

ETOTAL = SUM jarak EA EB EC DE

Jika BTOTAL adalah terbesar, Anda akan mengganti titik B dengan D jika BD = min {AB, BC, BD, BE}

Smoothing ini menentukan outlier dan dapat ditambah dengan menggunakan titik tengah BD bukan titik D untuk menghaluskan garis posisi. Jarak tempuh Anda dapat bervariasi dan ada lebih banyak solusi yang ketat secara matematis.

ojblass
sumber
Terima kasih, saya akan mencobanya juga. Perhatikan bahwa saya ingin memperlancar posisi saat ini, karena yang sedang ditampilkan dan yang digunakan untuk mengambil beberapa data. Saya tidak tertarik dengan poin sebelumnya. Ide awal saya menggunakan cara tertimbang, tetapi saya masih harus melihat yang terbaik.
Al.
1
Al, ini tampaknya merupakan bentuk cara tertimbang. Anda perlu menggunakan poin "masa lalu" jika Anda ingin melakukan penghalusan, karena sistem perlu memiliki lebih dari posisi saat ini untuk mengetahui di mana harus memuluskan juga. Jika GPS Anda mengambil titik data satu kali per detik dan pengguna Anda melihat layar sekali per lima detik, Anda dapat menggunakan 5 titik data tanpa dia sadari! Rata-rata bergerak hanya akan tertunda satu dp juga.
Karl
4

Untuk kotak yang paling pas, berikut adalah beberapa hal lain yang dapat Anda coba:

  1. Hanya karena kuadratnya paling sesuai tidak berarti bahwa itu harus linier. Anda paling tidak bisa-kuadrat-cocok kurva kuadrat ke data, maka ini akan cocok dengan skenario di mana pengguna mempercepat. (Perhatikan bahwa dengan kuadrat terkecil yang saya maksud menggunakan koordinat sebagai variabel dependen dan waktu sebagai variabel independen.)

  2. Anda juga dapat mencoba menimbang titik data berdasarkan akurasi yang dilaporkan. Ketika akurasinya rendah, titik-titik data tersebut lebih rendah.

  3. Hal lain yang mungkin ingin Anda coba daripada menampilkan satu titik, jika akurasinya rendah, tampilkan lingkaran atau sesuatu yang menunjukkan kisaran di mana pengguna dapat didasarkan pada akurasi yang dilaporkan. (Inilah yang dilakukan aplikasi Google Maps bawaan iPhone.)

Alex319
sumber
3

Anda juga dapat menggunakan spline. Masukkan nilai-nilai yang Anda miliki dan sisipkan poin di antara poin yang diketahui. Menghubungkan ini dengan fit-kuadrat, rata-rata bergerak atau filter kalman (seperti yang disebutkan dalam jawaban lain) memberi Anda kemampuan untuk menghitung poin di antara poin "diketahui" Anda.

Mampu menginterpolasi nilai-nilai antara yang diketahui memberi Anda transisi yang bagus dan / masuk akal / perkiraan data apa yang akan hadir jika Anda memiliki kesetiaan yang lebih tinggi. http://en.wikipedia.org/wiki/Spline_interpolation

Splines yang berbeda memiliki karakteristik yang berbeda. Yang saya lihat paling umum digunakan adalah Akima dan Cubic splines.

Algoritme lain yang perlu dipertimbangkan adalah algoritma penyederhanaan garis Ramer-Douglas-Peucker, cukup umum digunakan dalam penyederhanaan data GPS. ( http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm )

Aidos
sumber
3

Kembali ke Filter Kalman ... Saya menemukan implementasi C untuk filter Kalman untuk data GPS di sini: http://github.com/lacker/ikalman Saya belum mencobanya, tetapi tampaknya menjanjikan.

KarateSnowMachine
sumber
0

Dipetakan ke CoffeeScript jika ada yang tertarik. ** sunting -> maaf menggunakan backbone juga, tetapi Anda mendapatkan idenya.

Dimodifikasi sedikit untuk menerima suar dengan attrib

{latitude: item.lat, bujur: item.lng, tanggal: Tanggal baru (item.effective_at), akurasi: 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]
lucygenik
sumber
Sudah mencoba mengedit ini, tetapi ada salah ketik di baris terakhir tempat @latdan @lngditetapkan. Seharusnya +=lebih daripada=
jdixon04
0

Saya telah mengubah kode Java dari @Stochastically ke Kotlin

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
        }
    }
}
inspire_coding
sumber
0

Berikut ini adalah implementasi Javascript dari implementasi Java @ Stochastically untuk siapa pun yang membutuhkannya:

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

Contoh penggunaan:

   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)
    }
jdixon04
sumber