Loading
BLOG 開発者ブログ

2025年5月20日

Apple Vision ProのLiDARスキャナを利用した空間のメッシュ可視化

はじめに

こんにちは。
クラウドソリューショングループのyamasaki.sです。

ARKitのLiDARスキャナをApple Vision Proでも利用して、部屋や周囲が認識できないか実際に実装して試してみました!

目次

LiDARスキャナとは

LiDAR(Light Detection and Ranging)スキャナとは、LiDAR技術を利用して対象物や周囲の空間をスキャンし、高精度な3Dデータを取得する装置のことです。

実装

まず、LiDARスキャナを利用するために開始処理と停止処理を実装します。
SceneReconstructionProviderを利用して、LiDARスキャナで得た周囲の情報(シーン)を取得します。

import Foundation
import ARKit

@MainActor
class LiDARScanner:ObservableObject {
    let session = ARKitSession()
    private var sceneReconstruction = SceneReconstructionProvider()

    func start() async {
        do {
            try await session.run([sceneReconstruction])
        } catch {
        print("ARKitSession error:", error)
        }
    }

    func stop() {
        session.stop()
    }
}

次に、LiDARスキャナで得たシーンを検知して状態に応じて処理を分けます。
「anchorUpdates」でシーンのイベントごとの処理を実装します。

class DemoLiDARScanner:ObservableObject {
...

    func start() async {
        do {
            try await session.run([sceneReconstruction])
            await processMeshAnchor()
        } catch {
            print("ARKitSession error:", error)
        }
    }

...

    func processMeshAnchor() async {
        for await update in sceneReconstruction.anchorUpdates {

            switch update.event {
                case .added:
                // 追加
                case .updated:
                // 更新
                case .removed:
                // 削除
            }
        }
    }
}

追加では、ModelEntityを生成し、シーンから取得した座標やスケール などに合わせて変換して配置します。
更新では、追加時に登録したIDをもとに、再度シーンから取得した座標やスケールなどに合わせて変換し直します。
削除では、保持していたデータから対象のIDとそのデータを削除します。

func processMeshAnchor() async {
    for await update in sceneReconstruction.anchorUpdates {
        let meshAnchor = update.anchor

        switch update.event {
            case .added:
                // 追加
                let entity = ModelEntity()
                entity.transform = Transform(matrix: meshAnchor.originFromAnchorTransform)

                meshEntities[meshAnchor.id] = entity
                contentEntity.addChild(entity)
            case .updated:
                // 更新
                guard let entity = meshEntities[meshAnchor.id] else { continue }
                entity.transform = Transform(matrix: meshAnchor.originFromAnchorTransform)
            case .removed:
                // 削除
                meshEntities[meshAnchor.id]?.removeFromParent()
                meshEntities.removeValue(forKey: meshAnchor.id)
        }
    }
}

最後に、最初に実装したstartとstopを呼び出す処理を加えれば、大まかな処理は完了です。

ビルド

さらに少し手を加えてみるとこんな感じで見えるようになります。
(薄く青っぽい感じの部分がLiDARスキャナで読み取れた箇所になります)

さいごに

簡単な実装ではLiDARスキャナの力を十分に引き出すことはできませんでしたが、その可能性を強く感じました!

周囲の情報を読み取りより精密に表現することで「バーチャル空間にいながら現実空間を感じる」「現実空間の情報をバーチャルで表現する」といった体験を実現できる可能性がありそうですね!

yamasakiのブログ