固定Beaconを使って現在位置を測位するアプリをDelphi/C++BuilderとBeaconFenceで作る

  • 2
    いいね
  • 0
    コメント

これは Delphi Advent Calendar 2016 17日目の記事です。

また、前回の記事 ビーコンの距離測定精度を上げるためのキャリブレーションを行うアプリをDelphiで作る の続きでもあります。

前回の内容のフォローアップ

前回の記事の投稿時点では Beacon の RSSI を取得するだけのカンタンなアプリを作るところまでを書いていましたが、これだけでは使い勝手がイマイチです。

そのため「RSSIの値から TxPower の最適値を自動で算出するアプリ」というものを作ってみました。このアプリのソースコードへのリポジトリを前回の記事に追記しています。実際のキャリブレーションではそちらをお使い頂くと良いでしょう。

BeaconFence でナビゲーションアプリを作る前に、ライセンスの話

Delphi/C++Builder/RAD Studio でBeaconFence を用いると、シンプルな位置測位アプリならばコードをほとんど書かずに実装できます。BeaconFenceを実際に用いる場合はエリアの広さやビーコンの個数によってライセンスが必要となるのですが、試用のために150m2(約12.24m四方)までの面積にビーコン3つを配置する場合は無償のPlutoライセンスが適用されます。

面積が150m2を超える場合やビーコンの個数が4つ以上のライセンスについては、面積やビーコンの個数ごとに適用されるライセンスを選びます。ただし RAD Server という製品には、BeaconFenceでビーコンの個数と面積無制限のライセンスが付帯していますので、内容によっては RAD Server のライセンスを購入する方が良いようです。

事前準備

予め行っておく作業は以下のとおりです。

  • エリアの縦横の長さを測る
  • エリアの見取り図を作る
  • 使用する Beacon の UUID, Major, Minor を確認しておく

これらは特別な作業は含みませんので説明を省略します。

位置測位を作るために必要なこと(BeaconFenceを使わない場合)

BeaconFenceの話を進める前に、めんどくさい話をあえて書きます。

三辺測量の知識が必要

平面(2次元)での位置測位のためには、3つの基準点からの距離が正確に分かっていることが必要です。

  • 1つの基準点からの距離 r1が分かっていると、その基準点から半径 r1 の円の円周上のどこかにいるはずです。この円を "円r1" と表記することにします。
  • 2つの基準点からの距離 r1 と r2 が分かっていると、"円r1 と 円r2" の円周が重なり合う交点のどこかにいるはずです。通常なら、この交点は2つ存在します。例外なのは "円r1 と 円r2" が1箇所で接している場合です。
  • 3つの基準点からの距離 r1, r2, r3 が分かっていると、3つの円の円周の交点にいるはずです。これは1箇所しか存在し得ません。

このように、3つの基準点からの距離が正確に分かっていれば位置が決まります。ここまでの話は中学生や高校生の数学でも出てきそうな話ですね。

ちなみに余談ではありますが、カーナビでの位置測位では4つのGPS衛星を使います。カーナビは空間(3次元)の位置決めをせねばならないからです。

電波強度から距離を計算する方法の知識が必要

「フリスの伝達公式」について調べてください。そして、ビーコンの TxPower と RSSI から実際に距離を計算してみると実感できると思うのですが、機器を安定的な状態に置いていても RSSI が変動することがわかります。そして RSSI から算出できる距離も当然のように変動しています。

確率統計の知識が必要

ビーコンを使った位置決めでは、そもそもビーコンからの距離計算自体が常時変動しています。だから理論上の計算とは違って、正確に位置測位を行うことは不可能です。3つの円の交わった場所は1点に収束せず、一定の面積のエリアを示していることでしょう。

したがって「3つの円が交わったエリアに対して時間軸の変化を重ねた時に、重なりが最も多い場所にいた可能性が高い」などのロジックで場所を推測せねばなりません。

このような位置決めでは確率統計の知識が不可欠です。さて、そろそろうんざりしていませんか?

位置測位を作るために必要なこと(BeaconFenceを使う場合)

BeaconFenceを使えば、三辺測量とか、フリスの伝達公式とか、確率統計の話は出てきません。BeaconFenceがこれらを全てやってくれます。必要なことは、固定ビーコンを使いたいエリアの見取り図を用意して、ビーコンの配置を決めるだけです。

BeaconFence で位置測位アプリを作る

BeaconFenceをインストールする

BeaconFenceはDelphi/C++Builder/RAD Studioを普通にインストールしただけでは含まれていません。GetItパッケージマネージャーから追加する必要があります。IDE起動後の画面で「GetItからアドオンを取得」を選ぶか、または [ツール]=>[GetItパッケージマネージャー]を選択します。
image

GetItパッケージマネージャーで、カテゴリーより [Internet Of Things] を選ぶと以下のような表示となっていることでしょう。
image

ここで[BeaconFence]の[インストール]をクリックするとダウンロードとインストールが行われます。

GetItパッケージマネージャーに BeaconFence が出てこない方は、大変申し訳ないのですが、ここで終了です……。Delphi/C++Builderではエディションにより BeaconFence の利用の可否が異なります。

ですが、以下の内容をご一読いただければ、BeaconFence による測位アプリがとても簡単に作れることがわかると思いますので、ぜひお目通しを。

新規プロジェクトを開く

新規プロジェクトは「マルチデバイスアプリケーションの新規作成」を選びます。「マルチデバイスアプリケーション」ではWindows/macOS/iOS/Android向けのプログラムを単一のソースコードから生成できます。このときのフレームワークは FireMonkey というものが用いられます。これはXamarin.Forms みたいなものだと思ってもらえればよいのかも(Xamarin使ったことないけど)。ここでは Delphi をベースに説明しますが、C++で作成することもできます。
image

マルチデバイスアプリケーションを選ぶと、さらにいくつかのテンプレートが選択できます。ここでは「空のアプリケーション」を選んでみます。
image

そうすると、IDEの画面はこのようになります。それでは作業を始めてみましょう。
image

コンポーネントをフォームに配置する

さて、フォームに対して以下の4種類のコンポーネントを載せていきます。コンポーネントは右下のツールパレットから選んでダブルクリックするか、またはドラッグ&ドロップします。
image

これらのコンポーネントの配置を3次元的に図にすると、こういう感じです。
image

TRectangle を配置する。

Form の上に Rectangle を配置します。Rectangle はナビアプリの描画領域として使いますので、できるだけ大きく表示させたいです。この場合はプロパティの Align = Client と設定しておきます。

image

TLayout を配置する

TLayout はアプリの下部のフッタ領域として使用します。画面の下部に配置する場合は Align = Bottom と設定します。
image

TMemo を配置する

さらに TMemo を TLayout の上に載せます。TMemo は動作に関するメッセージの表示領域として使います。TLayout を選んだ状態で載せます。

TMemo は Align = Client にします。
image

また、編集機能を無効にするために Locked = True にします。
image

BeaconMapFencing を配置する

ここまでの作業で表示用のコンポーネントの配置ができましたので、最後に BeaconFence (BeaconMapFencing) を配置します。BeaconFence のコンポーネント自体は描画の機能を持たない「非ビジュアルコンポーネント」ですので、フォーム上のどこに配置しても構いませんが、ツールパレットで選んでダブルクリックするとフォームの中央に配置されます。

image

そして BeaconMapFencing については、下記3つのプロパティを調整します。

  • PaintContol
  • Enabled
  • MapOptions

Enabled = True にしておくと、アプリ起動時から BeaconFence が有効になります。また、MapOptions はすべての項目を True にしておくと動作が分かりやすくなります。PaintControlはBeaconFenceの描画を受けるコンポーネントを指定します。ここではRectangleを指定しておきます。

image

BeaconMapFencing のマップを編集する

フォーム上の BeaconMapFencing のコンポーネントをダブルクリックすると、マップエディタが開きます。

image

ここでメニューアイコンの一番左をクリックすると、新規のマップが作られます。新規マップが開いたら「エリアの見取り図の画像」を指定し、「幅と高さの長さ」を設定します。

これらの作業が終わると、マップエディタはこのような画面になっていることでしょう。
image

それではいよいよビーコンを配置します。メニューから Create Beacon を選ぶとビーコンを配置できます。マウスでビーコンの位置を決めてクリックすると配置されます。配置が終了したら ESC を押すと配置作業は完了です。
image
配置したビーコンは UUID, Major, Minor が未設定の状態ですので、実際に配置するビーコンの情報を設定してください。

ここまで終わったら、念のために3つのビーコンに識別用の情報が適切に設定されているかどうかを再度確認の上で、マップエディタを閉じます。ウィンドウ右上の[閉じる]ボタンを押すと作成したマップを保存するかどうかを聞いてきますので[はい]を選びます。
image

実機にデプロイする。

この状態でコードは1行も書いていませんが、位置測位のアプリはこれで最低限のものは完成した状態です。これを実機にデプロイしてみましょう。

なお、Android 向けにデプロイする場合は「使用する権限の設定」が必要です。[プロジェクト]の[オプション]より、ビルドターゲット Android を選択し、[使用する権限]で「Bluetooth」と「Bluetooth管理」を True にします。
image

さて、これを実際にデプロイして実行してみます。IDEの画面でターゲットを選んで[実行]ボタンを押すだけです。

Androidの場合はUSBデバッグを有効にした機材をUSBケーブルでIDE実行中の機材に直接接続します。

image

なお、iOSでは「XCodeをインストールしたmac」に「PAServer」をインストールして「IDEとPAServerが通信できる状態」に設定しておくことが必要です。また原則として iOS 向けの実機デプロイでは Apple Developer Network への加入等が必要です。これらの説明はここでは省略しています。

また、iOS 向けにデプロイする場合には1点だけ注意があります。Delphi/C++Builder 10.1 Berlin の Update 1 と Update 2 を利用中の場合は iOS 64bit 向けのビルドが失敗します。これは Update 1 と Update 2 のパッケージングが腐っているようなので、利用者側での対処方法ができません。この問題はR&D側に報告済みですので、R&D側の対応待ちです。幸いなことに(?)BeaconFenceはGetItからインストールするコンポーネントですから、本件の対応はおそらくはR&D側の対処が完了したらGetItでの入れ直しで済むと思われます。

さて、実機へのデプロイを行うと、このような画面でアプリが動きます。

image

色の判例はざっくり書くとこんな感じです。

  • 黒丸は計算上の位置です。(10.1 Berlin以降では色をプロパティで変更可能)
  • 紫色は補正後の位置です。(10.1 Berlin以降では色をプロパティで変更可能)
  • ビーコンは電波の受信状況によって色が変わります。白丸なら電波を受けていません。黄色や緑なら電波を受信できています。
  • ビーコンの周りの赤丸(塗りなし)は、電波を受信している雰囲気を描画しています。実際の動作ではビーコンの周囲に赤い円が広がっていくような動きをつけて描画しています。

これらを描画する、しないの設定は BeaconMapFencing のプロパティのうち [MapOptions] で変更可能です。初期値ではこれらを描画しませんが、今回は全てを True に変更しましたので、全て描画されています。本番運用では位置だけを表示するのが良いのですが、開発時は必要に応じて表示する項目を増やした方が良いかと思います。

また補正は近くのビーコンまたは「パス」に対して寄せるように補正が掛かります。今回は「パス」を設定していないのでビーコンに対しての補正だけが行われています。

出来上がった後に必要なこと

ビーコンを使った位置測位では、ビーコンの電波を反射吸収するような障害物の影響を減らすように配置を工夫することが必要です。また、その他の電波との干渉についても留意せねばなりません。これに関する説明だけで記事が1つ作れるくらいなので詳細は省略しますが、実際の利用では十分にキャリブレーションされたビーコンを用いたとしても現場でのビーコン配置の微調整は必須と考えておくべきです。

次回予告?

思ったよりも今回の内容はボリュームが大きくなってしまったので、いくつかの取りこぼしがあります。

せっかく配置した Memo を活用していなかったり、あるいは「パス」の機能も使えていませんので、次回は Memo に対して情報を出力したり、あるいは「パス」を定義して位置の補正を積極的に行う話をしつつ、位置情報のログをクラウド側に送信してデータロギングする話もしたいと考えています。

⇒ Delphi Advent Calendar 2016 24日目に「IoTデバイスの計測値やiBeaconを利用した位置測位結果をGoogle Spreadsheetでリアルタイムに分析するためにGoogle Formを使う」を書きました。