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) {
}
ARKit教程05_第三章: Session Management基础_第1张图片

创建一个 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 配置会话配置类型支持。

ARKit教程05_第三章: Session Management基础_第2张图片

检查设备功能

您正在创建 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 
ARKit教程05_第三章: Session Management基础_第3张图片
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 对象的曲面上看到多边形的轮廓。你可以精确查看这些几何形状的详细程度。

上一章 目录 下一章

你可能感兴趣的:(ARKit教程05_第三章: Session Management基础)