1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[ARKit] ARWorldMapとは

Posted at

ARWorldMap

AR1.0までAR体験ができてもそれを永続化することができなかった。
こういった弱点を克服するためにARWorldMapは導入され、データの永続化と共有ができるようになった。

具体的にはARSessionでトラッキングした実世界の情報とARアンカーの情報が入っている。

実際なプロパティ

// ワールドマップで検知されたARアンカーたち
var anchors: [ARAnchor] { get set }

// ワールドマップの特徴点
var rawFeaturePoints: ARPointCloud { get }

// ワールドマップの空間のサイズ
var extent: simd_float3 { get }

var center: simd_float3
// ワールドマップの中心点

これらのデータを使用してARSessionを復元する。

ARWorldMapを取得する

ARSessionの下記メソッドを使用して非同期に取得する。

func getCurrentWorldMap(completionHandler: @escaping (ARWorldMap?, Error?)
-> Void)

実際に取得してみる

let session = ARSession()
session.getCurrentWorldMap { worldMap, error in
       guard let worldMap = worldMap else { fatalError() }
}

実際に保存するにはNSKeyedArchiverクラスからarchivedDataメソッドでData型に変換し、
data.write(to: url)を呼び出す。

func writeWorldMap(_ worldMap: ARWorldMap, to url: URL) throws {

    let data = try NSKeyedArchiver.archivedData(withRootObject: worldMap, requiringSecureCoding: true)
    try data.write(to: url)
}

実際に ARWorldMapを取り出すためにはNSKeyedArchiverからunarchviedObjectを呼び出す。

func loadWorldMap(from url: URL) throws -> ARWorldMap {
    let mapData = try Data(contentsOf: url)
    guard let worldMap = try NSKeyedUnarchiver.unarchivedObject(ofClass: ARWorldMap.self, from: mapData)
        else { throw ARError(.invalidWorldMap) }
    return worldMap
}

ワールドマップからセッションを復元してみる

ARWorldTrackingConfigurationには下記のプロパティが存在する

var initialWorldMap: ARWorldMap? { get set }

ここに Data型から復元したARWorldMapオブジェクトをセットしてrunすることでできる。

let configuration = ARWorldTrackingConfiguration()
configuration.initialWorldMap = worldMap
sceneView.session.run(configuration)

これを応用すれば保存したDataを何処かに保存しといて、他の誰かと共有することができる。

ワールドマップをゲットできるタイミング

ARFrameに worldMappingStatusという ARFrame.WorldMap
pingStatus型のプロパティが存在し、ワールドマップを取得するのに良いタイミングかどうかを判断する

var worldMappingStatus: ARFrame.WorldMappingStatus { get }

ARFrame.WorldMappingStatusは enum 型で、次の caseが定義されています。

enum WorldMappingStatus {
 case notAvailable
 //ワールドマッピングができない
 case limited 
// ワールドマッピング可能だが、機能制限が出てきてしまう
 case extending 
// ユーザーの操作によってマッピングが拡大中
 case mapped 
//見えているエリアのマッピング完了した状態
}

他のステータスではユーザーに行動の指針を示す、といったことが可能になります。
オブジェクトが停止しなければフレームごとに呼ばれる。
そこで保存ボタンなどを

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
// オブジェクトが更新されるたびにARFrameオブジェクトを取り出す。
   guard let frame = sceneView.session.currentFrame else { return }
   DispatchQueue.main.async {
  // ワールドマッピングステータスが mapped のときだけ保存ボタンを有効にする
  if frame.worldMappingStatus == .mapped {
    ここで保存を実行するボタンをアクティブとかにしてみる
  }
 }
}

参考

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?