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

前言

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

正文

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

準(zhǔn)備工作

我們需要在上一個項目的基礎(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)建一個 AR session

我們之前在Main.storyboard中添加的ARSCNView是一個很基本的SceneKit view。它包括一個ARSession對象衫哥,該對象負(fù)責(zé)處理ARKit的運動追蹤和圖像處理工作茎刚。需要注意的是,ARSession對象是基于會話來進(jìn)行工作的撤逢,也就是說膛锭,你需要先創(chuàng)建一個AR session實例,然后運行它蚊荣,才可以啟動AR的追蹤過程初狰。

創(chuàng)建con?guration

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

有兩種類型的配置:

  • AROrientationTrackingConfiguration, 用于三個自由度跟蹤, 簡稱3DOF跷究。
  • ARWorldTrackingConfiguration姓迅,用于六個自由度跟蹤, 簡稱 6DOF敲霍。

3DOF

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

6DOF

6DOF 跟蹤PitchRollYaw,類似于 3DOF扩然。它還使用 Sway艘儒、HeaveSurge 組件跟蹤 3D 空間中的設(shè)備移動。這些新組件表示與 X 軸夫偶、Y 軸和 Z 軸平行的移動界睁。這由 ARWorldTrack 配置會話配置類型支持。

檢查設(shè)備功能

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

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

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

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

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

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

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

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

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

運行session

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

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

sceneView.session.run(config)

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

操控AR session

盡管 AR session已啟動并運行,但它不是你可以啟動和忽略的內(nèi)容纱意。可能需要根據(jù)應(yīng)用中發(fā)生的情況控制其行為鲸阔。 其實,控制 AR session是非常簡單的偷霉。

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

  • ResumingARSession.run() 將恢復(fù)暫停的會話类少。它將利用現(xiàn)有的跟蹤配置來恢復(fù)追蹤過程叙身。

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

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

更新狀態(tài)信息

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

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

AR session錯誤處理

我們可以通過ARSessionDelegate來得知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無法跟蹤。在這種情況下,你沒有什么可以做的,只是希望狀態(tài)改變到更可控的狀態(tài)旁瘫。
    1. normalAR session 處于正常狀態(tài)祖凫。

顯示Debug選項

顯示Debug選項也不難,sceneView有一個debugOptions選項酬凳,該選項決定了你想要顯示哪些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: 這些是你整個場景中看到的小點;它們代表了 ARKit 在攝像機圖像中檢測到的顯著功能,這些功能又用作地標(biāo),以在設(shè)備移動時準(zhǔn)確跟蹤設(shè)備的位置和方向稠屠。

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

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

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

上一章 目錄 下一章
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市呐粘,隨后出現(xiàn)的幾起案子满俗,更是在濱河造成了極大的恐慌,老刑警劉巖作岖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件唆垃,死亡現(xiàn)場離奇詭異,居然都是意外死亡痘儡,警方通過查閱死者的電腦和手機辕万,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人渐尿,你說我怎么就攤上這事价捧。” “怎么了涡戳?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長脯倚。 經(jīng)常有香客問我渔彰,道長,這世上最難降的妖魔是什么推正? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任恍涂,我火速辦了婚禮,結(jié)果婚禮上植榕,老公的妹妹穿的比我還像新娘再沧。我一直安慰自己,他們只是感情好尊残,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布炒瘸。 她就那樣靜靜地躺著,像睡著了一般寝衫。 火紅的嫁衣襯著肌膚如雪顷扩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天慰毅,我揣著相機與錄音隘截,去河邊找鬼。 笑死汹胃,一個胖子當(dāng)著我的面吹牛婶芭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播着饥,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼犀农,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了宰掉?” 一聲冷哼從身側(cè)響起井赌,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎贵扰,沒想到半個月后仇穗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡戚绕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年纹坐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舞丛。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡耘子,死狀恐怖果漾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谷誓,我是刑警寧澤绒障,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站捍歪,受9級特大地震影響户辱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜糙臼,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一庐镐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧变逃,春花似錦必逆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至凰棉,卻和暖如春璧针,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背渊啰。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工探橱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人绘证。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓隧膏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親嚷那。 傳聞我的和親對象是個殘疾皇子胞枕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內(nèi)容