こんにちは!テクニカルコンサルティンググループの monma です。
iBeacon の記事の続きを書こうと思っていたのですが、肝心の umako 編集長が産休入りしてしまって、当面捕まる心配がなくなってしまいました!なので今回は、全然関係ないのですが、スマートフォン (iPhone) の加速度センサを利用して、『歩き方判定アプリ』を全二回で作ってみようと思います。
最近 IoT が流行っている中で、身近なスマートフォンに搭載されている加速度センサでも、ある程度の認識機能を作成できるという例として、ご紹介させていただきます。また、加速度センサにとどまらず、このような認識機能を作る際には、同じような手法が使用できますので、そちらの面でも参考になれば幸いです。
(完全に趣味ですが。。。)
取り急ぎ思いついた判定方法としては、
- ベルトにスマートフォンを挟む
- キャリブレーションする
- 前方に 10 歩、まっすぐ歩く
の 3 ステップで判定できるようにしたいと思います。
ベルトにスマートフォンを挟むイメージは以下の様な感じです。
やらなければいけないことをまとめてみました。以下のとおりに進めていきたいと思います。
- 加速度センサの値を記録するアプリを作成する
- このアプリはどの方向で使っても良いようにキャリブレーション機能※1を搭載する
- 直立キャリブレーション
- お辞儀キャリブレーション
- ローパスフィルタ※2をかける
- 歩き方を識別できるラベル※3を付けられるように、テキストボックスを設ける。
- Start ボタンと Stop ボタンがあり、Start から Stop までの加速度をファイルに保存できる
- このアプリはどの方向で使っても良いようにキャリブレーション機能※1を搭載する
- いくつか認識したい歩き方ラベルを作成する。
- 歩き方ラベルごとの歩き方で記録を行う。記録方法は上記で記載した 3 ステップで。
- 加速度センサの値をラベルと突き合わせて観察し、パラメータ(特徴量)を作成する
- ラベルとパラメータを機械学習※4にかける
- 5 で作成したロジックを 1 のアプリに組み込み、判定アプリを作る
こういった認識アルゴリズムを作る場合には、入力する値は違えど、大体上記のような手順で作成することになるかと思います。(時系列的に認識する方法もありますが。。。)
今回は、3 まで実施して、4 のパラメータの作成以降は次回のブログで紹介したいと思います。
※1 キャリブレーション機能:得られた値を補正して、なるべく一律な環境に近づける機能。
※2 ローパスフィルタ:低い周波数のものしか通さないフィルタ。
※3 ラベル:得られた値にラベルをつけることで、識別を行う。機械学習に使用できます。
※4 機械学習:値とラベルを与えることによって、ルールを導き出し、分類アルゴリズムを作成する手法
スマートフォンの加速度センサとは
そもそも『加速度センサとは』的な話は色々なところで行われているので、詳しい説明は割愛しますが、ざっくりと以下のような軸になっていて、それぞれの加速度が計測できます。重力も計測できますので、スマートフォンを立てた状態だと Y 軸の下方向の加速度が計測できます。その場合は、Y 軸方向のマイナス方向に 1G の加速度がかかっていますので、y = -1.0 となります。
加速度センサの値を記録するアプリを作成する
まずは、この加速度センサから出力される値を記録しなくては観察することも出来ません。ただし、キャリブレーション機能も入れたいので、加速度センサから出力された値ではなく、キャリブレーション後の値を記録していきたいと思います。(加速度は 1 秒間に 100 回取得します)
キャリブレーションする理由としては、ベルトへの挟み方、体型などに個人差があるので、分析する軸が異なってしまいますので、その方向を補正するためになります。
分析する軸を地面に合わせてキャリブレーションしたほうが分析しやすいので、そのためのキャリブレーションアルゴリズムを実装していきます。以下のようにキャリブレーションを行うことを想定しています。
直立キャリブレーション機能
直立静止した状態で 3 秒間加速度を計測し、その平均値から重力方向を測定します。この重力を Y 軸方向 -1.0 に合わせることを考えます。
X 軸, Y 軸 の回転
まず X, Y 軸のみを考えると、以下のように一番大きい力がかかっている方向を Y 軸 -1.0 の方向に回転させる必要があります。
まず、重力方向と X 軸との角度を算出します。上図の θ 部分になります。この θ を算出するためには逆三角関数の atan (アークタンジェント)を使います。※ x と y の長さから角度(ラジアン)を算出することが出来ます。
θ = atan (y / x)
さらに、θ だけでは回転量が足りません。1π ラジアンは、180° ですので、残り 90° 分を回転させるためには、π / 2 を足した値になります。回転させる角度 α を求めるためには、以下のような公式になります。
ただし、右回転させるためには回転させるラジアンを負の数にする必要がありますので、
α = -1.0 * atan(y / x) - π / 2
となります。
上記が X 軸が正の数の場合の回転角度になります。 X 軸がマイナスだった場合、以下のように左回転させる必要があります。
x がマイナスの場合、atan (y / x) は、負の数で返却されます。同じくさらに 90° 分回転させる必要がありますので、π / 2 を加算することには変わりはありません。
つまり、
α = -1.0 * atan(y / x) + π / 2
で回転角度を導き出すことが出来ます。
あとは詳しい説明は省きますが、Y 軸方向の正負の値に関係なく、
x > 0 の場合、
α = -1.0 * atan(y / x) - π / 2
x < 0 の場合、
α = -1.0 * atan(y / x) + π / 2
となります。
実際に x, y についてだけ、キャリブレーションを行ってみます。
例えば z = 0 の場合、x = 0.73, y = 0.683448 とした時に、キャリブレーション結果が大体 x’ = 0, y’ = -1.0 になることを確認してみます。
α = -0.818321326
上記は回転角度の係数になりますので、実際に値を算出するときには、以下の公式を使用します。この公式は 2 次元の回転行列を解いた公式になります。回転後の座標を x’, y’ とします。
x’ = x * cos(α) - y * sin(α) y’ = x * sin(α) - y * cos(α)
以下のように大体 x’ = 0, y’ = -1.0 となりました。(ただし z が 0 以外の場合は、以下の解は出ません)
x’ = 0.0 y’ = -1.000000584
Z 軸, Y 軸の回転
次に z, y に対しての回転を x, y と同じように行っていきます。x と y の時と全く同じです。唯一違うのは、上記で X 軸, Y 軸について既に回転させている y’ を元に係数を決める点が異なっています。
z > 0 の場合、
β = -1.0 * atan(y' / z) - π / 2
z < 0 の場合、
β = -1.0 * atan(y’ / z) + π / 2
あとは以下のように計算して検算してみます。
z’ = z * cos(β) - y * sin(β) y’ = z * sin(β) - y * cos(β)
これで、直立状態の重力方向を x = 0, y = -1.0, z = 0 という座標へ回転させることができました。
この回転の係数 α と β で常に加速度のデータを回転させてやれば、iPhone を横に装着した場合でも斜めに装着した場合でも重力方向が必ず Y 軸になります。
お辞儀キャリブレーション
ただし、このままでは重力方向へのキャリブレーションを行っただけで、前方(進む方向)がどちらかというキャリブレーションはできていません。スマートフォンに前方がどちらかということを教えてあげる必要があります。
そこでお辞儀した状態で 2 秒間静止、キャリブレーションを行うことで、x 方向と z 方向を確定します。前節で行えていない x, z の回転を行います。もちろん直立キャリブレーションした結果の係数をかけた結果で x, y, z を算出した値で計算を行います。
お辞儀を行うと、以下のイラストのように自然と進行方向へ重力の力がかかります。(理論的には。。。)
そして、z 軸を前後方向、x 軸を左右方向とした場合に、真上から見ると、
こんな感じの力がかかるはずです。y = -1 でやってきた公式をそのまま使って、z = -1, x = 0 方向へそのまま回転させます。
x > 0 の場合、
γ = -1.0 * atan(z / x) - π / 2
x < 0 の場合、
γ = -1.0 * atan(z / x) + π / 2
これを α, β に続く第三の係数 γ とします。
ローパスフィルタをかける
上記に加えて、キャリブレーションされた加速度の値にローパスフィルタをかけたものも用意します。デジタルフィルタにはなるべく綺麗にローパスフィルタをかけたいので、 FIR フィルタ(有限インパルス応答フィルタ)を使用します。
ローパスフィルタをかける理由としては、細かい振動の影響よりは、大きな加速度の動きのほうが歩き方の影響を見やすいのでは?と考えたからです。
FIR フィルタは一般的なデジタルフィルタと呼ばれるものですが、使用するためには設計が必要です。設計は、デジタルフィルタ設計用の Web ページも存在しますし、MATLAB でも行えます。実際に設計に使用した内容は以下になります。
- Sampling freq. : 1000 Hz
- 加速度センサの値を大体 1000 サンプルと見積もりました。
- Cutoff freq.(Low) : 40 Hz
- 1000 Hz 中、40 Hz 以上の振動数を持った信号を通さないようにします。
- Window Type. : Hamming
- 係数を求めるための窓関数を設定します。窓関数毎に特性がありますが、今回は一般的なハミング窓を使用しました。
- taps. : 97
- フィルタ係数の次数です。多いとよりフィルタの精度が高くなりますが、計算量が増えます。
以下の様な周波数特性が得られます。40 Hz くらいの周期の信号しか通さないフィルタとなります。
あとは係数が 97 個得られますので、加速度の信号に対して以下の公式を使うと、ローパスフィルタ後の信号の値が取得できます。(a0〜a96 までが 97 個の係数)
Y[n] = a0*X[n] + a1*X[n-1] + ... + a96*X[n-96]
ラベルの付与とファイル保存
今回、加速度を記録するために以下のようなアプリを作成しました。
- 加速度センサの値と、ジャイロセンサの値をリアルタイムで表示する部分。(ジャイロは使用予定はありません)
- 直立キャリブレーションを実行するボタン
- お辞儀キャリブレーションを実行するボタン
- ファイル名へ文字列を追加するためのテキストボックス
- 加速度の値の記録開始
このようになっています。
4. の文字列は歩き方のラベルをつけるために実装しています。設定したラベルは 5. のボタンをタップした時に記録されるファイル名に追加されます。
以下のように、x, y, z 軸のそれぞれのキャリブレーション後の値とローパスフィルタ後の値をファイルに保存します。保存先は、アプリのドキュメントディレクトリになります。
歩き方のラベルを作成する
さて、認識させたい歩き方を定義していきます。(実際に認識できるかどうかはわかりません)
- 普通
- 姿勢を正しく目線は 10 m くらい先の地面
- がに股
- 大きながに股で偉そうに歩く。ペタペタ歩くイメージ。
- すり足
- 地面からあまり足をあげないで歩く
- のけぞり
- 後ろにのけぞって歩く。重心を後ろに置くイメージ。
- 内股
- 足先を内側に向けて歩く。かかとをあまり付けないイメージ。
- 左右にふらふら
- 左右にふらふらと歩く。
- 猫背
- 姿勢を悪くして歩く。うつむく。
上記の 7 パターンを認識させたいと思います。各種の歩き方を実際にやってみます。
歩き方の記録
データの取得ですが、本当は『複数人で行う(大人数)』『複数の環境で行う』『何回も行う』という 3 つの条件を満たすことが望ましいのですが、今回はとりあえず作ってみるスタンスですので、自分一人で、環境を統一し、8 回ほどの試行でデータ取得を行いました。
データ取得環境: 自宅(フローリング)
履物: 裸足
データ取得手順:
- 歩き方ラベルを入力
- 直立した状態で Calibration 1 ボタンをタップし、3 秒待つ
- お辞儀した状態で Calibration 2 ボタンをタップし、2 秒待つ
- 再度直立して、Start ボタンをタップした後に、歩き方に従って 10 歩前進する。
- 10 歩歩いたら静止して、Stop ボタンをタップする。
4-5 をあと 7 回繰り返し、合計 8 回になったところで、次の歩き方ラベルへ移行することにしました。
次回は…
次回はいよいよパラメータを作成していきます。パラメータは、出力された値とラベルを観察しながら、どのようなパラメータが適しているかを観察しながら作成していこうと思います。
また、パラメータ出力をする際に、毎回 iPhone で計算させていては大変なので、Mac で簡単にパラメータ出力できるアプリも作っていきます。