ARKit教程05_第三章: Session Management基礎(chǔ)

前言

對(duì)ARKit感興趣的同學(xué),可以訂閱ARKit教程專題
源代碼地址在這里

正文

在本章中,我們將了解AR session是什么以及如何管理它。這包括啟動(dòng),停止和重置。還將學(xué)習(xí)如何處理會(huì)話錯(cuò)誤并跟蹤典型AR應(yīng)用程序生命周期中可能發(fā)生的問題。

準(zhǔn)備工作

我們需要在上一個(gè)項(xiàng)目的基礎(chǔ)之上添加一些可交互的事件,我們需要在ViewController.swift添加一些UI控件和一些事件方法:

 // MARK: - Outlets
@IBOutlet var sceneView: ARSCNView!
@IBOutlet weak var statusLabel: UILabel!
@IBOutlet weak var startButton: UIButton!
@IBOutlet weak var styleButton: UIButton!
@IBOutlet weak var resetButton: UIButton!

// MARK: - Actions
@IBAction func startButtonPressed(_ sender: Any) {
}

@IBAction func styleButtonPressed(_ sender: Any) {
}

@IBAction func resetButtonPressed(_ sender: Any) {
}

創(chuàng)建一個(gè) AR session

我們之前在Main.storyboard中添加的ARSCNView是一個(gè)很基本的SceneKit view。它包括一個(gè)ARSession對(duì)象,該對(duì)象負(fù)責(zé)處理ARKit的運(yùn)動(dòng)追蹤和圖像處理工作。需要注意的是,ARSession對(duì)象是基于會(huì)話來(lái)進(jìn)行工作的,也就是說(shuō),你需要先創(chuàng)建一個(gè)AR session實(shí)例,然后運(yùn)行它,才可以啟動(dòng)AR的追蹤過程。

創(chuàng)建con?guration

在啟動(dòng)AR session,之前,必須創(chuàng)建AR session con?guration (AR 會(huì)話配置)。此配置用于在真實(shí)世界(設(shè)備所在的位置)和虛擬 3D 世界(虛擬內(nèi)容所在的位置)之間建立連接。

有兩種類型的配置:

  • AROrientationTrackingConfiguration, 用于三個(gè)自由度跟蹤, 簡(jiǎn)稱3DOF。
  • ARWorldTrackingConfiguration,用于六個(gè)自由度跟蹤, 簡(jiǎn)稱 6DOF。

3DOF

3DOF跟蹤設(shè)備旋轉(zhuǎn),分為Pitch(俯仰)、Roll(滾動(dòng))和 Yaw(偏航) 組件,表示圍繞X 軸、Y 軸和 Z 軸的旋轉(zhuǎn)。這由 AR 定向跟蹤配置會(huì)話配置類型支持。

6DOF

6DOF 跟蹤Pitch、RollYaw,類似于 3DOF。它還使用 Sway、HeaveSurge 組件跟蹤 3D 空間中的設(shè)備移動(dòng)。這些新組件表示與 X 軸、Y 軸和 Z 軸平行的移動(dòng)。這由 ARWorldTrack 配置會(huì)話配置類型支持。

檢查設(shè)備功能

您正在創(chuàng)建 AR 應(yīng)用程序需要 6DF 跟蹤,因此你將使用 ARWorldTrackingConfiguration對(duì)象。良好的編碼實(shí)踐是檢查設(shè)備是否能夠支持此功能。

為此,在 initARSession() 中添加以下內(nèi)容:

guard ARWorldTrackingConfiguration.isSupported else { print("*** ARConfig: AR World Tracking Not Supported") return }

可以使用 類的isSupported屬性來(lái)檢查設(shè)備是否支持該配置。如果不是,這是一個(gè)偉大的地方,通知用戶適當(dāng)?shù)南?。以機(jī)智的方式向用戶提供壞消息總是一個(gè)好主意。

現(xiàn)在您知道設(shè)備支持 6DOF,可以創(chuàng)建配置對(duì)象。

將以下內(nèi)容添加到 initARSession() 的底部:

// 1
let config = ARWorldTrackingConfiguration()
// 2 
config.worldAlignment = .gravity 
// 3 
config.providesAudioData = false

上面的代碼主要功能如下:

    1. 首先,創(chuàng)建一個(gè) ARWorldTrackingConfiguration配置實(shí)例, 該實(shí)例已分配給config
    1. 設(shè)置worldAlignment屬性,用于指定虛擬內(nèi)容與真實(shí)世界的關(guān)系。這里有三個(gè)選項(xiàng):
      ?a) gravity: 這將設(shè)置虛擬內(nèi)容坐標(biāo)系的 Y 軸,與地球引力平行。這可確保 Y 軸始終在實(shí)際空間中向上指向。它還使用設(shè)備的初始位置作為坐標(biāo)系源,稱為世界原點(diǎn)。這是 AR 會(huì)話開始時(shí)設(shè)備在真實(shí)世界中的位置。
      ?b) gravityAndHeading:這還會(huì)設(shè)置虛擬內(nèi)容坐標(biāo)系的 Y 軸,與重力平行。它還定向 X 軸,使其從西向東運(yùn)行,并且 Z 軸,以便從北到南運(yùn)行:
      ?最后,它還使用設(shè)備的初始位置作為世界起源。例如,你可以使用它將用戶指向真實(shí)世界的指南針方向。
      ?c)camera:這將使用設(shè)備方向和 3D 空間中的位置作為世界原點(diǎn)。例如,用戶可以在啟動(dòng) AR 會(huì)話之前將其設(shè)備放在墻上。
    1. 通過將providesAudioData設(shè)置為false來(lái)禁用該功能。此屬性允許 AR 會(huì)話捕獲音頻。
    1. 這里還有一個(gè)其他的屬性,isLightEstimationEnabled。在后面的章節(jié)中你會(huì)了解它的。

運(yùn)行session

現(xiàn)在已經(jīng)創(chuàng)建了 AR 配置,剩下的唯一事情就是啟動(dòng) AR 會(huì)話。

initARSession() 方法中添加以下內(nèi)容:

sceneView.session.run(config)

在 ARSCNView 的 ARSession 上調(diào)用run(_:options:),傳入剛剛創(chuàng)建的 ARWorldTrackingConfiguration。就是這個(gè),你的AR session現(xiàn)在啟動(dòng)并運(yùn)行,并且它正在積極收集6DOF跟蹤數(shù)據(jù)。

操控AR session

盡管 AR session已啟動(dòng)并運(yùn)行,但它不是你可以啟動(dòng)和忽略的內(nèi)容??赡苄枰鶕?jù)應(yīng)用中發(fā)生的情況控制其行為。 其實(shí),控制 AR session是非常簡(jiǎn)單的。

  • PausingARSession.pause()暫停AR session追蹤。在用戶切換到另一個(gè)應(yīng)用程序時(shí),可以很好地使用會(huì)話。

  • ResumingARSession.run() 將恢復(fù)暫停的會(huì)話。它將利用現(xiàn)有的跟蹤配置來(lái)恢復(fù)追蹤過程。

  • UpdatingARSession.run(ARSessionConfig)用于更新對(duì)配置的更改。也許你確實(shí)希望啟用音頻采樣,但僅當(dāng)用戶按下按鈕時(shí)。首先從活動(dòng)運(yùn)行的會(huì)話獲取配置,調(diào)整其屬性,然后使用已更改的配置重新運(yùn)行會(huì)話。

  • ResettingARSession.run(_:options:)在異常情況下很有用,并且別無(wú)選擇,只能重新啟動(dòng) AR session。有可能用戶長(zhǎng)時(shí)間關(guān)閉設(shè)備,這將使任何以前收集的跟蹤信息毫無(wú)意義。

更新狀態(tài)信息

我們可以把AR session的實(shí)時(shí)狀態(tài)顯示到屏幕上,我們可以添加一個(gè)對(duì)象:var trackingStatus: String = ""。然后添加如下代碼:

func renderer(_ renderer: SCNSceneRenderer,
 updateAtTime time: TimeInterval) { 
 DispatchQueue.main.async { 
     self.statusLabel.text = self.trackingStatus
     } 
}

AR session錯(cuò)誤處理

我們可以通過ARSessionDelegate來(lái)得知AR session的一些問題。

@protocol ARSessionDelegate <ARSessionObserver>
ARSessionDelegate && ARSessionObserver

我們可以作如下操作:

extension ViewController : ARSCNViewDelegate {
// MARK: - SceneKit Management
func renderer(_ renderer: SCNSceneRenderer,
              updateAtTime time: TimeInterval) {
    DispatchQueue.main.async {
        self.statusLabel.text = self.trackingStatus
    }
}

// MARK: - Session State Management
func session(_ session: ARSession,
             cameraDidChangeTrackingState camera: ARCamera) {
    switch camera.trackingState {
    // 1
    case .notAvailable:
        trackingStatus = "Tacking:  Not available!"
    // 2
    case .normal:
        trackingStatus = "Tracking: All Good!"
    // 3
    case .limited(let reason):
        switch reason {
        case .excessiveMotion:
            trackingStatus = "Tracking: Limited due to excessive motion!"
        // 3.1
        case .insufficientFeatures:
            trackingStatus = "Tracking: Limited due to insufficient features!"
        // 3.2
        case .initializing:
            trackingStatus = "Tracking: Initializing..."
        // 3.3
        case .relocalizing:
            trackingStatus = "Tracking: Relocalizing..."
        }
    }
}

// MARK: - Session Error Managent
func session(_ session: ARSession,
             didFailWithError error: Error) {
    trackingStatus = "AR Session Failure: \(error)"
}

func sessionWasInterrupted(_ session: ARSession) {
    trackingStatus = "AR Session Was Interrupted!"
}

func sessionInterruptionEnded(_ session: ARSession) {
    trackingStatus = "AR Session Interruption Ended"
}
// MARK: - Plane Management
}

想必大部分的代碼你們可以看得很明白,不過需要解釋的是ARCamera.trackingStatus

    1. notAvailable: 由于不可預(yù)見的原因,AR session無(wú)法跟蹤。在這種情況下,你沒有什么可以做的,只是希望狀態(tài)改變到更可控的狀態(tài)。
    1. normalAR session 處于正常狀態(tài)。

顯示Debug選項(xiàng)

顯示Debug選項(xiàng)也不難,sceneView有一個(gè)debugOptions選項(xiàng),該選項(xiàng)決定了你想要顯示哪些Debug信息。

sceneView.debugOptions = []

下面是相關(guān)的文檔信息:

public struct SCNDebugOptions : OptionSet {

public init(rawValue: UInt)


public static var showPhysicsShapes: SCNDebugOptions { get } //show physics shape

public static var showBoundingBoxes: SCNDebugOptions { get } //show object bounding boxes

public static var showLightInfluences: SCNDebugOptions { get } //show objects's light influences

public static var showLightExtents: SCNDebugOptions { get } //show light extents

public static var showPhysicsFields: SCNDebugOptions { get } //show SCNPhysicsFields forces and extents

public static var showWireframe: SCNDebugOptions { get } //show wireframe on top of objects

@available(iOS 11.0, *)
public static var renderAsWireframe: SCNDebugOptions { get } //render objects as wireframe

@available(iOS 11.0, *)
public static var showSkeletons: SCNDebugOptions { get } //show skinning bones

@available(iOS 11.0, *)
public static var showCreases: SCNDebugOptions { get } //show subdivision creases

@available(iOS 11.0, *)
public static var showConstraints: SCNDebugOptions { get } //show slider constraint

@available(iOS 11.0, *)
public static var showCameras: SCNDebugOptions { get } //show cameras
}

你們可以自己試著加一下。例如,我們做如下設(shè)置:

sceneView.debugOptions = [
        SCNDebugOptions.showFeaturePoints,
        SCNDebugOptions.showWorldOrigin,
        SCNDebugOptions.showBoundingBoxes,
        SCNDebugOptions.showWireframe
    ]

呈現(xiàn)的效果如下:

  • Feature points: 這些是你整個(gè)場(chǎng)景中看到的小點(diǎn);它們代表了 ARKit 在攝像機(jī)圖像中檢測(cè)到的顯著功能,這些功能又用作地標(biāo),以在設(shè)備移動(dòng)時(shí)準(zhǔn)確跟蹤設(shè)備的位置和方向。

  • World origin: 這是紅色、綠色和藍(lán)色線的大交叉點(diǎn),位于開始AR session的位置。紅線表示正 X 軸,綠線表示正 Y 軸,藍(lán)線表示正 Z 軸。

  • Bounding boxes: 這些是所有 3D 對(duì)象周圍的框狀輪廓。

  • Wireframe: 需要注意的是,你現(xiàn)在可以在 AR 場(chǎng)景中每個(gè) 3D 對(duì)象的曲面上看到多邊形的輪廓。你可以精確查看這些幾何形狀的詳細(xì)程度。

上一章 目錄 下一章
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容