【问题标题】:Filtering streaming data to reduce noise, kalman filter c#过滤流数据以减少噪声,卡尔曼滤波器 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 的值并且与噪声无关(在他的计算中没有参考噪声或稳定读数)

标签: c# streaming kalman-filter


【解决方案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,因为我们有更多数据进行估计。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-01
    • 2011-04-14
    • 1970-01-01
    • 2017-04-05
    • 2019-04-25
    相关资源
    最近更新 更多