示例1用到了ZedGraph进行绘图并保存结果图片。 示例2在WPF下使用Gu.Wpf.DataGrid2D控件显示数据和oxy:Plot控件绘图。

示例1-Console

Result

代码:

using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Double;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnscentedKalmanFilter;
using ZedGraph;namespace Example
{class Program{static void Main(string[] args){var filter = new UKF();//无迹卡尔曼滤波List<double> measurements = new List<double>();//测量值列表List<double> states = new List<double>();//预测状态Random rnd = new Random();for (int k = 0; k < 100; k++){var measurement = Math.Sin(k * 3.14 * 5 / 180) + (double)rnd.Next(50) / 100;//生成随机测量值measurements.Add(measurement);filter.Update(new[] { measurement });//更新状态 更新协方差states.Add(filter.getState()[0]);//预测状态值添加到列表}//ZedGraph.GraphPane https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/99716066 //https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100112573//https://blog.csdn.net/qq_31324491/article/details/106634800GraphPane myPane = new GraphPane(new RectangleF(0, 0, 3200, 2400), "Unscented Kalman Filter", "number", "measurement");//尺寸、标题、x标题、y标题PointPairList measurementsPairs = new PointPairList();//测量点对列表PointPairList statesPairs = new PointPairList();//预测点对列表for (int i = 0; i < measurements.Count; i++){measurementsPairs.Add(i, measurements[i]);statesPairs.Add(i, states[i]);}//绘制曲线myPane.AddCurve("measurement", measurementsPairs, Color.Red, SymbolType.Circle);//曲线标签,点对数据,颜色,符号类型myPane.AddCurve("estimate", statesPairs, Color.Green, SymbolType.XCross);//保存图片Bitmap bm = new Bitmap(200, 200);Graphics g = Graphics.FromImage(bm);myPane.AxisChange(g);Image im = myPane.Image;im.Save("result.png", ImageFormat.Png);}}
}

示例2-WPF

Result

主窗口界面

<Window x:Class="DemoApp.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:DemoApp"xmlns:oxy="http://oxyplot.org/wpf"xmlns:dg2d="http://gu.se/DataGrid2D"mc:Ignorable="d"Title="MainWindow" Height="350" Width="525"><DockPanel><Grid DockPanel.Dock="Bottom" ><Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Column="1"><TabControl><TabItem Header="Graph"><oxy:Plot  x:Name="Plot1" Grid.Column="0"  ><oxy:Plot.Series><oxy:AreaSeries ItemsSource="{Binding Estimates}"  Title="Estimate Deviation"    DataFieldX="Time" DataFieldY="LowerDeviation" DataFieldX2="Time" DataFieldY2="UpperDeviation" /><oxy:LineSeries ItemsSource="{Binding Measurements}"   Title="Measurement"   DataFieldX="Time" DataFieldY="Value"  MarkerType="Cross"/><oxy:LineSeries ItemsSource="{Binding Estimates}"  Title="Estimate"    DataFieldX="Time" DataFieldY="Value"  /></oxy:Plot.Series><oxy:Plot.Axes><oxy:LinearAxis Position="Bottom"/><oxy:LinearAxis Position="Left"/></oxy:Plot.Axes></oxy:Plot></TabItem><TabItem Header="DataTable"><DataGrid  Grid.Column="1" x:Name="DataGrid1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"ItemsSource="{Binding Measurements}"/></TabItem></TabControl>      </Grid></Grid></DockPanel>
</Window>

主窗口的交互逻辑:

/// <summary>/// 主窗口.xaml的交互逻辑 /// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();var x = new MainWindowViewModel();//获取视图模型对象this.DataContext = x;//数据绑定}}

主窗口的视图模型:

using System;
using System.Collections.ObjectModel;
using UnscentedKalmanFilter;namespace DemoApp
{class MainWindowViewModel : INPCBase//视图模型{//ObservableCollection 表示一个动态数据集合,它可在添加、删除项目或刷新整个列表时提供通知。public ObservableCollection<Measurement> Measurements { get; set; }public ObservableCollection<Measurement> Estimates { get; set; }public MainWindowViewModel(){Measurements = new ObservableCollection<Measurement>();Estimates = new ObservableCollection<Measurement>();var filter = new UKF();//无迹卡尔曼滤波var N = 100;for (int k = 1; k < N; k++){double[] z = ProcessBuilder.SineWave(k);//计算正弦值 带噪声filter.Update(z);//滤波var state = filter.getState();//获取预测装填var covariance = filter.getCovariance();//获取协方差Measurements.Add(new Measurement() { Value = z[0], Time = TimeSpan.FromSeconds(k) });//构造测量值对象,添加到测量值集合Estimates.Add(new Measurement() { Value = state[0], Time = TimeSpan.FromSeconds(k), Variance = covariance[0, 0] });//构造预测值对象,添加到预测值集合}}}//随机值处理器public static class ProcessBuilder{private static Random rnd = new Random();public static double[] SineWave(int iteration)//计算正弦值{return new[] { Math.Sin(iteration * 3.14 * 5 / 180) + (double)rnd.Next(50) / 100 };}}public struct Measurement//测量{private double variance;//协方差public double Value { get; set; }//值public TimeSpan Time { get; set; }//时间public double Variance {get{return  variance;}set{variance = value;//设置协方差的值UpperDeviation = Value + Math.Sqrt(variance);//上限偏差LowerDeviation = Value - Math.Sqrt(variance);//下限偏差}}public double UpperDeviation { get;private set; }//获取上偏差public double LowerDeviation{ get; private set; }//获取下偏差}
}

属性改变接口:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace DemoApp
{public abstract class INPCBase : INotifyPropertyChanged{#region INotifyPropertyChanged Implementation/// <summary>/// 在更改此对象上的任何属性时发生。/// </summary>public event PropertyChangedEventHandler PropertyChanged;/// <summary>/// 引发属性的PropertyChanged事件的辅助方法。/// </summary>/// <param name="propertyNames">The names of the properties that changed.</param>public virtual void NotifyChanged(params string[] propertyNames){foreach (string name in propertyNames){OnPropertyChanged(new PropertyChangedEventArgs(name));}}/// <summary>/// 引发PropertyChanged事件。/// </summary>/// <param name="e">Event arguments.</param>protected virtual void OnPropertyChanged(PropertyChangedEventArgs e){if (this.PropertyChanged != null){this.PropertyChanged(this, e);}}#endregion}
}

无迹卡尔曼滤波算法代码:

using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.LinearAlgebra.Factorization;
using System;namespace UnscentedKalmanFilter
{public class UKF{/// <summary>/// 状态值States number/// </summary>private int L;  /// <summary>/// 测量值Measurements number/// </summary>private int m;/// <summary>/// 系数,表示均值附近的sigma-point离散/// The alpha coefficient, characterize sigma-points dispersion around mean/// </summary>private double alpha;  /// <summary>/// The ki./// </summary>private double ki;/// <summary>/// beta系数,表征型分布(2为正态分布)/// The beta coefficient, characterize type of distribution (2 for normal one) /// </summary>private double beta;/// <summary>/// 比例因子Scale factor/// </summary>private double lambda;/// <summary>/// Scale factor/// </summary>private double c; /// <summary>/// 平均权值Means weights/// </summary>private Matrix<double> Wm;/// <summary>///协方差的权值 Covariance weights/// </summary>private Matrix<double> Wc;/// <summary>/// 状态State/// </summary>private Matrix<double> x;/// <summary>/// 协方差 Covariance/// </summary>private Matrix<double> P;/// <summary>/// Std of process /// </summary>private double q;/// <summary>/// Std of measurement /// </summary>private double r;/// <summary>/// Covariance of process/// </summary>private Matrix<double> Q;/// <summary>/// Covariance of measurement /// </summary>private Matrix<double> R;/// <summary>/// Constructor of Unscented Kalman Filter/// 无迹卡尔曼滤波的构造函数/// </summary>/// <param name="L">States number</param>/// <param name="m">Measurements number</param>public UKF(int L = 0){this.L = L;}private void init(){q = 0.05;r = 0.3; x = q * Matrix.Build.Random(L, 1); //带噪声的初始状态initial state with noiseP = Matrix.Build.Diagonal(L, L, 1); //初始状态协方差 initial state CovarianceQ = Matrix.Build.Diagonal(L, L, q * q); //Covariance of processR = Matrix.Build.Dense(m, m, r * r); //Covariance of measurement  alpha = 1e-3f;ki = 0;beta = 2f;lambda = alpha * alpha * (L + ki) - L;c = L + lambda;//weights for meansWm = Matrix.Build.Dense(1, (2 * L + 1), 0.5 / c);Wm[0, 0] = lambda / c;//weights for covarianceWc = Matrix.Build.Dense(1, (2 * L + 1));Wm.CopyTo(Wc);Wc[0, 0] = Wm[0, 0] + 1 - alpha * alpha + beta;c = Math.Sqrt(c);}public void Update(double[] measurements){if (m == 0){var mNum = measurements.Length;if (mNum > 0){m = mNum;if (L == 0) L = mNum;init();}}var z = Matrix.Build.Dense(m, 1, 0);z.SetColumn(0, measurements);//sigma points around xMatrix<double> X = GetSigmaPoints(x, P, c);//无迹变换 unscented transformation of process// X1=sigmas(x1,P1,c) - sigma points around x1//X2=X1-x1(:,ones(1,size(X1,2))) - deviation of X1Matrix<double>[] ut_f_matrices = UnscentedTransform(X, Wm, Wc, L, Q);Matrix<double> x1 = ut_f_matrices[0];Matrix<double> X1 = ut_f_matrices[1];Matrix<double> P1 = ut_f_matrices[2];Matrix<double> X2 = ut_f_matrices[3];//unscented transformation of measurmentsMatrix<double>[] ut_h_matrices = UnscentedTransform(X1, Wm, Wc, m, R);Matrix<double> z1 = ut_h_matrices[0];Matrix<double> Z1 = ut_h_matrices[1];Matrix<double> P2 = ut_h_matrices[2];Matrix<double> Z2 = ut_h_matrices[3];//transformed cross-covarianceMatrix<double> P12 = (X2.Multiply(Matrix.Build.Diagonal(Wc.Row(0).ToArray()))).Multiply(Z2.Transpose());Matrix<double> K = P12.Multiply(P2.Inverse());//更新状态state updatex = x1.Add(K.Multiply(z.Subtract(z1)));//更新协方差covariance update P = P1.Subtract(K.Multiply(P12.Transpose()));}public double[] getState(){return x.ToColumnArrays()[0];}public double[,] getCovariance(){return P.ToArray();}/// <summary>/// Unscented Transformation/// </summary>/// <param name="f">nonlinear map</param>/// <param name="X">sigma points</param>/// <param name="Wm">Weights for means</param>/// <param name="Wc">Weights for covariance</param>/// <param name="n">numer of outputs of f</param>/// <param name="R">additive covariance</param>/// <returns>[transformed mean, transformed smapling points, transformed covariance, transformed deviations</returns>private Matrix<double>[] UnscentedTransform(Matrix<double> X, Matrix<double> Wm, Matrix<double> Wc, int n, Matrix<double> R){int L = X.ColumnCount;Matrix<double> y = Matrix.Build.Dense(n, 1, 0);Matrix<double> Y = Matrix.Build.Dense(n, L, 0);Matrix<double> row_in_X;for (int k = 0; k < L; k++){row_in_X = X.SubMatrix(0, X.RowCount, k, 1);Y.SetSubMatrix(0, Y.RowCount, k, 1, row_in_X);y = y.Add(Y.SubMatrix(0, Y.RowCount, k, 1).Multiply(Wm[0,k]));}Matrix<double> Y1 = Y.Subtract(y.Multiply(Matrix.Build.Dense(1,L,1)));Matrix<double> P = Y1.Multiply(Matrix.Build.Diagonal(Wc.Row(0).ToArray()));P = P.Multiply(Y1.Transpose());P = P.Add(R);Matrix<double>[] output = { y, Y, P, Y1 };return output;}/// <summary>/// Sigma points around reference point/// </summary>/// <param name="x">reference point</param>/// <param name="P">covariance</param>/// <param name="c">coefficient</param>/// <returns>Sigma points</returns>private Matrix<double> GetSigmaPoints(Matrix<double> x, Matrix<double> P, double c) {Matrix<double> A = P.Cholesky().Factor;A = A.Multiply(c);A = A.Transpose();int n = x.RowCount;Matrix<double> Y = Matrix.Build.Dense(n, n, 1);for (int j=0; j<n; j++)  {Y.SetSubMatrix(0, n, j, 1, x);}Matrix<double> X = Matrix.Build.Dense(n,(2*n+1));X.SetSubMatrix(0, n, 0, 1, x);Matrix<double> Y_plus_A = Y.Add(A);  X.SetSubMatrix(0, n, 1, n, Y_plus_A);Matrix<double> Y_minus_A = Y.Subtract(A);X.SetSubMatrix(0, n, n+1, n, Y_minus_A);return X;}}
}

参考:

https://blog.csdn.net/muxi_huang/article/details/105070498 C#控件ZedGraph使用小

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/101370197 

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/99716066        https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100112573

https://blog.csdn.net/qq_31324491/article/details/106634800

https://blog.csdn.net/Frankgoogle/article/details/105525098

https://blog.csdn.net/ouyangliping/article/details/5152476

https://zhuanlan.zhihu.com/p/399370551

https://www.cnblogs.com/long5683/p/14091520.html

https://www.cnblogs.com/yrm1160029237/p/10161663.html

https://cloud.tencent.com/developer/article/2040902

The End

【Unscented Kalman Filter】C#无迹卡尔曼滤波Demo--两个示例附代码相关推荐

  1. RBF-UKF径向基神经网络结合无迹卡尔曼滤波估计锂离子电池SOC(附MATLAB代码)

    目录 RBFNN训练结果 UKF估计SOC 文章的结尾红色部分有彩蛋 RBFNN训练结果 这篇文章主要介绍如何使用RBF神经网络训练出的参数并结合UKF算法完成锂离子电池SOC的估计,有关RBF参数训 ...

  2. [译]无迹卡尔曼滤波教程

    无迹卡尔曼滤波器 https://www.cse.sc.edu/~terejanu/files/tutorialUKF.pdf 翻译的文件可以直接在这里下载:https://download.csdn ...

  3. 多目标跟踪(MOT)中的卡尔曼滤波(Kalman filter)和匈牙利(Hungarian)算法详解

    多目标跟踪(MOT)中的卡尔曼滤波(Kalman filter)和匈牙利(Hungarian)算法详解 1. 概览 在开始具体讨论卡尔曼滤波和匈牙利算法之前,首先我们来看一下基于检测的目标跟踪算法的大 ...

  4. 手撕自动驾驶算法——无迹卡尔曼滤波(UKF)

    文章目录 1. 简介 2. CTRV运动模型 2.1 CTRV的目标状态量: 2.2 CTRV的状态转移函数: 2.3 CTRV Process Noise 3. Prediction 3.1 Gen ...

  5. 【滤波】无迹卡尔曼滤波

    本文主要翻译自rlabbe/Kalman-and-Bayesian-Filters-in-Python的第10章节10-Unscented-Kalman-Filter(无迹卡尔曼滤波). %matpl ...

  6. 对Kalman Filter的理解

    1. 卡尔曼滤波理论回顾 对于一个动态系统,我们首先定义一组状态空间方程 状态方程:      测量方程:       xk是状态向量,zk是测量向量,Ak是状态转移矩阵,uk是控制向量,Bk是控制矩 ...

  7. ukf实测信号的预测 matlab,ukf(无迹卡尔曼滤波)算法的matlab程序.

     ukf(无迹卡尔曼滤波)算法的matlab程序. function [x,P]=ukf(fstate,x,P,hmeas,z,Q,R) % UKF   Unscented Kalman Filt ...

  8. ukf(无迹卡尔曼滤波)算法的matlab程序.

     ukf(无迹卡尔曼滤波)算法的matlab程序. function [x,P]=ukf(fstate,x,P,hmeas,z,Q,R) % UKF   Unscented Kalman Filt ...

  9. UKF 无迹卡尔曼滤波

    目录 参考: UKF数学原理: UKF的基本非线性系统描述: 计算sigma point和权重参数 UKF的基本预测步和更新步: UKF代码实现: 参考: UKF数学原理: UKF的基本非线性系统描述 ...

  10. Quaternion kinematics for error state kalman filter实现GPS+IMU融合,(附源码)

    最近在学习kalman滤波相关的知识,恰好工作可能需要使用ESKF算法,因此将Joan Sola大神的书看了一遍,同时推导了相关的公式.俗话说得好:"Talk is cheap, show ...

最新文章

  1. 简单查找,如果找到返回下标,如果找不到返回-1
  2. shell grep sed awk 练习
  3. python安装不上怎么办_python安装不了怎么办
  4. vue官方eslint插件配置eslint-plugin-vue-libs
  5. 苹果电脑上超级好用的双栏文件管理器Commander One PRO版推荐给大家!
  6. 计算机基础知识 笔试,计算机基础知识笔试题
  7. Flutter 页面滚动吸顶详解(NestedScrollView)
  8. python读取ansi编码文件,如何在Python中同时读取ANSI和Unicode txt文件?
  9. Docker简介及Linux下安装
  10. flex3提示mysql2_flex3+struts2+spring2+hibernate3+mysql(在web项目里面建flex,而不是flex工程)...
  11. 分布式搜索Elasticsearch增、删、改、查操作深入详解
  12. cat5e跑万兆_cat5e网线支持千兆吗?
  13. 欧姆龙nj与nx哪个高端_没想到还有比三菱更垃圾的PLC,欧姆龙隆重登场
  14. 菜菜PyTorch深度学习框架最全笔记(第一次课)
  15. 一键快速打开IE的Internet选项->连接->局域网设置
  16. Zoom会议多开 or 同时加入多个Zoom Meeting
  17. COB-ID的简单理解分析
  18. 中国科学院院士徐宗本:人工智能的基石是数学
  19. 好用的二维码API接口
  20. 【机考】华为OD2022.11.01机考题目思路与代码

热门文章

  1. python短信验证码_python发送短信验证码
  2. 医学影像中的基础知识
  3. 离散 单射 满射 双射
  4. PyAutoGUI库-模拟鼠标键盘操作
  5. SQL Server 数据库作业(备份、同步)
  6. 如何撰写《软件项目方案文档》
  7. Focal loss分析
  8. 纹波(ripple)的定义
  9. 两个表格合并怎么做?
  10. 采用JDBC解释java SPI机制和线程上下文类加载器 —————— 开开开山怪