Android 过滤加速度计数据噪声

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1638864/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:23:37  来源:igfitidea点击:

Filtering accelerometer data noise

androidaccelerometer

提问by Faiz

How do I filter noise of the accelerometer data in Android? I would like to create a high-pass filter for my sample data so that I could eliminate low frequency components and focus on the high frequency components. I have read that Kalman filter might be the best candidate for this, but how do I integrate or use this method in my application which will mostly written in Android Java? or can it be done in the first place? or through Android NDK? Is there by any chance that this can be done in real-time?

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

Any idea will be much appreciated. Thank you!

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

回答by Till

The samples from Apple's SDK actually implement the filtering in an even simpler way which is by using ramping:

来自 Apple 的 SDK 的示例实际上以更简单的方式实现了过滤,即使用斜坡:

//ramp-speed - play with this value until satisfied
const float kFilteringFactor = 0.1f;

//last result storage - keep definition outside of this function, eg. in wrapping object
float accel[3]; 

//acceleration.x,.y,.z is the input from the sensor

//result.x,.y,.z is the filtered result

//high-pass filter to eliminate gravity
accel[0] = acceleration.x * kFilteringFactor + accel[0] * (1.0f - kFilteringFactor);
accel[1] = acceleration.y * kFilteringFactor + accel[1] * (1.0f - kFilteringFactor);
accel[2] = acceleration.z * kFilteringFactor + accel[2] * (1.0f - kFilteringFactor);
result.x = acceleration.x - accel[0];
result.y = acceleration.y - accel[1];
result.z = acceleration.z - accel[2];

回答by rbgrn

Here's the code for Android, adapted from the apple adaptive high pass filter example. Just plug this in and implement onFilteredAccelerometerChanged()

这是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]);
}

回答by Shumoapp

For those wondering what norm() and clamp() methods do in the answer from rbgrn, you can see them here: http://developer.apple.com/library/IOS/samplecode/AccelerometerGraph/Listings/AccelerometerGraph_AccelerometerFilter_m.html

对于那些想知道在 rbgrn 的答案中 norm() 和clamp() 方法做了什么的人,你可以在这里看到它们: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;
}

回答by inked

I seem to remember this being done in Apple's sample code for the iPhone. Let's see...

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

Look for AccelerometerFilter.h / .m on Google (or grab Apple's AccelerometerGraph sample) and this link: http://en.wikipedia.org/wiki/High-pass_filter(that's what Apple's code is based on).

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

There is some pseudo-code in the Wiki, too. But the math is fairly simple to translate to code.

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

回答by Jerry Coffin

IMO, designing a Kalman filter as your first attempt is over-complicating what's probably a fairly simple problem. I'd start with a simple FIR filter, and only try something more complex when/if you've tested that and found with reasonable certainty that it can't provide what you want. My guess, however, is that it will be able to do everything you need, and do it much more easily and efficiently.

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