过滤加速度计数据噪声

发布于 2024-08-09 09:37:44 字数 188 浏览 3 评论 0原文

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

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

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?

Any idea will be much appreciated. Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

雨轻弹 2024-08-16 09:37:44

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];

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

//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];
初懵 2024-08-16 09:37:44

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

Here's the code for Android, adapted from the apple adaptive high pass filter example. Just plug this in and implement 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]);
}
记忆で 2024-08-16 09:37:44

对于那些想知道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;
}

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

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;
}
笨笨の傻瓜 2024-08-16 09:37:44

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

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

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

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

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).

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

墨洒年华 2024-08-16 09:37:44

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文