Kalman2DPositionFilter.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using Emgu.CV;
  7. using Emgu.CV.Structure;
  8. namespace bbiwarg.Utility
  9. {
  10. class Kalman2DPositionFilter
  11. {
  12. private Kalman kalman;
  13. private float mXX, mXY, mYY, processNoiseFactor;
  14. private float fps;
  15. public bool Initialized { get; private set; }
  16. // state: x, y, v_x, v_y
  17. // x: current x position
  18. // y: current y position
  19. // v_x: velocity in x direction
  20. // v_y: velocity in y direction
  21. // a_x: acceleration in x direction
  22. // a_y: acceleration in y direction
  23. public Kalman2DPositionFilter(float mXX, float mXY, float mYY, float processNoiseFactor = 1.0e-4f, int fps = 30)
  24. {
  25. this.mXX = mXX;
  26. this.mXY = mXY;
  27. this.mYY = mYY;
  28. this.processNoiseFactor = processNoiseFactor;
  29. this.fps = fps;
  30. reset();
  31. }
  32. public void reset()
  33. {
  34. // 6 state variables and 2 measurements (0 controls)
  35. kalman = new Kalman(4, 2, 0);
  36. // time step (s)
  37. float t = 1 / fps;
  38. // transition matrix
  39. Matrix<float> transitionMatrix = new Matrix<float>(new float[,]
  40. { {1.0f, 0.0f, 1.0f * t, 0.0f},
  41. {0.0f, 1.0f, 0.0f, 1.0f * t},
  42. {0.0f, 0.0f, 1.0f, 0.0f},
  43. {0.0f, 0.0f, 0.0f, 1.0f}});
  44. kalman.TransitionMatrix = transitionMatrix;
  45. // measurement matrix
  46. Matrix<float> measurementMatrix = new Matrix<float>(new float[,]
  47. { {1.0f, 0.0f, 0.0f, 0.0f}, // first measurement = x
  48. {0.0f, 1.0f, 0.0f, 0.0f} // second measurement = y
  49. });
  50. kalman.MeasurementMatrix = measurementMatrix;
  51. // measurement noise covariance matrix
  52. Matrix<float> measurementNoiseCovarianceMatrix = new Matrix<float>(2, 2);
  53. measurementNoiseCovarianceMatrix[0, 0] = mXX;
  54. measurementNoiseCovarianceMatrix[0, 1] = measurementNoiseCovarianceMatrix[1, 0] = mXY;
  55. measurementNoiseCovarianceMatrix[1, 1] = mYY;
  56. kalman.MeasurementNoiseCovariance = measurementNoiseCovarianceMatrix;
  57. // process noise covariance matrix
  58. Matrix<float> processNoiseCovarianceMatrix = new Matrix<float>(4, 4);
  59. processNoiseCovarianceMatrix.SetIdentity(new MCvScalar(processNoiseFactor));
  60. kalman.ProcessNoiseCovariance = processNoiseCovarianceMatrix;
  61. // error covariance post matrix (initial value)
  62. Matrix<float> errorCovariancePostMatrix = new Matrix<float>(4, 4);
  63. errorCovariancePostMatrix.SetIdentity(new MCvScalar(processNoiseFactor));
  64. kalman.ErrorCovariancePost = errorCovariancePostMatrix;
  65. Initialized = false;
  66. }
  67. public void setInitialPosition(Vector2D initialPosition)
  68. {
  69. // initial state (x, y, v_x, v_y)
  70. Matrix<float> initialState = new Matrix<float>(new float[] { initialPosition.X, initialPosition.Y, 0.0f, 0.0f });
  71. kalman.CorrectedState = initialState;
  72. Initialized = true;
  73. }
  74. public Vector2D getPrediction()
  75. {
  76. Matrix<float> predicton = kalman.Predict();
  77. return new Vector2D(predicton[0, 0], predicton[1, 0]);
  78. }
  79. // updates the filter and returns the corrected position
  80. public Vector2D getCorrectedPosition(Vector2D rawPosition)
  81. {
  82. Matrix<float> rawPositionMatrix = new Matrix<float>(new float[,]
  83. { {rawPosition.X},
  84. {rawPosition.Y}});
  85. // prediction according to model
  86. kalman.Predict();
  87. // corrected point
  88. Matrix<float> estimate = kalman.Correct(rawPositionMatrix);
  89. return new Vector2D(estimate[0, 0], estimate[1, 0]);
  90. }
  91. }
  92. }