はじめに
三菱総研DCSのAI・IoTエンジニアの桃井です。
BLEビーコンを用いた社員の位置測位システムについて、前回に引き続きご紹介したいと思います。第2回ではAWSを用いたバックエンド側の処理やシステムの運用について説明します。
目次
AWSの構成
全体のシステム構成を再掲します。
測定値の取得
フロア内に設置されたATOM LiteとBLEビーコンとのRSSIはAWSに送信され、クラウド上で測位処理を行います。データはゲートウェイデバイスからIoT Coreのトピックに対してMQTTを用いてパブリッシュします。その後、受け取ったデータは一旦SQSに格納します。
測位処理の実行
SQSからRSSIの測定値を取り出し、それと事前に測った環境値(フィンガープリント)をもとにLambdaで位置座標の測位をします。アルゴリズムとしては単純で、各区画における環境値と測定値とのユークリッド距離を算出し、それが最小となるエリアを自己位置とします。
測定値の取得にSQSを介しているのは、将来的にゲートウェイデバイスが増えた際、同一人物の測定値が複数のデバイスから観測されたときにデータの待ち合わせをする必要があるためです。IoT Coreから直接Lambdaを呼び出す形式だとそれができません。
また、この理由からLambdaの呼び出しはEventBridgeを用いてスケジューリングしています。この際、位置測位の実行は数秒単位で行いたいですが、EventBridgeのcron式は秒単位での起動はできません。そのため、"数秒ごとに位置測位の関数を呼び出す関数"を用意し、EventBridgeからはそれを起動するという方法を取っています。
データ蓄積
測位した位置情報や、事前測定した環境値はElasticsearchに格納します。また、ゲートウェイデバイスのリソース情報(CPU使用率など)も収集しており、そのデータも格納しています。Elasticsearchに付随する可視化サービスであるKibanaにはアラート機能があるため、今回は実装していませんが、デバイスの死活監視も行うことができます。
Webアプリのホスティング
社員を検索し、位置をフロアマップ上に描画するWebアプリを作成しました(画面は第1回の記事を参照)。開発にはVue+Typescriptを採用しました。アプリはS3に静的ホスティングし、CloudFrontを介してアクセスするようにします。社員位置の描画で必要となる、BLEビーコンのUUIDと社員情報とを対応付ける情報やフロアマップの画像については、社内情報となるため自社サーバ内に置いてAPIを通じて取得します。今回は簡単のため、NodeREDのHTTPノードを使ってAPIを作りました。
測位精度とその改善
測定値と正解座標のデータをもとに測位精度を計測したところ、誤差の平均は約5メートル程度であり、測位対象が静止した状態でも大きくぶれてしまう状態でした。原因として、障害物による電波の反射や、複数の電波が重なり合って弱まる/強まる干渉によりRSSIの計測結果の誤差が大きくなってしまったことが考えられます。
この対策として、測定したRSSIの系列データに対してノイズ軽減のための処理を適用することを試みました。この検証では社員の位置を計測することから、RSSIが極端に変化することはない(=瞬時に大きな距離を移動することはない)という仮定のもと、カルマンフィルタを適用しました。その結果、誤差の平均は約3メートルに抑えることができました。
AWS Greengrassを用いたエッジデバイスの運用
今回のようなシステム構成では、規模の拡大につれ複数のエッジデバイスを運用することによる手間や課題が生じることが想定されます。その解決のための手段の一つとして、デバイスソフトウェアの構築、デプロイ、および管理を支援するサービスであるAWS Greengrassを利用しました。
NodeREDのフローの遠隔更新
今回はGreengrassを使ってエッジ側で動作するNodeREDのフローの更新を遠隔で実行できるようにしました。Greengrassを使うことにより、デバイスに直接接続せずともセキュアに通信ができる他、複数のデバイスに対して同じデプロイを同時に実行することができるという効率面での利点もあります。
図3. デバイスの更新イメージ
Greengrassにはv1、v2の2つのバージョンがありますが、最新のv2を使用しました。
前準備
公式のインストール手順に従った場合、Greengrassの実行用のユーザとしてggc_userが作られていると思います。NodeREDのリロードやファイルの配置を行うには、このユーザにsudo権限を付ける必要があります。
※簡単のため、この例ではsudoで全コマンドを実行できるようにしています
/etc/sudoers
# User privilege specification
root ALL=(ALL:ALL) ALL
ggc_user ALL=(ALL:ALL) ALL # 追記
エッジデバイスに転送するファイルはS3の任意のバケットに置いておく必要があります。
・flows_raspberrypi.json:更新するフローのjsonファイル
・update_flow.sh:ファイルをNodeREDのディレクトリに移動してフローをリロードする処理を記述したスクリプト
update_flow.sh
cp -f $1/flows_raspberrypi.json /home/<ユーザ名>/.node-red/
node-red-reload
Greengrassの実行ロール(インストール手順に従えばGreengrassV2TokenExchangeRoleになります)に、S3バケットへのオブジェクト取得権限(s3:GetObject)を与えます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::<バケット名>/*"
}
]
}
デプロイの実行
以下のレシピを適用したコンポーネントをデプロイすることで、S3上のファイルをデバイスに転送し、その後、指定のコマンドを実行させることができます。
RecipeFormatVersion: "2020-01-25" ComponentName: "nodered" ComponentVersion: "1.0.0" ComponentType: "aws.greengrass.generic" ComponentDescription: "component for modify nodered flow." ComponentPublisher: "publisher name" Manifests: - Platform: os: "linux" Name: "Linux" Lifecycle: Run: "bash {artifacts:path}/update_flow.sh {artifacts:path}" Artifacts: - Uri: "s3://<バケット名>/flows_raspberrypi.json" Algorithm: "SHA-256" Unarchive: "NONE" Permission: Read: "ALL" Execute: "ALL" - Uri: "s3://<バケット名>/update_flow.sh" Algorithm: "SHA-256" Unarchive: "NONE" Permission: Read: "ALL" Execute: "ALL" Lifecycle: {}
まとめ
今回は位置測位のシステムのバックエンドとなるAWSの構成について説明しました。本検証で用いた手法では、目的としていた“社員がどの席に座っているか”の把握ができる精度には至りませんでしたが、大まかにどのエリアにいるかの把握であれば十分可能であることが分かりました。一方で、測位アルゴリズムとしてフィンガープリント方式を採用しましたが、この手法は事前計測に手間がかかることや、計測後に電波に影響があるような物が移動した際に再計測が必要となることが課題です。大まかな測位であれば近接性方式のような手軽な手法でも可能なため、求める精度や運用の手間を考慮して、最適な方法を選択することが必要になるでしょう。
※SORACOMは、株式会社ソラコムの登録商標または商標です。