ARKit教程05_第三章: Session Management基础

前言

ARKit感兴趣的同学,可以订阅ARKit教程专题
源代码地址在这里

正文

在本章中,我们将了解AR session是什么以及如何管理它。这包括启动,停止和重置。还将学习如何处理会话错误并跟踪典型AR应用程序生命周期中可能发生的问题。

准备工作

我们需要在上一个项目的基础之上添加一些可交互的事件,我们需要在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) {
}

创建一个 AR session

我们之前在Main.storyboard中添加的ARSCNView是一个很基本的SceneKit view。它包括一个ARSession对象,该对象负责处理ARKit的运动追踪和图像处理工作。需要注意的是,ARSession对象是基于会话来进行工作的,也就是说,你需要先创建一个AR session实例,然后运行它,才可以启动AR的追踪过程。

创建configuration

在启动AR session,之前,必须创建AR session configuration (AR 会话配置)。此配置用于在真实世界(设备所在的位置)和虚拟 3D 世界(虚拟内容所在的位置)之间建立连接。

有两种类型的配置:

  • AROrientationTrackingConfiguration, 用于三个自由度跟踪, 简称3DOF
  • ARWorldTrackingConfiguration,用于六个自由度跟踪, 简称 6DOF

3DOF

3DOF跟踪设备旋转,分为Pitch(俯仰)、Roll(滚动)和 Yaw(偏航) 组件,表示围绕X 轴、Y 轴和 Z 轴的旋转。这由 AR 定向跟踪配置会话配置类型支持。

6DOF

6DOF 跟踪PitchRollYaw,类似于 3DOF。它还使用 SwayHeaveSurge 组件跟踪 3D 空间中的设备移动。这些新组件表示与 X 轴、Y 轴和 Z 轴平行的移动。这由 ARWorldTrack 配置会话配置类型支持。

检查设备功能

您正在创建 AR 应用程序需要 6DF 跟踪,因此你将使用 ARWorldTrackingConfiguration对象。良好的编码实践是检查设备是否能够支持此功能。

为此,在 initARSession() 中添加以下内容:

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

可以使用 类的isSupported属性来检查设备是否支持该配置。如果不是,这是一个伟大的地方,通知用户适当的消息。以机智的方式向用户提供坏消息总是一个好主意。

现在您知道设备支持 6DOF,可以创建配置对象。

将以下内容添加到 initARSession() 的底部:

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

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

    1. 首先,创建一个 ARWorldTrackingConfiguration配置实例, 该实例已分配给config
    1. 设置worldAlignment属性,用于指定虚拟内容与真实世界的关系。这里有三个选项:
       a) gravity: 这将设置虚拟内容坐标系的 Y 轴,与地球引力平行。这可确保 Y 轴始终在实际空间中向上指向。它还使用设备的初始位置作为坐标系源,称为世界原点。这是 AR 会话开始时设备在真实世界中的位置。
       b) gravityAndHeading:这还会设置虚拟内容坐标系的 Y 轴,与重力平行。它还定向 X 轴,使其从西向东运行,并且 Z 轴,以便从北到南运行:
       最后,它还使用设备的初始位置作为世界起源。例如,你可以使用它将用户指向真实世界的指南针方向。
       c)camera:这将使用设备方向和 3D 空间中的位置作为世界原点。例如,用户可以在启动 AR 会话之前将其设备放在墙上。
    1. 通过将providesAudioData设置为false来禁用该功能。此属性允许 AR 会话捕获音频。
    1. 这里还有一个其他的属性,isLightEstimationEnabled。在后面的章节中你会了解它的。

运行session

现在已经创建了 AR 配置,剩下的唯一事情就是启动 AR 会话。

initARSession() 方法中添加以下内容:

sceneView.session.run(config)

在 ARSCNView 的 ARSession 上调用run(_:options:),传入刚刚创建的 ARWorldTrackingConfiguration。就是这个,你的AR session现在启动并运行,并且它正在积极收集6DOF跟踪数据。

操控AR session

尽管 AR session已启动并运行,但它不是你可以启动和忽略的内容。可能需要根据应用中发生的情况控制其行为。 其实,控制 AR session是非常简单的。

  • PausingARSession.pause()暂停AR session追踪。在用户切换到另一个应用程序时,可以很好地使用会话。

  • ResumingARSession.run() 将恢复暂停的会话。它将利用现有的跟踪配置来恢复追踪过程。

  • UpdatingARSession.run(ARSessionConfig)用于更新对配置的更改。也许你确实希望启用音频采样,但仅当用户按下按钮时。首先从活动运行的会话获取配置,调整其属性,然后使用已更改的配置重新运行会话。

  • ResettingARSession.run(_:options:)在异常情况下很有用,并且别无选择,只能重新启动 AR session。有可能用户长时间关闭设备,这将使任何以前收集的跟踪信息毫无意义。

更新状态信息

我们可以把AR session的实时状态显示到屏幕上,我们可以添加一个对象: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: 由于不可预见的原因,AR session无法跟踪。在这种情况下,你没有什么可以做的,只是希望状态改变到更可控的状态。
    1. normalAR session 处于正常状态。

显示Debug选项

显示Debug选项也不难,sceneView有一个debugOptions选项,该选项决定了你想要显示哪些Debug信息。

sceneView.debugOptions = []

下面是相关的文档信息:

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
}

你们可以自己试着加一下。例如,我们做如下设置:

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

呈现的效果如下:

  • Feature points: 这些是你整个场景中看到的小点;它们代表了 ARKit 在摄像机图像中检测到的显著功能,这些功能又用作地标,以在设备移动时准确跟踪设备的位置和方向。

  • World origin: 这是红色、绿色和蓝色线的大交叉点,位于开始AR session的位置。红线表示正 X 轴,绿线表示正 Y 轴,蓝线表示正 Z 轴。

  • Bounding boxes: 这些是所有 3D 对象周围的框状轮廓。

  • Wireframe: 需要注意的是,你现在可以在 AR 场景中每个 3D 对象的曲面上看到多边形的轮廓。你可以精确查看这些几何形状的详细程度。

上一章 目录 下一章
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352

推荐阅读更多精彩内容