过滤流数据以减少噪声,卡尔曼滤波器 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#的主要内容,如果未能解决你的问题,请参考以下文章

具有 2 个测量噪声的卡尔曼滤波器

过滤加速度计数据噪声

卡尔曼滤波器的实现以过滤加速度并找到速度和位置

实现卡尔曼滤波器以平滑来自 deviceOrientation API 的数据

如何在 Python 中使用卡尔曼滤波器获取位置数据?

卡尔曼滤波器+过程噪声协方差