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