最近为了项目,同事让我帮他做一个硬件版的kalman滤波器,实现对设备的kalman滤波,以验证他的理论算法。
犹豫了好几天,用dsp吧,我的kalman滤波算法比较简单,有点大材小用。刚好手里有一块arm调试版,也装了wince系统,就准备在.net环境下编一个kalman滤波器。
虽说学的是导航专业,对kalman滤波应该比较熟悉,可是当时学的就不好,所有学的东西都还给导师了。(导师您不会看到这篇文章吧!看来不能放在首页上!)
于是,只能在网上找一些相关资料。感觉现在变的懒了,总是喜欢在别人的代码上改来改去,不愿意去思考了。算了,反正就这么一次。罪过罪过!
国内的资料对于matlab的算法比较多了,网上随便down,但是基于C#的比较少,还好我的搜索能力不是很差,总算让我找到了相关资料。
引用博客的地址是:http://blog.csdn.net/csdnbao/archive/2009/09/24/4590519.aspx
文章把整个算法都写出来了,我也一起贴出来吧!
using System; using System.Collections.Generic; using System.Text; namespace SimTransfer { public class KalmanFacade { #region inner class class KalmanFilter { int MP; /* number of measurement vector dimensions */ int DP; /* number of state vector dimensions */ int CP; /* number of control vector dimensions */ public Matrix state_pre; /* predicted state (x'(k)): x(k)=A*x(k-1)+B*u(k) */ public Matrix state_post; /* corrected state (x(k)): x(k)=x'(k)+K(k)*(z(k)-H*x'(k)) */ public Matrix transition_matrix; /* state transition matrix (A) */ public Matrix control_matrix; /* control matrix (B) (it is not used if there is no control)*/ public Matrix measurement_matrix; /* measurement matrix (H) */ public Matrix process_noise_cov; /* process noise covariance matrix (Q) */ public Matrix measurement_noise_cov; /* measurement noise covariance matrix (R) */ public Matrix error_cov_pre; /* priori error estimate covariance matrix (P'(k)): P'(k)=A*P(k-1)*At + Q)*/ Matrix gain; /* Kalman gain matrix (K(k)): K(k)=P'(k)*Ht*inv(H*P'(k)*Ht+R)*/ Matrix error_cov_post; /* posteriori error estimate covariance matrix (P(k)): P(k)=(I-K(k)*H)*P'(k) */ Matrix temp1; /* temporary matrices */ Matrix temp2; Matrix temp3; Matrix temp4; Matrix temp5; public KalmanFilter() { MP = 1; DP = 2; CP = 0; state_pre = new Matrix(DP, 1); state_pre.Zero(); state_post = new Matrix(DP, 1); state_post.Zero(); transition_matrix = new Matrix(DP, DP); transition_matrix.SetIdentity(1.0); transition_matrix[0, 1] = 1; process_noise_cov = new Matrix(DP, DP); process_noise_cov.SetIdentity(1.0); measurement_matrix = new Matrix(MP, DP); measurement_matrix.SetIdentity(1.0); measurement_noise_cov = new Matrix(MP, MP); measurement_noise_cov.SetIdentity(1.0); error_cov_pre = new Matrix(DP, DP); error_cov_post = new Matrix(DP, DP); error_cov_post.SetIdentity(1); gain = new Matrix(DP, MP); if (CP > 0) { control_matrix = new Matrix(DP, CP); control_matrix.Zero(); } // temp1 = new Matrix(DP, DP); temp2 = new Matrix(MP, DP); temp3 = new Matrix(MP, MP); temp4 = new Matrix(MP, DP); temp5 = new Matrix(MP, 1); } public Matrix Predict() { state_pre = transition_matrix.Multiply(state_post); //if (CP>0) //{ // control_matrix //} temp1 = transition_matrix.Multiply(error_cov_post); Matrix at = transition_matrix.Transpose(); error_cov_pre = temp1.Multiply(at).Add(process_noise_cov); Matrix result = new Matrix(state_pre); return result; } public Matrix Correct(Matrix measurement) { temp2 = measurement_matrix.Multiply(error_cov_pre); Matrix ht = measurement_matrix.Transpose(); temp3 = temp2.Multiply(ht).Add(measurement_noise_cov); temp3.InvertSsgj(); temp4 = temp3.Multiply(temp2); gain = temp4.Transpose(); temp5 = measurement.Subtract(measurement_matrix.Multiply(state_pre)); state_post = gain.Multiply(temp5).Add(state_pre); error_cov_post = error_cov_pre.Subtract(gain.Multiply(temp2)); Matrix result = new Matrix(state_post); return result; } public Matrix AutoPredict(Matrix measurement) { Matrix result = Predict(); Correct(measurement); return result; } } #endregion public KalmanFacade(int valueItem) { if (valueItem<=0) { throw new Exception("not enough value items!"); } kmfilter = new KalmanFilter[valueItem]; Random rand = new Random(1001); for (int i = 0; i < valueItem; i++ ) { kmfilter[i] = new KalmanFilter(); kmfilter[i].state_post[0, 0] = rand.Next(10); kmfilter[i].state_post[1, 0] = rand.Next(10); // kmfilter[i].process_noise_cov.SetIdentity(1e-5); kmfilter[i].measurement_noise_cov.SetIdentity(1e-1); } } private KalmanFilter[] kmfilter = null; public bool GetValue(double[] inValue, ref double[] outValue) { if (inValue.Length != kmfilter.Length || outValue.Length != kmfilter.Length) { return false; } Matrix[] measures = new Matrix[kmfilter.Length]; for (int i = 0; i < kmfilter.Length; i++ ) { measures[i] = new Matrix(); measures[i][0, 0] = inValue[i]; outValue[i] = kmfilter[i].AutoPredict(measures[i])[0, 0]; } return true; } } } //==========test============= SimTransfer.KalmanFacade kalman = new SimTransfer.KalmanFacade(1); Random rand = new Random(1001); System.IO.StreamWriter dataFile = new System.IO.StreamWriter("D:\\test.csv"); for (int x = 0; x < 2000; x++ ) { double y = 100 * Math.Sin((2.0 * Math.PI / (float)200) * x); double noise = 20 * Math.Sin((40.0 * Math.PI / (float)200) * x) + 40 * (rand.NextDouble() - 0.5); double[] z_k = new double[1]; z_k[0] = y + noise; double[] y_k = new double[1]; kalman.GetValue(z_k, ref y_k); dataFile.WriteLine(y.ToString() + "," + z_k[0].ToString() + "," + y_k[0].ToString()); } dataFile.Close(); MessageBox.Show("OK!");
源码是很详细,但是注释比较少,看来我还得把程序翻译一遍!
这两天把注释重新写一下!!!
还有一个就是Matrix的类库。