目次
Session概要
ARKit 4は、人々とその身の周りの世界とのつながり方を一変させる次世代の拡張現実アプリの構築を可能にします。バーチャルオブジェクトと実世界の緯度経度、及び高度とをつなぐロケーションアンカーの使い方を含め、Appleの拡張現実プラットフォームにおける最新の改善点をご紹介します。iPad ProのLiDARスキャナを利用し、周囲環境の深度マップを手に入れる方法や、iPad Air(第3世代)、iPad mini(第5世代)を含め、その他のA12 Bionic以降のチップを搭載したフロントカメラ付きのすべてのデバイスでのARにおけるフェイストラッキングの方法もお伝えします。 https://developer.apple.com/videos/play/wwdc2020/10611/ARKit 4での新機能
これまでの機能
- ARKitでのトラッキングでは、QRコードも外部機器も不要で周囲にコンテンツを設置するだけ良い
- ARコンテンツの複数ユーザ体験
- ARコンテンツをソーシャル化するには、別のデバイスを通じて友人と共有します
- ARのScene内で人を把握可能
- モーションキャプチャが可能
- モーションキャプチャが可能

ロケーションアンカー API
- バーチャルコンテンツを地面との関連で配置し、ARの体験を地面まで引き上げます
- iOS 14から利用可能で、利用可能な地域も限られている
- そのため、ロケーションアンカーのみを使用するアプリの場合は、UIRequiredDeviceCapabilitiesを使用して対象ユーザを利用可能なユーザのみに制限することが可能
- 経度、緯度、高度を指定してバーチャルオブジェクトを配置可能
- 自分のジオ座標や高解像度のマップデータをApple Mapsから受け取りワールドロケーションでARコンテンツを設置できます
- このプロセス全体をビジュアルローカリゼーションと呼び、GPSで行うよりも正確に周囲の環境との関連でデバイスを見つけ出す
- ARKitはローカル座標とジオ座標系の統合も処理するため、ARコンテンツの作成方法に関係なく1つの統合システムで作業可能
- これらを利用するための、ARジオトラッキングコンフィギュレーションがある
- ARジオアンカーは他のARKit同様コンテンツに配置するために使用する

ジオトラッキングの使用
- ジオトラッキングを使う場合、現在地の詳細をApple Mapsから取得する
- ローカリゼーションマップと現在のロケーションデバイスの画像で機能学習によるデバイスロケーションを視覚的にローカライズして特定する
ロケーションアンカーAPIの構成
- ロケーションアンカーAPIは3つの部分に分かれており、
- ARGeoTrackingConfiguration
- 新しいロケーションアンカー機能の活用のためで、ジオトラッキングと互換性のあるワールドトラッキング機能が含まれている
- ジオコンフィギュレーションを使用してARセッションを開始すると、他のARKitアンカーと同様にARジオアンカーを作成できるようになる
- ARGeoAnchor
- ARGeoTrackingStatus
- ジオトラッキングの使用中に表示される新しいトラッキングステータス
- ローカライズ中のジオトラッキングとの距離を表し、デバイスとトラッキング対象との関係性をユーザに通知する
- ジオデータが読み込まれていない場合は、ネットワーク接続が必要であることを通知する
- 一般的には、建物や構造物にデバイスを向けることを推奨され、開けた場所や動的に変化する環境ではローカライズの可能性が低くなる
- ローカリゼーション前にオブジェクトを配置すると、オブジェクトが意図しない場所に移動することがある
- 追跡の紛失やマップデータが使用できない場合は初期化も行う
- ARGeoTrackingConfiguration

ロケーションアンカーを使用したアプリの構築手順
- ジオトラッキングの可用性をチェック
- ロケーションアンカーはA12 Bionicチップと新しいGPSを搭載したデバイスが必要
- ARジオグラフィックコンフィギュレーションがサポート対象のクラスメソッドで確認可能
- ジオトラッキングの場合は、現在のロケーションのサポートも確認する
- ARKitはさらにカメラとロケーションの許可をユーザに要求する
- ロケーションアンカーはA12 Bionicチップと新しいGPSを搭載したデバイスが必要
- ロケーションアンカーの追加
- ARGeoAnchorを追加する
- グローバル座標で動作するため、変換だけでは作成できない
- 経度、緯度、高度を使用してジオ座標を指定する必要がある
- バーチャルコンテンツの配置
- ジオトラッキングの移行
// 可用性の確認
// Check device support for geo-tracking
guard ARGeoTrackingConfiguration.isSupported else {
// Geo-tracking not supported on this device
return
}
// Check current location is supported for geo-tracking
ARGeoTrackingConfiguration.checkAvailability { (available, error) in
guard available else {
// Geo-tracking not supported at current location
return
}
// Run ARSession
let arView = ARView()
// ワールドロケーションを使用するため、セッション実行時にジオトラッキングコンフィギュレーションを設定する
arView.session.run(ARGeoTrackingConfiguration())
}
// Create coordinates
// マップデータを使用して標高を決定するので、高度を指定する必要はない
let coordinate = CLLocationCoordinate2D(latitude: 37.795313, longitude: -122.393792)
// Create Location Anchor
let geoAnchor = ARGeoAnchor(name: "Ferry Building", coordinate: coordinate)
// Add Location Anchor to session
arView.session.add(anchor: geoAnchor)
// Create a RealityKit anchor entity
let geoAnchorEntity = AnchorEntity(anchor: geoAnchor)
// Anchor content under the RealityKit anchor
geoAnchorEntity.addChild(generateSignEntity())
// Add the RealityKit anchor to the scene
arView.scene.addAnchor(geoAnchorEntity)
コンテンツのポジショニング
- ジオアンカーのX軸は常に東方向を向き、z軸は常に南方向を向く
- 右手座標系を使用しているため正のY軸は地面から上に向いています
- ジオアンカーは不変的であるため、レンダリングエンジンで原点からバーチャルオブジェクトを回転か変換可能
// オブジェクトの回転と高さ調整
// Create a new entity for our virtual content
let signEntity = generateSignEntity();
// Add the virtual content entity to the Geo Anchor entity
geoAnchorEntity.addChild(signEntity)
// Rotate text to face the city
let orientation = simd_quatf.init(angle: -Float.pi / 3.5, axis: SIMD3<Float>(0, 1, 0))
signEntity.setOrientation(orientation, relativeTo: geoAnchorEntity)
// Elevate text to 35 meters above ground level
let position = SIMD3<Float>(0, 35, 0)
signEntity.setPosition(position, relativeTo: geoAnchorEntity)
Scene ジオメトリ
- 新しいLiDARセンサーでSceneジオメトリを使用可能
- 物理オブジェクトの認識と分類を可能にする
- オクルージョンからライティングまで周辺環境のメッシュが提供されます
- 現実世界を隠したり、バーチャルオブジェクトと物理オブジェクト間のリアルな相互作用を実現
- 検出したメッシュデータから各表面に適した詳細を表すことができ、セマンティック分類が有効な場合は、カラーメッシュが表示される
- シートには青色、床は緑色など各色が異なる分類を表す
- Sceneジオメトリの有効化にはDepth APIを使用する

LiDARスキャナの機能
- LiDARは周囲に光を放ちシーン内の表面からの反射光を収集します
- 深度はLiDARから放射された光が反射スキャナに戻るまでの時間を測って推定する
- 深度はLiDARから放射された光が反射スキャナに戻るまでの時間を測って推定する

Depth API
- 高密度な深度画像を提供し、カメラからメートル単位の深度に画像のピクセルが対応する
- 深度のデバッグ可視化が青から赤へのグラデーションとなる
- 青はカメラに近い領域、赤は遠い領域を表す
- 深度データは各ARFrameに関連付けられた60Hzで利用可能
- このAPIはLiDARスキャナで稼働しており、LiDARを搭載したデバイスで利用可能
- 各ARFrameには深度データにアクセスするためにsceneDepthという新しいプロパティがあり、ARDepthDataのオブジェクトを表示するもの
- ARDepthDataは深度マップと信頼度マップのバッファ用コンテナ
- ARDepthDataは深度マップと信頼度マップのバッファ用コンテナ


深度マップ
- CVPixelBufferでピクセルはメートル単位での深さを表します
- この深度はカメラの平面からある地点までの距離に相当する
- ARFrame上のキャプチャ画像より深度マップの解像度は低いのに同じアスペクト比を維持している
信頼度マップ
- LiDARでの深度の計測は物体から反射する光を利用するため、深度マップは周辺環境による影響を受けるため、物体によっては精度を下げたりなど調整することが可能で、この精度は信頼度という値で表す
- 各深度ピクセルにはARConfidenceLevelに対応する信頼度があり、信頼度はアプリの要件に準じた深度のフィルタリングに役立つ
// Enabling the depth API
let session = ARSession()
let configuration = ARWorldTrackingConfiguration()
// Check if configuration and device supports .sceneDepth
// .sceneDepthという新しいframeSemanticを用いてDepth APIをオンにする
// そのため、利用可能かチェックする
if type(of: configuration).supportsFrameSemantics(.sceneDepth) {
// Activate sceneDepth
configuration.frameSemantics = .sceneDepth
}
session.run(configuration)
...
// Accessing depth data
func session(_ session: ARSession, didUpdate frame: ARFrame) {
guard let depthData = frame.sceneDepth else { return }
// Use depth data
}
// Using the depth API alongside person occlusion
let session = ARSession()
let configuration = ARWorldTrackingConfiguration()
// Set required frame semantics
// ピープルオクルージョン機能は.personSegmentationWithDepthを設定する
// アプリへの電力負荷を増やさずsceneDepthframeSemanticをサポートするデバイスに自動でsceneDepthを得られます
let semantics: ARConfiguration.FrameSemantics = .personSegmentationWithDepth
// Check if configuration and device supports the required semantics
if type(of: configuration).supportsFrameSemantics(semantics) {
// Activate .personSegmentationWithDepth
configuration.frameSemantics = semantics
}
session.run(configuration)



ARCamera上のパラメータで深度マップから3D空間へunproject(非投影)する
画像とunproject情報を元にMetalを使ってレンダリングされる
オブジェクト配置について
- ARKit 4ではLiDARスキャナがレイキャスティングを大きく改善した
- レイキャストとは
- ユーザーがタッチした画面上のポイントから透明なバーチャル線を引いて、バーチャル空間でのオブジェクト、平面等とヒットしたかどうか検知するもの
- オブジェクト配置のためにレイキャスティングは高度に最適化されており、ARアプリ内の仮想オブジェクトの正確な配置が容易になった
- オブジェクト配置はLiDARスキャナにより一層速く正確になった
- レイキャストとは
- ヒットテストはレイキャストAPIが推奨されている
- レイキャストを使用する前に、レイキャストクエリを作成する必要がある
- レイキャストクエリはレイキャスト用にレイの方向と動作を記述するもので、レイが交差できる表面のタイプを記述するレイキャストターゲットで構成されている
- レイキャストの種類
- シングルショットレイキャスト
- 1回限りの結果を返す
- 追跡型レイキャスト
- ARKitの理解が発達するに伴い、結果を更新し続ける
- ARKitの理解が発達するに伴い、結果を更新し続ける
- シングルショットレイキャスト
let session = ARSession()
hitTest(point, types: [.existingPlaneUsingGeometry,
.estimatedVerticalPlane,
.estimatedHorizontalPlane])
let query = arView.makeRaycastQuery(from: point,
allowing: .estimatedPlane,
alignment: .any)
let raycast = session.trackedRaycast(query) { results in
// result updates
}

顔追跡機能の改善
- フロントカメラのAR体験で顔を検出可能
- バーチャルコンテンツをオーバーレイして、リアルタイムで顔の表情をアニメーション化できる
- TrueDepthカメラ搭載の全デバイスでサポートされていたが、ARKit 4ではTrueDepthカメラを搭載していないデバイスにも拡張される
- ただし、A12 Bionic以上が必要
- しかし、キャプチャされた深度データはTrueDepthカメラ搭載のデバイス限定で可能
