24

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

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

4

5 回答 5

26

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];
于 2009-11-15T05:00:56.783 回答
12

这是 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]);
}
于 2011-11-30T09:20:28.900 回答
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;
}
于 2012-05-25T02:57:22.633 回答
1

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

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

Wiki 中也有一些伪代码。但是数学很容易翻译成代码。

于 2009-10-28T17:52:44.673 回答
0

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

于 2009-10-28T17:56:00.893 回答