tomoima525's blog

Androidとか技術とかその他気になったことを書いているブログ。世界の秘密はカレーの中にある!サンフランシスコから発信中。

Androidの加速度センサー(Accelerometer)から重力の影響を省いて値を取得する(ローパスフィルタでノイズも除去)

Android端末では加速度センサーで加速度値(m/s^2)を取得できます。

ところが精度が良すぎるのか、ものすごい値がぶれます。また、重力の値までとれちゃいます。

例えば加速度をベクトル値にしたい場合、値は頻繁にぶれるんでこのままではとても使い物になりません。

 

そこで、ハイパスフィルタとローパスフィルタを使って、Android端末自体の加速度データを取得し、かつまろやかにするコードを書きました。

 

 

実装の仕組み

センサーから取得した値を2つのフィルタに通します。

ハイパスフィルター:

ある周波数以下の低周波数を除去するフィルタです。ここでは、重力加速度の影響を除去するために実装します。

 

ローパスフィルター:

時系列データの細かいギザギザを平滑化します。

ここでは端末の加速度データを平滑化するために実装します。

手法としては加重移動平均、指数移動平均などがありますが、Android Developerのチュートリアルhttp://developer.android.com/guide/topics/sensors/sensors_motion.html#sensors-motion-accel)で使用しているのは、指数移動平均です。

 

ローパスフィルタの式

S[t]= α*Y[t-1]+(1-α)*S[t-1]

 

Sは取得したセンサー値を処理した値、Yはセンサーで取得した値、αは平滑化係数と呼ばれ、0<α<1の値を取ります。

一般的にαが大きくなると、センサーで実際に取得したデータの重み付け(影響度)が大きくなるので、よりギザギザになります。なるべく平滑化したい場合はαを小さくするのがよいようです。

 

コード

ポイント:

・加速度の差分からベクトル値を取得するサンプルコードです。

・フィルタではぶけないぶれをさらに省くため、ある閾値以上のベクトル値を取得、カウントします。

・端末を上下に揺らした場合、上、下で2回分の値が取得されます。一揺れで一回分の加速度データを取得するためにcountedフラグをつけています。

・ローパスフィルタの仕組み上一回目は初期の値(つまり重力の値も入ったデータ)が入ってしまうので、それをはぶくためにnoiseflgを設定しています。

Andorid code snippet for acquiring an accelerome ...

 

ちなみに、このアプリで使用しているアルゴリズムです…

https://play.google.com/store/apps/details?id=com.tomo.drawgraph&hl=ja