2017-05-17 09:43:27 +02:00
|
|
|
/**
|
|
|
|
* KalmanFilter
|
|
|
|
* @class
|
|
|
|
* @author Wouter Bulten
|
|
|
|
* @see {@link http://github.com/wouterbulten/kalmanjs}
|
|
|
|
* @version Version: 1.0.0-beta
|
|
|
|
* @copyright Copyright 2015 Wouter Bulten
|
|
|
|
* @license GNU LESSER GENERAL PUBLIC LICENSE v3
|
|
|
|
* @preserve
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-05-17 16:03:45 +02:00
|
|
|
function KalmanFilter(params) {
|
|
|
|
/**
|
|
|
|
* Create 1-dimensional kalman filter
|
|
|
|
* @param {Number} options.R Process noise
|
|
|
|
* @param {Number} options.Q Measurement noise
|
|
|
|
* @param {Number} options.A State vector
|
|
|
|
* @param {Number} options.B Control vector
|
|
|
|
* @param {Number} options.C Measurement vector
|
|
|
|
* @return {KalmanFilter}
|
|
|
|
*/
|
2017-05-17 09:43:27 +02:00
|
|
|
|
2017-05-17 16:03:45 +02:00
|
|
|
this.R = typeof params.R == "undefined" ? 1 : params.R; // noise power desirable
|
|
|
|
this.Q = typeof params.Q == "undefined" ? 1 : params.Q; // noise power estimated
|
2017-05-17 09:43:27 +02:00
|
|
|
|
2017-05-17 16:03:45 +02:00
|
|
|
this.A = typeof params.A == "undefined" ? 1 : params.A;
|
|
|
|
this.C = typeof params.C == "undefined" ? 1 : params.C;
|
|
|
|
this.B = typeof params.B == "undefined" ? 0 : params.B;
|
|
|
|
this.cov = NaN;
|
|
|
|
this.x = NaN; // estimated signal without noise
|
|
|
|
}
|
2017-05-17 09:43:27 +02:00
|
|
|
|
2017-05-17 16:03:45 +02:00
|
|
|
/**
|
|
|
|
* Filter a new value
|
|
|
|
* @param {Number} z Measurement
|
|
|
|
* @param {Number} u Control
|
|
|
|
* @return {Number}
|
|
|
|
*/
|
|
|
|
KalmanFilter.prototype.filter = function (z, u) {
|
|
|
|
if (typeof u == "undefined")
|
|
|
|
u = 0;
|
|
|
|
if (isNaN(this.x)) {
|
|
|
|
this.x = (1 / this.C) * z;
|
|
|
|
this.cov = (1 / this.C) * this.Q * (1 / this.C);
|
|
|
|
}
|
|
|
|
else {
|
2017-05-17 09:43:27 +02:00
|
|
|
|
2017-05-17 16:03:45 +02:00
|
|
|
// Compute prediction
|
|
|
|
const predX = (this.A * this.x) + (this.B * u);
|
|
|
|
const predCov = ((this.A * this.cov) * this.A) + this.R;
|
2017-05-17 09:43:27 +02:00
|
|
|
|
2017-05-17 16:03:45 +02:00
|
|
|
// Kalman gain
|
|
|
|
const K = predCov * this.C * (1 / ((this.C * predCov * this.C) + this.Q));
|
2017-05-17 09:43:27 +02:00
|
|
|
|
2017-05-17 16:03:45 +02:00
|
|
|
// Correction
|
|
|
|
this.x = predX + K * (z - (this.C * predX));
|
|
|
|
this.cov = predCov - (K * this.C * predCov);
|
|
|
|
}
|
2017-05-17 09:43:27 +02:00
|
|
|
|
2017-05-17 16:03:45 +02:00
|
|
|
return this.x;
|
|
|
|
}
|
2017-05-17 09:43:27 +02:00
|
|
|
|
2017-05-17 16:03:45 +02:00
|
|
|
/**
|
|
|
|
* Return the last filtered measurement
|
|
|
|
* @return {Number}
|
|
|
|
*/
|
|
|
|
KalmanFilter.prototype.lastMeasurement = function () {
|
|
|
|
return this.x;
|
|
|
|
}
|
2017-05-17 09:43:27 +02:00
|
|
|
|
2017-05-17 16:03:45 +02:00
|
|
|
/**
|
|
|
|
* Set measurement noise Q
|
|
|
|
* @param {Number} noise
|
|
|
|
*/
|
|
|
|
KalmanFilter.prototype.setMeasurementNoise = function (noise) {
|
|
|
|
this.Q = noise;
|
|
|
|
}
|
2017-05-17 09:43:27 +02:00
|
|
|
|
2017-05-17 16:03:45 +02:00
|
|
|
/**
|
|
|
|
* Set the process noise R
|
|
|
|
* @param {Number} noise
|
|
|
|
*/
|
|
|
|
KalmanFilter.prototype.setProcessNoise = function (noise) {
|
|
|
|
this.R = noise;
|
2017-05-17 09:43:27 +02:00
|
|
|
}
|
2017-05-17 16:03:45 +02:00
|
|
|
|