RSSI と TxPower からビーコンとの距離および近接度（Proximity）を推定する

先日、Eddystone の使いどころについて書いた記事で、<b>iBeaconと比較した場合の利点のうちのひとつは「カスタマイズ性」</b>（＝自前実装が可能）であると書きました。 [^1]

- [Eddystone と iOS - その1: iBeacon と比較したメリット・デメリット](http://qiita.com/shu223/items/9ff648211af6554ebaf0)

[^1]: iOSでは、iBeacon仕様のビーコンを検出し Proximity UUID / Major / Minor を取得するということを Core Bluetooth で自前で実装することができないようになっている。詳しくは [こちらの記事](http://qiita.com/shu223/items/9ff648211af6554ebaf0) を参照

この場合、Core Bluetooth を使って、

1. Eddystone ビーコンをスキャン
2. 発見時に得られるアドバタイズメントデータを解析

という処理を実装することになるわけですが、

- [Eddystone と iOS - その2: 実装編](http://qiita.com/shu223/items/cf21c63b7b58b96bfbc0)

その際に Core Location の iBeacon 実装と同等のことをしたければ、つまり<b>「近接度（Proximity）」を知りたければ、 didDiscoverPeripheral〜 メソッドの引数に渡されてくる RSSI と、ビーコンの TxPower から推定距離を算出する</b> 必要があります。 [^2]

[^2]: 推定距離を算出せず、<b>RSSIの値をそのまま平均して閾値処理にかけて近接度を判定</b>するという実装もみかけます。RSSIは対数ベースの値だし、あまり適切ではないと思うのですが、どうなんでしょうね。。

## TxPower と RSSI について

### TxPower

**ビーコンが発する信号の強さ**を示していて、単位は dBm （ディービーエム）です。**iBeacon の場合は 1m**  離れた地点での受信信号強度を利用しますが、**Eddystone の場合は 0m** 地点での強度を利用する、という違いがあります。

- https://github.com/google/eddystone/tree/master/eddystone-uid

> Note that this is different from other beacon protocol specifications that require the Tx power to be measured at 1 m.


**1m 地点の受信信号強度に 41dBm を足すと 0m 地点での受信信号強度に** なります。

- https://github.com/google/eddystone/tree/master/eddystone-url

> Note to developers: the best way to determine the precise value to put into this field is to measure the actual output of your beacon from 1 meter away and then add 41dBm to that. 41dBm is the signal loss that occurs over 1 meter.


iBeacon の場合はこの値は Proximity UUID や Major, Minor が入っている Manufacturer Data の領域の最後に入っています。

- [iBeacon と BLE](http://d.hatena.ne.jp/shu223/20141208/1418051009)


Eddystone の場合は、この値は [Eddystone-UID フレーム](https://github.com/google/eddystone/tree/master/eddystone-uid) や、[Eddystone-URL フレーム](https://github.com/google/eddystone/tree/master/eddystone-url) より取得できます。


ちなみに iBeacon の場合は Core Location 内部で Proximity を計算するので、この値を Core Location の API から直接取得することはできません。が、iOS をペリフェラル（ビーコン側）としてふるまわせたい場合に利用する `peripheralDataWithMeasuredPower:` メソッドの引数に `nil` を指定するとデフォルト値が設定されるのですが、その値は -59dBm となります。


### RSSI

Received Signal Strength Indication の略で、ここでは iOS デバイスが受信した電波の強度を示します。単位は同じく dBm です。


## RSSI と TxPower から推定距離を計算する

**自由空間では受信信号強度は距離の二乗に反比例**して減衰していく（フリスの伝達公式）ので、RSSI と TxPower と距離（d）の関係は次のようになります。

```
RSSI = TxPower - 20 * lg(d)
```

（lg は底を 10 とする常用対数）

というわけで、距離 d の計算式は以下のようになります。

```
d = 10 ^ ((TxPower - RSSI) / 20)
```

Swift のコードだとこんな感じです。

```swift:swift
let d = pow(10.0, (TxPower - RSSI) / 20.0)
```

ちなみに上で「自由空間」と書きましたが、自由空間というのは「障害物のない理想空間」を意味していて、実際には**障害物の有無などで電波の受信強度というのは変わってきます**。

これを考慮したい場合には次のように距離に係る部分を変数にします。

```
RSSI = TxPower - 10 * n * lg(d)
```

この係数は

- n = 2.0 : 障害物のない理想空間
- n < 2.0 : 電波が反射しながら伝搬する空間
- n > 2.0 : 障害物に吸収され減衰しながら伝搬する空間

という意味になります。


（参考書籍、ページ）

- iBeacon ハンドブック 2.3 「ビーコンまでの距離推定」

<div class="amazlet-box" style="margin-bottom:0px;"><div class="amazlet-image" style="float:left;margin:0px 12px 1px 0px;"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/B00J9MHG66/22301-22/ref=nosim/" name="amazletlink" target="_blank"><img src="http://ecx.images-amazon.com/images/I/41Xi8teJQsL._SL160_.jpg" alt="iBeacon ハンドブック" style="border: none;" /></a></div><div class="amazlet-info" style="line-height:120%; margin-bottom: 10px"><div class="amazlet-name" style="margin-bottom:10px;line-height:120%"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/B00J9MHG66/22301-22/ref=nosim/" name="amazletlink" target="_blank">iBeacon ハンドブック</a><div class="amazlet-powered-date" style="font-size:80%;margin-top:5px;line-height:120%">posted with <a href="http://www.amazlet.com/" title="amazlet" target="_blank">amazlet</a> at 14.12.08</div></div><div class="amazlet-detail"> (2014-03-25)<br />売り上げランキング: 11,647<br /></div><div class="amazlet-sub-info" style="float: left;"><div class="amazlet-link" style="margin-top: 5px"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/B00J9MHG66/22301-22/ref=nosim/" name="amazletlink" target="_blank">Amazon.co.jpで詳細を見る</a></div></div></div><div class="amazlet-footer" style="clear: left"></div></div>

- [無線 LAN と通信距離について(1)｜Wireless・のおと｜サイレックス・テクノロジー株式会社](http://www.silex.jp/blog/wireless/2011/11/-lan-1.html)
- [Estimating beacon proximity/distance based on RSSI - Bluetooth LE - Stack Overflow](http://stackoverflow.com/questions/22784516/estimating-beacon-proximity-distance-based-on-rssi-bluetooth-le)


## 近接度（Proximity）への変換

Core Location の実装ではビーコンとの距離を、CLBeacon の `proximity` プロパティから、以下の3段階で得られるようになっています。

- CLProximityImmediate （非常に近い）
- CLProximityNear （近い）
- CLProximityFar （遠い）

Appleのドキュメント「[Getting Started with iBeacon](https://developer.apple.com/ibeacon/Getting-Started-with-iBeacon.pdf)」によると`Near`は1〜3mとされています。

> With a clear line of sight from the device to the beacon, this would indicate a proximity of approximately 1-3 meters. 

また上に載せた『ビーコンハンドブック』によると、Immediateは〜20cmとされています。[^3]

[^3]: Appleのリファレンス、プログラミングガイドではこの記述を発見できず。WWDCの資料とか、他のドキュメントに書いてある？

単純な閾値による判定が行われているのか、その閾値はいくつなのか、というのはわかりませんが、上記を目安に近づけることは可能です。

またレンジングの間隔は1秒であること、CLBeacon の `accuracy` プロパティは "one sigma horizontal accuracy in meters" を示していることから、**何回分かのRSSIから計算した推定距離を平均化して近接度の判定に用いていると推測**されます。


## accuracy（精度）の計算

### CLBeacon の accuracy について散見される誤解

ちょっと話はずれるのですが、CLBeacon の `accuracy` プロパティについて、**「ビーコンとの推定距離をメートル単位で示したもの」という記述**を結構みかけます。（日本語記事だけじゃなくて、StackOverflowとかでも見かける）

ただ [Appleのリファレンス](https://developer.apple.com/library/prerelease/ios/documentation/CoreLocation/Reference/CLBeacon_class/index.html#//apple_ref/occ/instp/CLBeacon/accuracy) によるとこの `accuracy` は

> one sigma horizontal accuracy in meters

とあり、この "one sigma" は 

> 標準偏差によって定義される範囲は測定の68.3%（1σ）の信頼区間である。標準偏差を正確に求めるために十分な回数の測定が行われ、測定の誤差に偏りがなければ、測定のうち68.3%は 1σ の範囲にあり、95.4%は 2σの範囲にあり、99.7%は 3σ の範囲にあることになる。（[正確度と精度 - Wikipedia](https://ja.wikipedia.org/wiki/%E6%AD%A3%E7%A2%BA%E5%BA%A6%E3%81%A8%E7%B2%BE%E5%BA%A6)）

![](sigma.png)

の意味での "1σ"（シグマ）です。

なので、`accuracy` は **推定距離ということではなく、推定距離のばらつきを示す**値です。

というわけでリファレンスでも、

> Use this property to differentiate between beacons with the same proximity value. Do not use it to identify a precise location for the beacon. 

と、「同じ proximity であるビーコン同士の比較に使いましょう」としているわけですね。


### accuracy の計算

というわけで CLBeacon の accuracy 相当の値が欲しい場合には、推定距離の標準偏差を計算します。


## まとめ

RSSI と TxPower から距離を推定する方法について書きました。個人的には Eddystone を iBeacon の代替として用いる際にこの実装が必要になりましたが、iBeacon を使う場合でも、ラップされているとはいえ、このあたりを理解しておくとトラブルシューティングの際などにも見通しがよくなるのではないかと思います。