ARKit教程05_第三章: Session Managemen
前言
对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 跟踪Pitch、Roll和 Yaw,类似于 3DOF。它还使用 Sway、Heave 和 Surge 组件跟踪 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
上面的代码主要功能如下:
- 首先,创建一个 ARWorldTrackingConfiguration配置实例, 该实例已分配给config。
- 设置worldAlignment属性,用于指定虚拟内容与真实世界的关系。这里有三个选项:
a) gravity: 这将设置虚拟内容坐标系的 Y 轴,与地球引力平行。这可确保 Y 轴始终在实际空间中向上指向。它还使用设备的初始位置作为坐标系源,称为世界原点。这是 AR 会话开始时设备在真实世界中的位置。
b) gravityAndHeading:这还会设置虚拟内容坐标系的 Y 轴,与重力平行。它还定向 X 轴,使其从西向东运行,并且 Z 轴,以便从北到南运行:
最后,它还使用设备的初始位置作为世界起源。例如,你可以使用它将用户指向真实世界的指南针方向。
c)camera:这将使用设备方向和 3D 空间中的位置作为世界原点。例如,用户可以在启动 AR 会话之前将其设备放在墙上。
- 设置worldAlignment属性,用于指定虚拟内容与真实世界的关系。这里有三个选项:
- 通过将providesAudioData设置为false来禁用该功能。此属性允许 AR 会话捕获音频。
- 这里还有一个其他的属性,isLightEstimationEnabled。在后面的章节中你会了解它的。
运行session
现在已经创建了 AR 配置,剩下的唯一事情就是启动 AR 会话。
在 initARSession() 方法中添加以下内容:
sceneView.session.run(config)
在 ARSCNView 的 ARSession 上调用run(_:options:),传入刚刚创建的 ARWorldTrackingConfiguration。就是这个,你的AR session现在启动并运行,并且它正在积极收集6DOF跟踪数据。
操控AR session
尽管 AR session已启动并运行,但它不是你可以启动和忽略的内容。可能需要根据应用中发生的情况控制其行为。 其实,控制 AR session是非常简单的。
-
Pausing:ARSession.pause()暂停AR session追踪。在用户切换到另一个应用程序时,可以很好地使用会话。
-
Resuming: ARSession.run() 将恢复暂停的会话。它将利用现有的跟踪配置来恢复追踪过程。
-
Updating: ARSession.run(ARSessionConfig)用于更新对配置的更改。也许你确实希望启用音频采样,但仅当用户按下按钮时。首先从活动运行的会话获取配置,调整其属性,然后使用已更改的配置重新运行会话。
-
Resetting: ARSession.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:
- notAvailable: 由于不可预见的原因,AR session无法跟踪。在这种情况下,你没有什么可以做的,只是希望状态改变到更可控的状态。
- normal: AR 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 对象的曲面上看到多边形的轮廓。你可以精确查看这些几何形状的详细程度。
上一章 | 目录 | 下一章 |
---|