Android 滤波加速度计数据噪声

Android 滤波加速度计数据噪声,android,accelerometer,Android,Accelerometer,如何过滤Android中加速度计数据的噪声?我想为我的样本数据创建一个高通滤波器,这样我就可以消除低频成分,专注于高频成分。我已经读到Kalman filter可能是最好的选择,但是我如何在我的应用程序中集成或使用这种方法呢?我的应用程序主要是用Android Java编写的?或者一开始就可以做到吗?还是通过安卓NDK?这是否有可能实时完成 任何想法都将不胜感激。谢谢大家! 我似乎记得这是在苹果iPhone的示例代码中完成的。让我们看看 在谷歌上查找AccelerometerFilter.h/.

如何过滤Android中加速度计数据的噪声?我想为我的样本数据创建一个高通滤波器,这样我就可以消除低频成分,专注于高频成分。我已经读到Kalman filter可能是最好的选择,但是我如何在我的应用程序中集成或使用这种方法呢?我的应用程序主要是用Android Java编写的?或者一开始就可以做到吗?还是通过安卓NDK?这是否有可能实时完成


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

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

在谷歌上查找AccelerometerFilter.h/.m(或抓取苹果的AccelerometerGraph示例)和以下链接:(这就是苹果代码的基础)


Wiki中也有一些伪代码。但是数学很容易转化为代码。

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

来自苹果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]; //坡道速度-使用此值播放,直到满意为止 常量浮点kFilteringFactor=0.1f; //最后结果存储-将定义保持在此函数之外,例如在包装对象中 浮动加速度[3]; //加速度.x、.y、.z是来自传感器的输入 //结果.x、.y、.z是过滤后的结果 //消除重力的高通滤波器 加速度[0]=加速度.x*kFilteringFactor+加速度[0]*(1.0f-kFilteringFactor); 加速度[1]=加速度.y*kFilteringFactor+加速度[1]*(1.0f-kFilteringFactor); 加速度[2]=加速度.z*kFilteringFactor+加速度[2]*(1.0f-kFilteringFactor); 结果.x=加速度.x-加速度[0]; 结果.y=加速度.y-加速度[1]; 结果.z=加速度.z-加速度[2];
以下是Android的代码,改编自apple自适应高通滤波器示例。只需插入此插件并实现OnFilteredAccelerMeterChanged()


对于那些想知道norm()和climp()方法在rbgrn的答案中做了什么的人,您可以在这里看到它们:

双范数(双x,双y,双z)
{
返回Math.sqrt(x*x+y*y+z*z);
}
双夹钳(双v、双最小、双最大)
{
如果(v>最大值)
返回最大值;
否则如果(v
norm()和clamp()应该做什么?我想说,“norm”指的是计算给定向量的范数(sqrt([0]^2+[1]^2'[2]^2]),clamp是一个具有上下边界的限制函数(在这种情况下,第一个参数限制在0.0f和1.0f之间)。另外,非常感谢这个自适应的例子,我想我要做的是某种形式的自适应。我如何确定这些变量的值?(RC、dt、cutOffFreq等等)我目前正在探索不同的过滤机制。与上述公认的答案相比,FIR滤波器有哪些优点?@Nazerke:看来公认的答案是(非常简单的)FIR滤波器。过滤器中的极点越多,你就可以更好地控制过滤器的滚动速度,尤其是更快的滚动速度(如果你愿意)。@JerryCoffin公认的答案是一个简单的IIR,也是一个非常简单的KF。我不确定我是否了解这里发生的事情。。。如果加速度.x是常数(理论上可能发生这种情况),则结果.x=0;accel[0]看起来像已过滤的输出;不确定结果是什么。
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]);
}
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;
}