平滑传感器的数据

Mwo*_*rks 23 algorithm sensor smoothing

我有一个测量v(x,y,z)数据的3D传感器.我只使用x和y数据.仅平滑x和y就足够了.

如果我使用日志显示数据,它会显示如下:(时间)0.1 ...(数据日志)x = 1.1234566667(时间)0.2 ...(数据日志)x = 1.1245655666(时间)0.3. ..(数据日志)x = 1.2344445555

实际上数据更准确,但我想在1.1234值和1.2344值之间平滑,因为对我来说它是相同的,我可以使用整数,只显示"x = 1"但我也需要小数,然后,我需要在这里展示一种"平滑"的价值.

任何人有任何想法?我正在使用c#进行编程,但并非所有函数都正常工作,所以我需要构建自己的函数.

sle*_*man 63

最简单的方法是对数据进行移动平均.也就是说,保持一系列传感器数据读数并对其进行平均.像这样的东西(伪代码):

  data_X = [0,0,0,0,0];

  function read_X () {
      data_X.delete_first_element();
      data_X.push(get_sensor_data_X());
      return average(data_X);
   }
Run Code Online (Sandbox Code Playgroud)

这样做有一个权衡.您使用的数组越大,结果越平滑,但结果与实际读数之间的滞后越大.例如:

                           /\_/\
                        /\/     \_/\
  Sensor reading:  __/\/            \/\
                                       \/\  _/\___________
                                          \/
                              _
                           __/ \_
                       ___/      \__
  Small array:     ___/             \_/\_       _
                                         \   __/ \________
                                          \_/

                                 ____
                              __/    \__
                           __/           \__
  Large array:     _______/                 \__      __
                                               \_   /  \__
                                                 \_/


(forgive my ASCII-ART but I'm hoping it's good enough for illustration).
Run Code Online (Sandbox Code Playgroud)

如果你想要快速响应但是平滑度很好,那么你使用的是阵列的加权平均值.这基本上是数字信号处理(与资本DSP)相反,其名称与模拟设计更为密切相关.这是一篇关于它的简短维基百科文章(如果你想沿着这条路走下去,你应该阅读好的外部链接):http://en.wikipedia.org/wiki/Digital_filter

以下是一些关于低通滤波器的代码,可以满足您的需求:低通滤波器软件?.请注意,在该答案的代码中,他使用的是大小为4的数组(或信号处理术语中的顺序4,因为此类过滤器称为四阶滤波器,它实际上可以通过四阶多项式方程建模:ax ^ 4 + bx ^ 3 + cx ^ 2 + dx).

  • ASCII艺术使得伟大的答案变得令人敬畏 (14认同)
  • 移动平均滤波器是低通滤波器的一种特殊情况,它是一个非常糟糕的滤波器(在性能方面).在频率响应和计算负荷以及程序复杂性方面,一阶低通滤波器通常(通常是?)优于移动平均值.对于许多应用程序,您可以忽略这些细节,例如可以缓慢响应的罗盘显示,移动平均值会很好.如果你有一个想要使用噪声传感器进行快速响应的游戏,移动平均线将是一个糟糕的解决方案,因为它会导致给定量的过滤滞后. (3认同)

tho*_*nic 22

所以我来到这里寻找解决同样的问题(Android中的传感器输入平滑),这就是我想出的:

/*
 * time smoothing constant for low-pass filter
 * 0 ? ? ? 1 ; a smaller value basically means more smoothing
 * See: http://en.wikipedia.org/wiki/Low-pass_filter#Discrete-time_realization
 */
static final float ALPHA = 0.2f;

protected float[] accelVals;

public void onSensorChanged(SensorEvent event) {
    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
        accelVals = lowPass( event.values, accelVals );

    // use smoothed accelVals here; see this link for a simple compass example:
    // http://www.codingforandroid.com/2011/01/using-orientation-sensors-simple.html
}

/**
 * @see http://en.wikipedia.org/wiki/Low-pass_filter#Algorithmic_implementation
 * @see http://en.wikipedia.org/wiki/Low-pass_filter#Simple_infinite_impulse_response_filter
 */
protected float[] lowPass( float[] input, float[] output ) {
    if ( output == null ) return input;

    for ( int i=0; i<input.length; i++ ) {
        output[i] = output[i] + ALPHA * (input[i] - output[i]);
    }
    return output;
}
Run Code Online (Sandbox Code Playgroud)

谢谢@slebetman指点我看维基百科的链接,经过一番阅读后,我就开始了解维基百科低通过滤器文章中的算法.我不会发誓我有最好的算法(甚至是正确的!)但是轶事证据似乎表明它正在做这个伎俩.

  • 只是想说,如果你在android上使用这个代码,最初返回input.copy()而不是数组本身.我的传感器写入相同的数组,即输入和输出是相同的数组,平滑将不起作用. (2认同)

Jay*_*ora 7

有很多方法可以平滑传感器数据,这取决于它是什么类型的传感器以及适合的类比。我在我的项目中使用了这些算法:

  1. 高通滤波器 [HPF] 和低通滤波器 [LPF]- 如所选答案所示。
  2. 移动平均算法-MAA
  3. Gaely 算法mm[MAA 的更好版本]
  4. 快速傅立叶变换-FFT

代码:

HPF-高通滤波器

private float[] highPass(float x, float y, float z) {
    float[] filteredValues = new float[3];
    gravity[0] = ALPHA * gravity[0] + (1 – ALPHA) * x;
    gravity[1] = ALPHA * gravity[1] + (1 – ALPHA) * y;
    gravity[2] = ALPHA * gravity[2] + (1 – ALPHA) * z;
    filteredValues[0] = x – gravity[0];
    filteredValues[1] = y – gravity[1];
    filteredValues[2] = z – gravity[2];
    return filteredValues;   
    }
Run Code Online (Sandbox Code Playgroud)

LPF-低通滤波器

private float[] lowPass(float x, float y, float z) {
    float[] filteredValues = new float[3];
    filteredValues[0] = x * a + filteredValues[0] * (1.0f – a);
    filteredValues[1] = y * a + filteredValues[1] * (1.0f – a);
    filteredValues[2] = z * a + filteredValues[2] * (1.0f – a);
    return filteredValues;
    }
Run Code Online (Sandbox Code Playgroud)

MAA-移动平均线

     private final int SMOOTH_FACTOR_MAA = 2;//increase for better results   but hits cpu bad

     public ArrayList<Float> processWithMovingAverageGravity(ArrayList<Float> list, ArrayList<Float> gList) {
            int listSize = list.size();//input list
            int iterations = listSize / SMOOTH_FACTOR_MAA;
            if (!AppUtility.isNullOrEmpty(gList)) {
                gList.clear();
            }
            for (int i = 0, node = 0; i < iterations; i++) {
                float num = 0;
                for (int k = node; k < node + SMOOTH_FACTOR_MAA; k++) {
                    num = num + list.get(k);
                }
                node = node + SMOOTH_FACTOR_MAA;
                num = num / SMOOTH_FACTOR_MAA;
                gList.add(num);//out put list
            }
            return gList;
        }
Run Code Online (Sandbox Code Playgroud)

  • 盖利算法是什么? (2认同)