AppleがARKitを発表してからもう2年以上たちました。 今回 iPad Proの発売にあわせてリリースされたARKit3.5では、また新しい進化がありました。 なにができるようになったのかみていきましょう。
Scene Geometory
ARKit3.5では、新しい iPad Proに搭載された LiDARスキャナーを利用して、周囲の物体の正確な位置測定と種類判別を行えるようになりました。 この機能はLiDARスキャナー搭載デバイス(2020年3月時点では iPad Pro 11 inch/12,0 inchのみ)でしか使えないので、現時点では利用範囲が限定されますが、今までの位置判定より格段に正確で、とても強力な機能です。
この動画でわかるように、周囲の物体を動的にメッシュとして認識し、それらの種類を判別できるようになります。
ARKitは、複数のレンダリング方法をサポートしていますが、この機能はRealityKitでレンダリングをする場合だけ利用可能です。
RealityKitでレンダリングをするARプロジェクトをつくり、ARConfiguration
のsceneReconstruction
を設定すると、自動的にメッシュ作成・判別が行われます。(.mesh
を指定した場合には、メッシュのみの判定、.meshWithClassification
を指定した場合にメッシュに加えて物体の種類判定も行われます。)
let configuration = ARWorldTrackingConfiguration() configuration.sceneReconstruction = .meshWithClassification
上の動画のようにメッシュを表示するには、ARViewのDebugOptionを設定します。 (ただし、このメッシュ表示はデバッグ用で、ユーザーに見える場所で表示するのは望ましくないようです。)
arView.debugOptions.insert(.showSceneUnderstanding)
メッシュを表現するクラスは、ARAnchor
の拡張クラス、ARMeshAnchor
です。
ARView
のsession
から、今までに使っていた ARAnchor
も含んだ形で取れます。
arView.session.currentFrame.anchors
ARMeshAnchorは、位置情報の他に物体の種類(classification)情報を持っています。
classificationはこの8種類。
public enum ARMeshClassification : Int { case none = 0 // なし case wall = 1 // 壁 case floor = 2 // 床 case ceiling = 3 // 天井 case table = 4 // テーブル case seat = 5 // 椅子 case window = 6 // 窓 case door = 7 // ドア }
物質判定はかなり正確で、カーテンがついていても窓を認識してくれるし、テーブルや椅子も正確に認識されます。
ARMeshAnchor
の一つ一つが「壁」とか「窓」と判定されるわけではありません。
ARMeshAnchor
は複数の「面」をもちますが、それぞれの面に対して種類判定が行われます。
let anchor: ARMeshAnchor for face in anchor.geometry.faces{ let classification: ARMeshClassification = anchor.geometry.classificationOf(faceWithIndex: index) }
Scene Geometoryについては、Appleが提供しているこちらのサンプルを見ると参考になります。
LiDARスキャナーの精度
さて、今回のLiDARスキャナーの精度はどのくらいでしょうか。
iPad Pro 11 inchで確認してみたところ、このくらいの数値でした。
- 距離判定精度 : 約 1~2cm
- 到達距離 : 約 3~4m
(私が個人的に測定したものなので、正確な測定ではありませんし、対象物などによっても異なると思うので参考程度の値です。)
端末間のCompatibility確認
ARKitもかなりバージョンがあがってきたので、端末間の連携アプリを作る際などに、それぞれの端末のARKitのバージョンも気にしなければいけなくなってきました。
ARKitはiOSに含まれているので、iOSのシステムバージョンを確認すればARKitのバージョンも類推できますが、少し面倒ですよね。
端末間のARKitの互換性確認のために NetworkCompatibilityToken
が使えるようになりました。
自分のトークンを NetworkCompatibilityToken.local
で取得し、他のデバイスのトークンと比較すると、Compatibility. compatible
かCompatibility . sessionProtocolVersionMismatch
が得られます。
Compatibility . sessionProtocolVersionMismatch
の場合には連携処理をしないなどの対応をすれば万全です。
なお、他のデバイスのトークンを取得する方法はデフォルトで用意されていません。
例えば MultipeerConnectivity
を使うときには、MCNearbyServiceAdvertiser
のdiscoveryInfo
などにいれるなどの処理をしておきましょう。
let localToken = NetworkCompatibilityToken.local let anotherToken = ... // 他のデバイスのトークン let compatibility = localToken.compatibilityWith(anotherToken) switch compatibility { case .compatible: // 処理を続ける case .sessionProtocolVersionMismatch: // OSのバージョンアップをしてください、などのアラートを表示する。 }