【SensorTile kit】FP-AI-SENSING1をリバースエンジニアリング

本記事では、FP-AI-SENSING1のソースコードを覗いて、プログラム的にどういう作りになっているのか解析していきます。

本記事では、コードの詳細は対象とせず、プログラムの構造に絞って記載します。プログラムの構造が分かれば、動作イメージはつかめますし、詳細を知りたい時は該当箇所がすぐわかるので、直接見に行って確かめれば良いのです。

プログラムの構造とは地図のようなもので、本記事が地図として使えるようになれば良いと思っています。

 

1.FP-AI-SENSING1の構造の解析

まずは全体の構造を解析し、俯瞰できるようにします。

1-1.ファイル単位の関連

まずはファイル単位の関係性を整理して、全体の構造を理解します。

FP-AI-SENSING1のファイル構成

 

sensor_sevice.c

アプリケーションのインタフェースの役割を担います。Bluetooth通信を行って、スマホアプリからの各デモ機能のスタート/ストップ要求の実行と、デモ機能の処理結果の送信を行います。

Bluetooth通信のサンプルプログラムとしてもとても有用そうです。

 

ちなみに、別のインタフェースとしてcli_commands.cにコマンドライン機能が実装されていますが、今回は省略しています。

 

main.c

アプリケーションのロジック部分はほとんどここに詰め込まれている感じで、約2,500行ほどあります。フラットな作りであまり好みではないですが、1つ1つの関数はわかりやすく書かれているので、読みやすいです。サンプルアプリケーションとしては、こういう書き方の方が正解なのかもしれません。

このファイルが主な解析対象になります。

 

<各モジュール.c>

各デモ機能が利用する、モジュール化された機能ブロック群です。必要に応じて見ていきたいと思います。

 

1-2.main.cの構造

main.cの構造を図にしました。(図が煩雑になるのを避けるため、Sempahore等の一部のものは省略しています。)

FP-AI-SENSING1のmain.cの構造

この図の中の淡い水色の部分(スレッドorタイマ)に着目すると動きが見えてきます。

 

TimerXXHandle:startProcessing

FreeRTOSのタイマです。TimerXXHandleはタイマのハンドル名で、startProcessingが実際に実行される関数です。デモ機能毎にタイマが存在し、XXに名前が入ります。

  • TimerEnvHandle
  • TimerBatHandle
  • TimerMotionHandle
  • TimerAudioLevHandle
  • TimerActivityHandle
  • TimerSdRecordingHandle

このタイマが各デモ機能の実行フラグを定期的にONすることにより、各デモ機能が定期的に実行されます。

 

THREAD_1:ProcessThread

このスレッドは各デモ機能のフラグをチェックし、ONされているものがあったら実行します。実行結果はMailQueueに送信します。

各デモ機能の詳細はこのProcessThreadを追えばわかります。各デモ機能を実装している関数と、さらにその中で利用するモジュールを表にまとめました。

 

デモ 関数 モジュール
Environmental SendEnvironmentalData()  
Plot Data

SendAudioLevelData()

SendMotionData()

 
Activity Recognition ComputeMotionAR() har_processing.c
Acc Event MEMSCallback() HWAdvanceFeature.c
Audio Classification RunASC() asc_processing.c
AI Data Log   DataLogManager.c
Rssi & Battery SendBatteryInfoData()  

 

A.I.を利用している”Activity Recognition”については、後ほどさらにコードを追いかけて詳細を解析します。

 

Thread_2:HostThread

MailQueueからデモ機能の実行結果を受信し、sensor_service.cに実行結果のデータ送信を依頼します。

 

2.Activity Recognitionの解析

A.I.デモ機能は”Activity Recognition”と”Audio Classification”の2つがあります。前者は加速度センサーを使っていて、後者は音声データを使っています。私は加速度センサーを使ったA.I.アプリケーションを作りたいと考えているので、前者のみ解析を行います。

さらに、”Activity Recognition”にはアルゴリズムが3つありますが、使い方を覚える目的なら1つだけで十分なので、デフォルトのGMPを対象とします。

 

2-1.Activity Recognitionの動作イメージ

HARの動作イメージ

 

”Activity Recognition”の推論だけに着目して抜き出したのが、上の図です。

 

TimerActivityHandleは32ms間隔で動作します。つまり、”Activity Recognition”のプロセスの実行間隔もそのまま32ms間隔となります。32ms間隔でニューラルネットワークの入力バッファにデータが追加されます。マニュアルと実装が異なっているようで、かなり混乱しました。

 

For HAR_GMP, 24×3 data matrix (24 x-axis, 24 y-axis, 24 z-axis) is given as input every 0.62 ms to the neural network.

引用:FP-AI-SENSING1_en.DM00568147.pdf

 

har_Processing.c:HAR_Run()がこのデモ機能の中核です。32ms毎に追加された入力データのバッファがフルサイズの24個たまったら、A.I.推論を実行します。なお、バッファは24個の半分の12個がオーバーラップする作りになっているので、実際には12回に1回、A.I.推論が行われます。

 

2-2.Activity Recognitionの前処理

推論の前には、har_Preprocessing.c:gravity_supress_rotate()により、入力データの前処理を行います。入力データの前処理として2つ行っています。

 

  • 加速度センサーの値から重力成分を分離
  • SensorTileの傾きを無視

 

加速度センサーは常に重力の影響を受けており、そのままだと純粋な加速度がわからず扱いづらいので、センサーの値から重力成分を分離します。分離は、IIRフィルタを使って低周波成分(1Hz)を重力成分として抜き出します。この処理はhar_Preprocessing.c:dynamic_acceleration()に記述されています。

 

次に、”Activity Recognition”というアプリケーションの特性上、SensorTileはどういう持ち運び方をされるかわからないので、SensorTileの傾きは無視したくなります。先ほど重力成分を抜き出したので、ここからSensorTileがどの程度傾いているのかわかるので、傾きを補正します。補正にはロドリゲスの回転公式を使っています。この処理は、har_Preprocessing.c:gravity_suppress_rotate()に記述されています。

 

2-3.Activity Recognitionの推論処理

ニューラルネットワークの構造としては、畳み込みネットワークを使っているようです。推論モデルは自前で作ろうと考えているので、詳細は調べませんでした。

A.I.推論アプリケーションの作り方は下記を参考にしてください。

 

X-CUBE-AIを使った推論プログラムの作り方をわかりやすく解説

 

2-4.Activity Recognitionの後処理

推論の後のhar_Postprocessing.c:har_Postprocess()は、推論結果から最も適合度の高いクラス(立つ、歩く、走る、自転車をこぐ、車を運転する)を返します。

 

3.おわりに

FP-AI-SENSING1をリバースエンジニアリングしたことで、SensorTileを使った推論アプリケーションの作り方を理解しました。

ただSensorTile本体にユーザインタフェースが何もないので、別途ユーザインタフェースを持ったBluetoothでSensorTileをコントロールするアプリケーションが必要になります。ST社がiOSアプリ/Androidアプリ/Pythonのライブラリを用意しているので、これのどれかを使うことになるでしょう。しばらくは調査の日々が続きそうです。

 

続き:まだ