【问题标题】:Filtering accelerometer data noise过滤加速度计数据噪声
【发布时间】:2010-12-10 23:10:14
【问题描述】:

如何在 Android 中过滤加速度计数据的噪音?我想为我的样本数据创建一个高通滤波器,以便我可以消除低频分量并专注于高频分量。我已经读过卡尔曼滤波器可能是最好的选择,但是我如何在我的应用程序中集成或使用这种方法,而我的应用程序主要是用 Android Java 编写的?还是可以首先完成?还是通过Android NDK?有没有可能实时完成?

任何想法将不胜感激。谢谢!

【问题讨论】:

    标签: android accelerometer


    【解决方案1】:

    Apple SDK 中的示例实际上以更简单的方式实现过滤,即使用渐变:

    //ramp-speed - 玩这个值直到满意 常量浮动 kFilteringFactor = 0.1f; //最后一个结果存储 - 将定义保留在此函数之外,例如。在包装对象 浮动加速度[3]; //acceleration.x,.y,.z 是传感器的输入 //result.x,.y,.z是过滤后的结果 //高通滤波器消除重力 加速度[0] = 加速度.x * kFilteringFactor + accel[0] * (1.0f - kFilteringFactor); 加速度[1] = 加速度.y * kFilteringFactor + accel[1] * (1.0f - kFilteringFactor); 加速度[2] = 加速度.z * kFilteringFactor + accel[2] * (1.0f - kFilteringFactor); 结果.x = 加速度.x - 加速度[0]; 结果.y = 加速度.y - 加速度[1]; 结果.z = 加速度.z - 加速度[2];

    【讨论】:

    • 我不确定我是否关注这里发生的事情......如果acceleration.x是恒定的(理论上这可能发生),而不是result.x =0; accel[0] 看起来像过滤后的输出;不确定 result.x 是什么。
    【解决方案2】:

    这是适用于 Android 的代码,改编自苹果自适应高通滤波器示例。只需将其插入并实现 onFilteredAccelerometerChanged()

    private static final boolean ADAPTIVE_ACCEL_FILTER = true;
    float lastAccel[] = new float[3];
    float accelFilter[] = new float[3];
    
    public void onAccelerometerChanged(float accelX, float accelY, float accelZ) {
        // high pass filter
        float updateFreq = 30; // match this to your update speed
        float cutOffFreq = 0.9f;
        float RC = 1.0f / cutOffFreq;
        float dt = 1.0f / updateFreq;
        float filterConstant = RC / (dt + RC);
        float alpha = filterConstant; 
        float kAccelerometerMinStep = 0.033f;
        float kAccelerometerNoiseAttenuation = 3.0f;
    
        if(ADAPTIVE_ACCEL_FILTER)
        {
            float d = clamp(Math.abs(norm(accelFilter[0], accelFilter[1], accelFilter[2]) - norm(accelX, accelY, accelZ)) / kAccelerometerMinStep - 1.0f, 0.0f, 1.0f);
            alpha = d * filterConstant / kAccelerometerNoiseAttenuation + (1.0f - d) * filterConstant;
        }
    
        accelFilter[0] = (float) (alpha * (accelFilter[0] + accelX - lastAccel[0]));
        accelFilter[1] = (float) (alpha * (accelFilter[1] + accelY - lastAccel[1]));
        accelFilter[2] = (float) (alpha * (accelFilter[2] + accelZ - lastAccel[2]));
    
        lastAccel[0] = accelX;
        lastAccel[1] = accelY;
        lastAccel[2] = accelZ;
        onFilteredAccelerometerChanged(accelFilter[0], accelFilter[1], accelFilter[2]);
    }
    

    【讨论】:

    • norm()和clamp()应该怎么做?
    • 我会说“范数”是指计算给定向量的范数 (sqrt([0]^2+[1]^2´[2]^2)) 并且钳位是一个限制具有上下边界的函数(在这种情况下,第一个 arg 限制在 0.0f 和 1.0f 之间)。另外,非常感谢自适应示例,我想我会采用某种形式。
    • 如何确定这些变量的值? (RC、dt、cutOffFreq 等等..)
    【解决方案3】:

    对于那些想知道 norm() 和 clamp() 方法在 rbgrn 的答案中的作用的人,您可以在此处查看它们: http://developer.apple.com/library/IOS/samplecode/AccelerometerGraph/Listings/AccelerometerGraph_AccelerometerFilter_m.html

    double norm(double x, double y, double z)
    {
        return Math.sqrt(x * x + y * y + z * z);
    }
    
    double clamp(double v, double min, double max)
    {
        if(v > max)
            return max;
        else if(v < min)
            return min;
        else
            return v;
    }
    

    【讨论】:

      【解决方案4】:

      我似乎记得这是在 Apple 的 iPhone 示例代码中完成的。让我们看看...

      在 Google 上查找 AccelerometerFilter.h / .m(或获取 Apple 的 AccelerometerGraph 示例)和此链接:http://en.wikipedia.org/wiki/High-pass_filter(这是 Apple 代码的基础)。

      Wiki 中也有一些伪代码。但是将数学转换为代码相当简单。

      【讨论】:

        【解决方案5】:

        IMO,作为您的第一次尝试设计卡尔曼滤波器过于复杂,这可能是一个相当简单的问题。我会从一个简单的 FIR 滤波器开始,并且只有在/如果你已经测试过并且有合理的把握发现它不能提供你想要的东西时才尝试更复杂的东西。然而,我的猜测是,它将能够完成您需要的一切,并且更轻松、更有效地完成。

        【讨论】:

        • 我目前正在探索不同的过滤机制。与上述公认的答案相比,FIR 滤波器的优势是什么?
        • @Nazerke:看起来接受的答案 is 是一个(非常简单的)FIR 滤波器。过滤器中的更多极点将使您能够更好地控制过滤器滚降的速度,尤其是能够更快地滚降(如果您愿意的话)。
        • @JerryCoffin 接受的答案是一个简单的 IIR,也是一个非常简单的 KF。
        猜你喜欢
        • 2021-06-16
        • 2016-09-09
        • 2013-08-16
        • 2011-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-09
        • 2016-09-07
        相关资源
        最近更新 更多