||
最佳线性滤波理论起源于40年代美国科学家Wiener和前苏联科学家Kолмогоров等人的研究工作,后人统称为维纳滤波理论。从理论上说,维纳滤波的最大缺点是必须用到无限过去的数据,不适用于实时处理。为了克服这一缺点,60年代Kalman把状态空间模型引入滤波理论,并导出了一套递推估计算法,后人称之为卡尔曼滤波理论。卡尔曼滤波是以最小均方误差为估计的最佳准则,来寻求一套递推估计的算法,其基本思想是:采用信号与噪声的状态空间模型,利用前一时刻地估计值和现时刻的观测值来更新对状态变量的估计,求出现时刻的估计值。它适合于实时处理和计算机运算。卡尔曼滤波在工程计算中十分有用,所以想去尝试一下卡尔曼滤波器的实现。通过C#平台,采用确定范围内的随机数的方法模拟实际测量值,进行卡尔曼滤波的计算,最后成图。
模拟温度的测量:
最后实际效果图如下:
贴上源代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
namespace 折线图
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
double[] CanShu = { 23, 9, 16, 16, 1, 0, 0, 0 };
//double[] Observ = { 22, 24, 24, 25, 24, 26, 21, 26, };
//double[] Observ = { 25, 26 };
double[] ObsRand = new double[100];
private void button1_Click(object sender, EventArgs e)
{
//产生随机数列
for (int i = 0; i < 100; i++)
{
//Random Random1 = new Random();//这样声明的话,如果多次调用rnd则会会出现每次的随机数值都一样
Random Random1 = new Random((int)DateTime.Now.Ticks); //利用系统日期作为参数传进去之后可以解决上面出现的问题
double i1 = Random1.Next(20, 30);
double result = Random1.NextDouble() * (-0.99) + 0.99;//随机生成-0.90至0.99的随机双精度数值
ObsRand[i] = i1+result;
this.richTextBox2.Text += ObsRand[i].ToString() + "n";
}
chart1.Series.Clear();
graphPoint(chart1, "测量值", ObsRand, Color.PowderBlue);
double[] True = GetKalMan(CanShu, ObsRand);
graph(chart1, "滤波后值",True, Color.Black);
double[] Ave = new double[ObsRand.Length];
for (int i = 0; i < ObsRand.Length; i++)
{
Ave[i] = Average;
}
graph(chart1, "平均值", Ave, Color.Red);
}
//画图函数
protected void graph(Chart c, string name, double[] vals, Color clr)
{
Series s = new Series(name);
s.ChartType = SeriesChartType.Line;
for (int i = 0; i < vals.Length; i++)
{
s.Points.Add(new DataPoint(i, vals[i]));
}
s.Color = clr;
c.Series.Add(s);
}
//画图函数2
protected void graphPoint(Chart c, string name, double[] vals, Color clr)
{
Series s = new Series(name);
s.ChartType = SeriesChartType.Point;
for (int i = 0; i < vals.Length; i++)
{
s.Points.Add(new DataPoint(i, vals[i]));
}
s.Color = clr;
c.Series.Add(s);
}
//滤波函数
double Average;
public double[] GetKalMan(double[] CanShu, double[] Observe)
{
double KamanX = CanShu[0];
double KamanP = CanShu[1];
double KamanQ = CanShu[2];
double KamanR = CanShu[3];
double KamanY = CanShu[4];
double KamanKg =CanShu[5];
double KamanSum = CanShu[6];
double[] True = new double[ObsRand.Length];
for (int i = 0; i <= ObsRand.Length - 1; i++)
{
KamanY = KamanX;
KamanP = KamanP + KamanQ;
KamanKg = KamanP / (KamanP + KamanR);
KamanX = (KamanY + KamanKg * (Observe[i] - KamanY));
KamanSum += KamanX;
True[i] = KamanX;
this.richTextBox1.Text += KamanX.ToString() + "n";
KamanP = (1 - KamanKg) * KamanP;
}
Average = KamanSum / Observe.Length;
return True;
}
}
}
特别注意一点,产生随机数的时候,一定要获取系统时间点,否则在循环后发现很多值表现为连续一样,不符合实际测量规律
具体算法可以参照维基百科
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-12-28 16:21
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社