web-dev-qa-db-ja.com

加速度計のデータノイズのフィルタリング

Androidで加速度計データのノイズをフィルタリングするにはどうすればよいですか?サンプルデータ用のハイパスフィルターを作成して、低周波数成分を除去し、高周波数成分に焦点を合わせたいと思います。カルマンフィルターがこれに最適な候補である可能性があることを読みましたが、ほとんどがAndroid Javaで記述されるアプリケーションでこのメソッドを統合または使用するにはどうすればよいですか?またはで実行できますか?そもそも?またはAndroid NDK?これがリアルタイムで実行できる可能性はありますか?

どんなアイデアでも大歓迎です。ありがとうございました!

23
Faiz

AppleのSDKのサンプルは、実際には、ランプを使用するというさらに簡単な方法でフィルタリングを実装しています。

 // ramp-speed-満足するまでこの値で再生します
 const float kFilteringFactor = 0.1f; 
 
 //最後の結果ストレージ-定義をこれ以外に保持します機能、例えば。オブジェクトのラッピング
 float accel [3]; 
 
 // Acceleration.x、.y、.zはセンサーからの入力です
 
 // result.x、.y、.zはフィルタリングされた結果
 
 //重力を排除するためのハイパスフィルター
 accel [0] = Acceloration.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.0 f-kFilteringFactor); 
 result.x = acceleration.x-accel [0]; 
 result.y = acceleration.y-accel [1]; 
 result.z = Acceleration.z-accel [2]; 
26
Till

これは、Appleアダプティブハイパスフィルターの例から適応した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]);
}
12
rbgrn

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;
}
3
Shumoapp

これがAppleのiPhone用サンプルコードで行われたことを覚えているようです。どれどれ...

GoogleでAccelerometerFilter.h/.mを探します(またはAppleのAccelerometerGraphサンプルを入手します)。次のリンク:http://en.wikipedia.org/wiki/High-pass_filter(これがAppleのコードの基になっています)。

Wikiにもいくつかの擬似コードがあります。しかし、数学はコードに変換するのはかなり簡単です。

1
inked

IMO、最初の試みとしてカルマンフィルターを設計することは、おそらくかなり単純な問題を複雑にしすぎています。私は単純なFIRフィルターから始め、それをテストして、それがあなたが望むものを提供できないことが合理的な確実性で見つかった場合にのみ、より複雑なものを試します。しかし、私の推測では、必要なすべてを実行でき、はるかに簡単かつ効率的に実行できるようになります。

0
Jerry Coffin