ビーコンの距離測定精度を上げるためのキャリブレーションを行うアプリをDelphiで作る

  • 1
    いいね
  • 0
    コメント

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

また、前回の記事 DelphiでスマホやPCをBLEビーコンにしたり、ビーコンの電波を受けてみたりする の続きです。

ビーコン(iBeacon)で距離測定の基本的な話

iBeaconは、BluetoothLEとのアドバタイズを使ったビーコンです。そしてBluetoothLEというのは2.4GHzの周波数帯(ISMバンド)の電波を用いる規格です。

さて、ビーコンで距離を測るというのはどういうことでしょうか。基本的にはこういうことです。

  • 電波の強さは距離の2乗に反比例して弱くなる。
  • 「ビーコンから1メートル離れた場所で測定した電波の強さ」が分かっていれば、別な地点で測定した電波の強さとの比較や計算により、その場所がビーコンからどれくらい離れているかを知るころができる。

よって、まずはビーコンの電波の強さを1メートル地点で測っておき、その強さを知っておくことが必要です。しかしすべてのビーコンの1メートル地点の電波の強さを事前に把握しておくのはデータ管理が大変すぎます。

そのため、iBeaconでは「ビーコン自身が1メートル地点の電波の強さを通知する」ことが仕様の中に含まれています。この電波の強さは TxPower として通知されます。

しかし、実際のビーコンの TxPower を測定してみると、1メートル地点の電波強度とは必ずしも合致しない場合があります。また、PCやスマホをビーコンにする機能を提供するコンポーネントやフレームワークのデフォルトのTxPowerをそのまま用いると、同様に電波強度が合致しない状況がおきやすいです。

ビーコンは障害物による電波の減衰の影響が出やすいのに、さらに精度を下げるようなことがあってはよろしくありません。そこでビーコンによる距離の判定精度を下げないために、ビーコンのTxPowerのキャリブレーションを行うことが大切です。

iBeaconのキャリブレーション方法

iBeaconのキャリブレーションは、基本的には次のような手順で行います。

  • iBeaconから1メートル離れた地点に測定用の機器を置く。
  • iBeaconから1メートルの同心円の接線方向に対して30cmの範囲で測定用機器を動かして電波強度(RSSI)を計測する。
  • RSSIの平均値を TxPower として用いる。

この内容を短いムービーにしてみたのがこちらのURLです。
https://drive.google.com/open?id=0B42eHZU8M1fLQ3BTeWFvckRfdWM

なお、上記の内容はApple の開発者向けサイトにて以下のURLで公開されている文書の内容をベースにしています。
https://developer.apple.com/ibeacon/Getting-Started-with-iBeacon.pdf

以上のことから、ビーコンのキャリブレーションを行うためには以下のような処理が必要になります。

  • RSSIを計測する。
  • RSSIの平均値を計算する。できれば、RSSIの標準偏差も計算する

ただし、こういったことを本気で実装しだすとコード量も増えるから1日分で説明するには分量が多すぎます。

そこでここでは Beacon の電波を受けて表示するだけのカンタンな処理を書いてみることにします。

使用するコンポーネント

iBeaconの電波を受けて以下の情報をログに吐く処理を書いてみましょう。

  • Major
  • Minor
  • RSSI(受信強度)

このために必要なコンポーネントは以下の2つです。

  • TBeacon
  • TMemo

そして、TBeacon のイベントのうち、OnCalculateDistance に対してイベントハンドラを書きます。

この状態をフォームに配置した状態のスクリーンショットはこんなカンジですね。
image

そして CalculateDistance にはこんな処理を書きます。1行しか書いていません。

TForm1.Beacon1CalcutateDistance
procedure TForm1.Beacon1CalculateDistances(const Sender: TObject;
  const ABeacon: IBeacon; ATxPower, ARssi: Integer; var NewDistance: Double);
begin
  Memo1.Lines.Insert(0,Format('%d:%d %d', [ABeacon.Major, ABeacon.Minor, ARssi]) );
end;

TBeacon のプロパティですが、Enabled は True にしておいてください。これによりアプリの起動時から TBeacon が有効になります。

さて、これでビーコンを検出できるかというと、macOS や Android はこれだけでビーコンを検出できます。しかし iOS はこれではダメなのです。

iOS では UUID を明示的に指定された場合に限り、その UUID のビーコンが検出できるようになっています。だから iOS でビーコンの電波を受けるには、使用するビーコンの UUID を TBeacon に教えておく必要があるのです。

これは TBeacon のプロパティのうち、MonitorizedRegions で設定できます。また、構造ペインから MonitorizedRegions を選んで設定することもできます。スクリーンショットは MonitorizedRegions に対して監視対象のビーコンの情報を追加しようとしているところです。

image

MonitorizedRegions の追加を行うと、IDE の画面はこんなふうになっているはずです。
image

ここで監視対象のビーコンの UUID をプロパティで設定します。すると設定した UUID を持つビーコンを検知できるようになります。

ここまで終わったら、ビーコンが動いていることを確認しつつ、作ったアプリを動かしてみます。するとこんなふうに TMemo に情報が出ているはずです。1:1 というのは Major:Minor のペアです。そして -xx という数値がビーコンの電波の受信強度 (RSSI) です。

image

ビーコンから1mの地点で電波強度 (RSSI) を測ることで、ビーコンに本来設定すべき TxPower の値が分かります。その値をビーコンに設定すれば距離測位の精度が改善されます。

もうちょっとまともな測定を行うには

測定したRSSIをTMemoに書き出すだけではイマイチです。できれば、測定値の平均値をアプリで計算するとか、あるいは標準偏差(データの散らばり具合の指標)が見れるほうが良いし、さらにいうと測定値はグラフで見れるほうが便利です。

そして測定値に基づく TxPower の推奨値が分かればキャリブレーションが捗ります。

ここらへんのニーズを満たすための測定アプリのサンプルを GitHub の以下のリポジトリに配置しました。
https://github.com/kazinoue/BeaconCalibratorSimple

このアプリではキャリブレーションに基づく TxPower の補正後の値を自動的に算出します。

アプリ画面のスクリーンショットを貼っておきます。

ビーコン探索画面

RSSI測定とTxPowerの補正値算出

次回予告?

ビーコンのキャリブレーションが出来るようになりましたので、次はいよいよ、BeaconFenceを使って位置測位を行ってみましょう。

⇒ Delphi Advent Calendar 2016 17日目に「固定Beaconを使って現在位置を測位するアプリをDelphi/C++BuilderとBeaconFenceで作る」を書きました。

この投稿は Delphi Advent Calendar 201610日目の記事です。