随着传感技术、机器人、自动驾驶以及航空航天等技术的不断发展,对控制系统的精度及稳定性的要求也越来越高。卡尔曼滤波作为一种状态最优估计的方法,其应用也越来越普遍,卡尔曼滤波(Kalman filtering)是一种利用线性系统状态方程,通过系统输入输出观测数据,对系统状态进行最优估计的算法。

数据滤波是去除噪声还原真实数据的一种数据处理技术,Kalman滤波在测量方差已知的情况下能够从一系列存在测量噪声的数据中,估计动态系统的状态。由于它便于计算机编程实现,并能够对现场采集的数据进行实时的更新和处理,Kalman滤波是目前应用最为广泛的滤波方法,在通信,导航,制导与控制等多领域得到了较好的应用,下面带来的是它的C#版本。

/// <summary>
	/// Simple implementation of the Kalman Filter for 1D data.
	/// Originally written in JavaScript by Wouter Bulten
	/// 
	/// https://github.com/wouterbulten/kalmanjs/blob/master/contrib/java/KalmanFilter.java
	/// </summary>
	public class FilterKalman
	{
		private double A = 1;
		private double B = 0;
		private double C = 1;

		private double R;
		private double Q;

		private double cov = double.NaN;
		private double x = double.NaN;

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="R">R Process noise</param>
		/// <param name="Q">Q Measurement noise</param>
		/// <param name="A">A State vector</param>
		/// <param name="B">B Control vector</param>
		/// <param name="C">C Measurement vector</param>
		public FilterKalman(double R, double Q, double A, double B, double C)
		{
			this.R = R;
			this.Q = Q;

			this.A = A;
			this.B = B;
			this.C = C;

			this.cov = double.NaN;
			this.x = double.NaN; // estimated signal without noise
		}

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="R">R Process noise</param>
		/// <param name="Q">Q Measurement noise</param>
		public FilterKalman(double R, double Q)
		{
			this.R = R;
			this.Q = Q;
		}

		/// <summary>
		/// Filters a measurement
		/// </summary>
		/// <param name="measurement">The measurement value to be filtered</param>
		/// <param name="u">The controlled input value</param>
		/// <returns>The filtered value</returns>
		public double filter(double measurement, double u)
		{
			if (double.IsNaN(this.x))
			{
				this.x = (1 / this.C) * measurement;
				this.cov = (1 / this.C) * this.Q * (1 / this.C);
			}
			else
			{
				double predX = (this.A * this.x) + (this.B * u);
				double predCov = ((this.A * this.cov) * this.A) + this.R;

				// Kalman gain
				double K = predCov * this.C * (1 / ((this.C * predCov * this.C) + this.Q));

				// Correction
				this.x = predX + K * (measurement - (this.C * predX));
				this.cov = predCov - (K * this.C * predCov);
			}
			return this.x;
		}

		/// <summary>
		/// Filters a measurement
		/// </summary>
		/// <param name="measurement">The measurement value to be filtered</param>
		/// <returns>The filtered value</returns>
		public double filter(double measurement)
		{
			double u = 0;
			if (double.IsNaN(this.x))
			{
				this.x = (1 / this.C) * measurement;
				this.cov = (1 / this.C) * this.Q * (1 / this.C);
			}
			else
			{
				double predX = (this.A * this.x) + (this.B * u);
				double predCov = ((this.A * this.cov) * this.A) + this.R;

				// Kalman gain
				double K = predCov * this.C * (1 / ((this.C * predCov * this.C) + this.Q));

				// Correction
				this.x = predX + K * (measurement - (this.C * predX));
				this.cov = predCov - (K * this.C * predCov);
			}
			return this.x;
		}

		/// <summary>
		/// Set the last measurement.
		/// </summary>
		/// <returns>return The last measurement fed into the filter</returns>
		public double lastMeasurement()
		{
			return this.x;
		}

		/// <summary>
		/// Sets measurement noise
		/// </summary>
		/// <param name="noise">The new measurement noise</param>
		public void setMeasurementNoise(double noise)
		{
			this.Q = noise;
		}

		/// <summary>
		/// Sets process noise
		/// </summary>
		/// <param name="noise">The new process noise</param>
		public void setProcessNoise(double noise)
		{
			this.R = noise;
		}
	}

应用示例如下:

 FilterKalman test = new FilterKalman(0.008, 0.1);
            double[] testData = { 66, 64, 63, 63, 63, 66, 65, 67, 58 };
            foreach (var x in testData)
            {
                Console.WriteLine("Input data: {0:#,##0.00}, Filtered data:{1:#,##0.000}", x, test.filter(x));
            }

            Console.WriteLine("FilterKalman Usage with controlled input");

            FilterKalman test2 = new FilterKalman(0.008, 0.1, 1, 1, 1);
            double u = 0.2;
            foreach (var x in testData)
            {
                Console.WriteLine("Input data: {0:#,##0.00}, Filtered data:{1:#,##0.000}", x, test.filter(x, u));
            }

 

可以下载我写的源码:

链接:https://pan.baidu.com/s/1GqfJJF4I1PLJkx7uCIwOfQ 
 

💰 此内容为付费阅读 请先登录