ARKit3.5で周囲の物の位置が正確にわかるようになりました。

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プロジェクトをつくり、ARConfigurationsceneReconstructionを設定すると、自動的にメッシュ作成・判別が行われます。(.meshを指定した場合には、メッシュのみの判定、.meshWithClassificationを指定した場合にメッシュに加えて物体の種類判定も行われます。)

let configuration = ARWorldTrackingConfiguration()
configuration.sceneReconstruction = .meshWithClassification

上の動画のようにメッシュを表示するには、ARViewのDebugOptionを設定します。 (ただし、このメッシュ表示はデバッグ用で、ユーザーに見える場所で表示するのは望ましくないようです。)

arView.debugOptions.insert(.showSceneUnderstanding)

メッシュを表現するクラスは、ARAnchorの拡張クラス、ARMeshAnchorです。 ARViewsessionから、今までに使っていた 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が提供しているこちらのサンプルを見ると参考になります。

https://developer.apple.com/documentation/arkit/world_tracking/visualizing_and_interacting_with_a_reconstructed_scene

LiDARスキャナーの精度

さて、今回のLiDARスキャナーの精度はどのくらいでしょうか。

iPad Pro 11 inchで確認してみたところ、このくらいの数値でした。

  • 距離判定精度 : 約 1~2cm
  • 到達距離 : 約 3~4m

(私が個人的に測定したものなので、正確な測定ではありませんし、対象物などによっても異なると思うので参考程度の値です。)

f:id:toyship:20200329205617j:plain
床にメジャーをおいて測定

端末間のCompatibility確認

ARKitもかなりバージョンがあがってきたので、端末間の連携アプリを作る際などに、それぞれの端末のARKitのバージョンも気にしなければいけなくなってきました。

ARKitはiOSに含まれているので、iOSのシステムバージョンを確認すればARKitのバージョンも類推できますが、少し面倒ですよね。 端末間のARKitの互換性確認のために NetworkCompatibilityToken が使えるようになりました。

自分のトークンを NetworkCompatibilityToken.local で取得し、他のデバイスのトークンと比較すると、Compatibility. compatibleCompatibility . sessionProtocolVersionMismatch が得られます。 Compatibility . sessionProtocolVersionMismatch の場合には連携処理をしないなどの対応をすれば万全です。

なお、他のデバイスのトークンを取得する方法はデフォルトで用意されていません。 例えば MultipeerConnectivityを使うときには、MCNearbyServiceAdvertiserdiscoveryInfoなどにいれるなどの処理をしておきましょう。

        let localToken = NetworkCompatibilityToken.local
        let anotherToken = ... // 他のデバイスのトークン

        let compatibility = localToken.compatibilityWith(anotherToken)
        
        switch compatibility {
        case .compatible:
            // 処理を続ける
        case .sessionProtocolVersionMismatch:
            // OSのバージョンアップをしてください、などのアラートを表示する。
        }