KalmanLatLong.cs 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. public class KalmanLatLong
  6. {
  7. private float MinAccuracy = 1;
  8. private float Q_metres_per_second;
  9. private long TimeStamp_milliseconds;
  10. private double lat;
  11. private double lng;
  12. private float variance; // P matrix. Negative means object uninitialised. NB: units irrelevant, as long as same units used throughout
  13. public KalmanLatLong(float Q_metres_per_second) { this.Q_metres_per_second = Q_metres_per_second; variance = -1; }
  14. public long get_TimeStamp() { return TimeStamp_milliseconds; }
  15. public double get_lat() { return lat; }
  16. public double get_lng() { return lng; }
  17. public float get_accuracy() { return (float)Math.Sqrt(variance); }
  18. public void SetState(double lat, double lng, float accuracy, long TimeStamp_milliseconds)
  19. {
  20. this.lat = lat; this.lng = lng; variance = accuracy * accuracy; this.TimeStamp_milliseconds = TimeStamp_milliseconds;
  21. }
  22. /// <summary>
  23. /// Kalman filter processing for lattitude and longitude
  24. /// </summary>
  25. /// <param name="lat_measurement_degrees">new measurement of lattidude</param>
  26. /// <param name="lng_measurement">new measurement of longitude</param>
  27. /// <param name="accuracy">measurement of 1 standard deviation error in metres</param>
  28. /// <param name="TimeStamp_milliseconds">time of measurement</param>
  29. /// <returns>new state</returns>
  30. public void Process(double lat_measurement, double lng_measurement, float accuracy, long TimeStamp_milliseconds)
  31. {
  32. if (accuracy < MinAccuracy) accuracy = MinAccuracy;
  33. if (variance < 0)
  34. {
  35. // if variance < 0, object is unitialised, so initialise with current values
  36. this.TimeStamp_milliseconds = TimeStamp_milliseconds;
  37. lat = lat_measurement; lng = lng_measurement; variance = accuracy * accuracy;
  38. }
  39. else
  40. {
  41. // else apply Kalman filter methodology
  42. long TimeInc_milliseconds = TimeStamp_milliseconds - this.TimeStamp_milliseconds;
  43. if (TimeInc_milliseconds > 0)
  44. {
  45. // time has moved on, so the uncertainty in the current position increases
  46. variance += TimeInc_milliseconds * Q_metres_per_second * Q_metres_per_second / 1000;
  47. this.TimeStamp_milliseconds = TimeStamp_milliseconds;
  48. // TO DO: USE VELOCITY INFORMATION HERE TO GET A BETTER ESTIMATE OF CURRENT POSITION
  49. }
  50. // Kalman gain matrix K = Covarariance * Inverse(Covariance + MeasurementVariance)
  51. // NB: because K is dimensionless, it doesn't matter that variance has different units to lat and lng
  52. float K = variance / (variance + accuracy * accuracy);
  53. // apply K
  54. lat += K * (lat_measurement - lat);
  55. lng += K * (lng_measurement - lng);
  56. // new Covarariance matrix is (IdentityMatrix - K) * Covarariance
  57. variance = (1 - K) * variance;
  58. }
  59. }
  60. }