アールテクニカ地下ガレージ

アールテクニカ株式会社の製品開発・研究開発・日々の活動です

ARKitでポジショントラッキングと平面検出

Author

中村@アールテクニカ

アールテクニカの中村です。
iOS11から使えるようになったARKitを使ってポジショントラッキングと平面検出を行うアプリを作成します。

ARKitとは

概要

iOS 11から使用可能となったAR(拡張現実)のためのフレームワークです。
対応デバイスであればiOSデバイスのみでポジショントラッキングや平面検出などが可能です。
ただし、専用のセンサーなどを搭載したデバイスに比べると精度は落ちます。

対応機種

iOS11以降かつA9チップ以上を搭載したiOSデバイスが必要となっており、
iPhoneは6S/SE以降、iPadは第5世代以降の機種が必要です。
現行機種では、iPad mini 4とiPod touch(第6世代)は非対応なので注意が必要です。

アプリの作成

新規プロジェクト作成

Xcode9から新規プロジェクトのテンプレートに「Augumented Reality App」が追加されたのでこれをベースに作成します。

Xcode9で[File] → [Project]で新規プロジェクト作成画面を開らき、"Augumented Reality App"を選択します。

f:id:artteknika_nakamura:20180111203750p:plain:w560

「Content Technology」は、SceneKit、SpriteKit、Metalが選択できます。
オーバーレイ表示させるオブジェクトが3D表示の場合はSceneKit、2D表示の場合はSpriteKitを選択します。
Metalはよりパフォーマンスが必要な3D処理が必要な場合に選択します。
今回は、SceneKitを選択します。

f:id:artteknika_nakamura:20180111203812p:plain:w560


プロジェクトを作成したら、まずテンプレートのままの状態でビルド&実行して見ます。
アプリを起動すると正面に飛行機の3Dオブジェクトが表示されます。
iPhoneを前後左右上下に動かしたり回転させても飛行機の位置は同じ位置に留まったままです。


ARKitテストプロジェクト


ソースコードを見て見ると、ポジショントラッキングを開始するだけであれば、
ViewController.swiftのviewWillAppear(_)で、下記のコードを実行するだけで良いようです。
非常に簡単ですね。

let configuration = ARWorldTrackingConfiguration();
 sceneView.session.run(configuration)

平面検出の実装

平面の検出と検出した平面の画面表示のコードを追加します。

まず最初に、viewWillAppear(_)に下記のコードを追加すると平面検出を行います。

configuration.planeDetection = .horizontal
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
        
    // Create a session configuration
    let configuration = ARWorldTrackingConfiguration();
    // 平面の検出を有効化する
    configuration.planeDetection = .horizontal
        
    // Run the view's session
    sceneView.session.run(configuration)
}


次に平面が検出された時に呼ばれるARSCNViewDelegateのrenderer(_:didAdd:for:)を実装します。
検出された平面の情報がanchor引数で渡されるので、これを元にシーンに平面ノードを追加します。

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

    guard let planeAnchor = anchor as? ARPlaneAnchor else { return  }
        
    // 平面ジオメトリ作成
    let plane = SCNPlane(width: CGFloat(planeAnchor.extent.x), height: CGFloat(planeAnchor.extent.z))
       
    // 平面ジオメトリをグリーンの半透明に
    let planeMaterial = SCNMaterial()
    planeMaterial.diffuse.contents = UIColor.green.withAlphaComponent(0.5)
    plane.materials = [planeMaterial]
        
    // 平面ノード作成
    let planeNode = SCNNode(geometry: plane)
    planeNode.position = SCNVector3Make(planeAnchor.center.x, 0, planeAnchor.center.z)
    planeNode.transform =  SCNMatrix4MakeRotation(-Float.pi / 2, 1, 0, 0)
    node.addChildNode(planeNode)
}

動作確認

カメラで床やテーブルを写して平面検出を行います。
平面が検出されると緑色半透明の平面が表示されます。
検出完了には数秒かかります。
f:id:artteknika_nakamura:20180111195421j:plain:h400

少し上に向けると飛行機のオブジェクトがいます。
f:id:artteknika_nakamura:20180111195934j:plain:h400

最後に

ARKitを使えば簡単にポジショントラッキングや平面検出が実装できました。
この他にも現実空間や3Dオブジェクトに対し当たり判定を行うことが出来るのでインタラクティブなARアプリを作成することも可能です。
次回はこの当たり判定を使って見たいと思います。

Author

中村@アールテクニカ

アールテクニカのSE兼プログラマ。Web系のサーバサイド・フロントエンドからスマホ・PCのネイティブアプリまでソフトウェア開発全般が守備範囲。最近はハードウェア開発にも興味あり。

スポンサーリンク