はじめに
スマートフォンの近距離無線通信といえば、みなさん Bluetooth, Wi-Fi, NFC あたりを思い浮かべるでしょう。実はiPhoneでは、UWB(超広帯域無線)というもう一つの無線通信があることをご存知でしょうか。
iPhone11 から iPhone に標準搭載されるようになった Apple U1チップ。Apple製デバイスをUWBに対応させる専用チップで、一般向け製品に UWB が搭載された初のケースです。特に近距離の正確な位置測位に強く、他にはないポテンシャルを秘めています。
しかし、LiDARスキャナの話題性に比べ、こちらはあまり使われているアプリを見ることがありません(Apple公式の「探す」アプリくらい?)。今回はそんな UWB と、Apple の UWB 技術を簡単に使える開発者向けフレームワーク「NearbyInteraction」についてご紹介いたします。
目次
UWBについて
UWBとは?
UWB(Ultra Wide Band)
-
距離と方向が正確に取得できる、近距離の屋内位置測位技術。
通信距離は10m程度の近距離通信
距離と方向が正確に取得できる(誤差数十cm) -
超広帯域の周波数幅にわたって、低電力密度の無線電波を用いて無線通信を行う技術 (500MHz ~ 数GHz)
屋外利用は7.25-9.0 GHz, 24.25-29 GHz に限られる(2019年5月20日の総務省令) -
標準規格 IEEE 802.15.4z(2019年)
-
消費電力が極めて少ない(2.4 mW)
-
データ伝送の通信量 100 Mbps以上
-
三点測位によるリアルタイム位置測位システム(Real Time Location System:RTLS)に使われる
-
AirTagにも対応。「探す」アプリで正確な位置を特定することができる。
Bluetoothとの比較
同じく近距離無線通信で広く活躍している Bluetooth (BLE) との違いは以下の通りです。
UWB (Ultra Wide Band) | Bluetooth | Bluetooth (5.1~) | |
---|---|---|---|
消費電力 | 少ない | 少ない(特にBLE) | 少ない(特にBLE) |
通信距離 | ~10m程度 | ~10m程度 | ~10m程度 |
測距の誤差 | 10cm程度 | 1~5m程度 | 1~5m程度 |
方向の取得 | 可 | 不可 | 可(AoA) |
測距・測位方法 | ToF (Time of Flight) | RSSI (Received Signal Strength Indicator) | RSSI,AoA (Angle of Arrival) |
対障害物 | 比較的強い | 弱い | 弱い |
通信速度 | 100 Mbps以上 | 1 Mbps (4.0) | 2 Mbps (5.0以降) |
対応機種 | iPhone 11~ | 全てのiPhone | iPhone 11~ |
周波数 | 500MHz ~ 数GHz。屋外利用は7.25-9.0 GHz, 24.25-29 GHz に限られる(2019年5月20日の総務省令) | 2.4GHz帯 | 2.4GHz帯(日本の屋外利用) |
Nearby Interaction
Apple で UWB 通信をするために iOS14で導入されたフレームワーク。
これまでの Nearby Interaction
WWDC2020での登場以来、毎年新情報が更新されています。
WWDC2020 Meet Nearby Interaction
・iPhone to iPhone
WWDC2021 Explore Nearby Interaction with third-party accessories
・iPhone to Apple Watch
・Third-party Accessories
WWDC2022 What's new in Nearby Interaction
・Enhanced NI with ARKit
・Background Sessions, Third-party Hardware
実際の動作のイメージなども、ここから動画で確認できます。
フレームワークの概要
今回は最も簡単なiPhone to iPhone をベースに説明します。
接続のステップ
iPhone to iPhone のUWB接続は、大きく分けて以下の6ステップで実行されます。
- NISession の生成
- delegate のセット
- Peerデバイスと NI discovery token を共有
*tokenの共有方法はNearbyInteractionは提供していないため、bluetooth接続など他の方法で共有する必要がある
例:Multipeer Connectivity, Core Bluetooth - Peerデバイスから NI discovery token を受信
- session configration の作成
- 上記 configration でセッションを実行
// 1.NISession の生成
let session = NISession()
// 2.delegate のセット
session.delegate = self
// 3.Peerデバイスと NI discovery token を共有
let myDiscoveryToken = session.discoveryToken
sendDiscoveryTokenToMyPeer(peer, myDiscoveryToken) // YOUR app's method
// 4.Peerデバイスから NI discovery token を受信
let peerDiscoveryToken = ...
// 5.session configration の作成
let config = NINearbyPeerConfigration(peerToken: peerDiscoveryToken)
// 6.上記 configration でセッションを実行
session.run(config)
NI discovery token: ランダムに生成された一時的なセッションID。セッションが存続する間は有効。
NISessionクラスのインスタンスプロパティとして呼び出せる。
セッション実行の流れ
- NISessionでデリゲートを取得
- 実行すると、デリゲートが近傍オブジェクトの更新データを取得
余談ですが、1vsN で multiple session をする場合は、NISession までの流れを複数用意して、同一のdelegateを取得します。
NISessionクラス のよく使うインスタンスメソッド
NISession: 2 つのpeer devicies 間の一意の接続を識別する。
以下に、よく使うインスタンスメソッドの名前と引数、使用例を記載する。
open class NISession : NSObject {
// NI discovery token
@NSCopying var discoveryToken: NIDiscoveryToken? { get }
// セッションで実行される構成
@NSCopying var configuration: NIConfiguration? { get }
// セッションの操作
func run(_ configuration: NIConfiguration)
func pause()
func invalidate()
}
let session = NISession()
// セッションの実行
session.run(config)
// セッションのポーズ
session.pause()
// セッションの再開
session.run(session.config)
// セッションの停止
session.invalidate()
NISessionDelegate のよく使うインスタンスメソッド
NISessionDelegate: セッションの更新を監視して対応するオブジェクト。
以下に、よく使うインスタンスメソッドの名前と引数を記載する。
// NearbyInteraction の session delegate
public protocol NISessionDelegate : NSObjectProtocol {
// セッションが近傍オブジェクトを更新したときに通知
optional func session(
_ session: NISession,
didUpdate nearbyObjects: [NINearbyObject]
)
// セッションが1つ以上の近傍オブジェクトを削除したときに通知
optional func session(
_ session: NISession,
didRemove nearbyObjects: [NINearbyObject],
reason: NINearbyObject.RemovalReason
)
// 中断されたセッションを通知
optional func sessionWasSuspended(_ session: NISession)
// セッションの再開を通知
optional func sessionSuspensionEnded(_ session: NISession)
// 無効化されたセッションを通知
optional func session(
_ session: NISession,
didInvalidateWith error: Error
)
}
NINearbyObjectクラス から取得できる情報
open class NINearbyObject : NSObject, NSCopying, NSSecureCoding {
// discovery Token
@NSCopying var discoveryToken: NIDiscoveryToken { get }
// 相対距離の取得
public var distance: Float? { get }
// 角度の取得
public var direction: simd_float3? { get }
}
使用例
以下に、NearbyInteraction を開始するための簡単なメソッドの例を記載します。
func startup() {
// ① NISessionの生成
session = NISession()
// ② delegate のセット
session?.delegate = self
// トークン共有フラグのリセット(新規セッション開始のため)
sharedTokenWithPeer = false
// `connectedPeer`が存在する場合(P2P接続できている場合)、必要に応じて discovery トークンを共有
if connectedPeer != nil && mpc != nil {
// 接続済みの場合
// ③ Peerデバイスと discovery token を共有
if let myToken = session?.discoveryToken {
updateInformationLabel(description: "Initializing ...")
if !sharedTokenWithPeer {
shareMyDiscoveryToken(token: myToken)
}
// ④ Peerデバイスから discovery token を受信
guard let peerToken = peerDiscoveryToken else {
return
}
// ⑤ session configration の作成
let config = NINearbyPeerConfiguration(peerToken: peerToken)
// ⑥ 上記 configration でセッションを実行
session?.run(config)
} else {
fatalError("Unable to get self discovery token, is this session invalidated?")
}
} else {
// 接続できていない場合
updateInformationLabel(description: "Discovering Peer ...") // UIに文字列を設定
// P2P通信スタートアップ(P2P通信の開始トリガー)
// * Multipeer Connectivity フレームワークを使用 *
startupMPC()
// 距離・方向ステータスにunknownをセット
currentDistanceDirectionState = .unknown
}
}
おわりに
実際にアプリを作って動かしてみて、以下のような感想を持ちました。
・距離は10m以内であれば、どのように持っていても非常に正確な値が取れる。
・角度はiPhoneの背面同士を向け合わないと、取得が難しい。
すぐに使えるサンプルコードもあるので、ぜひお手元のiPhoneにビルドして動かしてみてください。
参考
Apple公式 https://developer.apple.com/documentation/nearbyinteraction
NearbyInteractionで周囲の端末の位置を測定する