过滤流数据以减少噪声,卡尔曼滤波器 c#
Posted
技术标签:
【中文标题】过滤流数据以减少噪声,卡尔曼滤波器 c#【英文标题】:Filtering streaming data to reduce noise, kalman filter c# 【发布时间】:2016-09-04 10:12:24 【问题描述】:我正在从惯性传感器将数据流式传输到 C# 应用程序中。数据有点嘈杂,所以我需要添加一个过滤器来平滑它。我有一个卡尔曼滤波器实现,在给定数组时效果很好,但我无法理解如何在恒定数据流上使用它。
我有:
double sensorData; //the noisy value, constantly updating from another class.
过滤器:
public static double[] noisySine = new double[20] 40, 41, 38, 40, 45, 42, 43, 44, 40, 38, 44, 45, 40, 39, 37, 41, 42, 70, 44, 42 ;
public static double[] clean = new double[20];
public static void KalmanFilter(double[] noisy)
double A = double.Parse("1"); //factor of real value to previous real value
// double B = 0; //factor of real value to real control signal
double H = double.Parse("1");
double P = double.Parse("0.1");
double Q = double.Parse("0.125"); //Process noise.
double R = double.Parse("1"); //assumed environment noise.
double K;
double z;
double x;
//assign to first measured value
x = noisy[0];
for (int i = 0; i < noisy.Length; i++)
//get current measured value
z = noisy[i];
//time update - prediction
x = A * x;
P = A * P * A + Q;
//measurement update - correction
K = P * H / (H * P * H + R);
x = x + K * (z - H * x);
P = (1 - K * H) * P;
//estimated value
clean[i] = x;
Console.WriteLine(noisy[i] + " " + clean[i]);
如何将双精度流而不是数组输入并返回(过滤的)双精度?
谢谢。
【问题讨论】:
一个 double 是八个字节。要流式传输数据,您需要一个字节数组。所以使用 Bit.Converter 类。 您好,感谢您的回复。我不明白你的意思。我有一个变量(双)不断更新。我需要将它发送到当前与 double[] 一起使用的过滤器函数中。 @anti 你解决过这个问题吗? 这个实现中有一个错误:当这个代码迭代时,P 很快变成接近 R/100000 的值并且与噪声无关(在他的计算中没有参考噪声或稳定读数) 【参考方案1】:创建这个类:
public class KalmanFilter
private double A, H, Q, R, P, x;
public KalmanFilter(double A, double H, double Q, double R, double initial_P, double initial_x)
this.A = A;
this.H = H;
this.Q = Q;
this.R = R;
this.P = initial_P;
this.x = initial_x;
public double Output(double input)
// time update - prediction
x = A * x;
P = A * P * A + Q;
// measurement update - correction
double K = P * H / (H * P * H + R);
x = x + K * (input - H * x);
P = (1 - K * H) * P;
return x;
并使用类:
KalmanFilter filter = new KalmanFilter(1, 1, 0.125, 1, 0.1, noisySine[0]);
for (int i = 0; i < noisy.Length; i++) clean[i] = filter.Output(noisySine[i]);
【讨论】:
【参考方案2】:试试下面的代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication1
class Program
static void Main(string[] args)
double[] input = 1.1,2.2,3.3,4.4;
byte[] bArray = input.Select(x => BitConverter.GetBytes(x)).SelectMany(y => y).ToArray();
MemoryStream inStream = new MemoryStream(bArray);
long length = inStream.Length;
byte[] outArray = new byte[length];
inStream.Read(outArray, 0, (int)length);
List<double> output = new List<double>();
for (int i = 0; i < bArray.Length; i += 8)
output.Add(BitConverter.ToDouble(outArray,i));
【讨论】:
谢谢,但我不认为这是我需要的。这如何帮助我将数据流发送到上面的过滤器函数中?抱歉,如果我遗漏了什么! 我更新了代码以显示所有需要的代码。我使用了内存流。【参考方案3】:这是修改代码以输入双精度并返回过滤后的双精度的方法。
public static void KalmanTest()
double[] noisySine = new double[20] 40, 41, 38, 40, 45, 42, 43, 44, 40, 38, 44, 45, 40, 39, 37, 41, 42, 70, 44, 42 ;
for (int i = 0; i < noisySine.Length; i++)
Console.WriteLine(noisySine[i] + " " + KalmanFilter(noisySine[i]));
// assign default values
// for a new mwasurement, reset this values
public static double P = double.Parse("1"); // MUST be greater than 0
public static double clean = double.Parse("0"); // any value
public static double KalmanFilter(double noisy)
double A = double.Parse("1"); //factor of real value to previous real value
// double B = 0; //factor of real value to real control signal
double H = double.Parse("1");
double Q = double.Parse("0.125"); //Process noise.
double R = double.Parse("1"); //assumed environment noise.
double K;
double z;
double x;
//get current measured value
z = noisy;
//time update - prediction
x = A * clean;
P = A * P * A + Q;
//measurement update - correction
K = P * H / (H * P * H + R);
x = x + K * (z - H * x);
P = (1 - K * H) * P;
//estimated value
clean = x;
return clean;
注意:有一个错误。当此代码迭代时,P 很快变为接近 R/100000 的值,并且此行为与噪声无关,因为在 P 计算中没有参考噪声或稳定读数。 干净的代码看起来像一个低通滤波器:
// assign default values
public static double clean = double.Parse("0"); // any value
public static double KalmanFilter(double noisy)
double K = double.Parse("0.125"); // noise 0 < K < 1
clean = clean + K * (noisy - clean);
return clean;
【讨论】:
这不是错误,P(估计不确定性)每次新测量都会变为 0,因为我们有更多数据进行估计。以上是关于过滤流数据以减少噪声,卡尔曼滤波器 c#的主要内容,如果未能解决你的问题,请参考以下文章