ARKit之路-ARSession执行流

版权声明:Davidwang原创文章,严禁用于任何商业途径,授权后方可转载。

  在ARSession启动后,ARKit会为其提供不间断的视频图像流、视觉计算数据流、运动传感器数据流。在AR应用运行其间,不管用户有没有操作,ARSession都在执行其命令循环,我们称之为ARSession执行流,就像打开水龙头开关,水流就会源源不断的从水管中流出,不管有没有人使用,不管水杯有没有溢出。

  在ARKit中,很多时候我们需要了解和监视特定事件的发生,以便进行相应处理。以水杯接水为例,在打开水龙头后,我们随时需要了解水杯中的水位以防止水过满溢出,现实中我们的处理方式是实时观察水杯中的水位。与水杯接水的处理方式完全一致,在ARKit中,也使用同样的方式监视ARSession的运行,通过设置一个观察者(Observer),我们就可以执行相应方法随时了解ARSession运行状态的方方面面。从技术上讲,通过采用观察者模式,ARKit已经为我们设置了这样一个观察者,这就是ARSessionObserver协议,通过遵循并执行协议中的方法,我们就能在ARsession发生特定事件时得到通知。

  ARSessionObserver协议是一个高层次的协议,可以在RealityKit、SceneKit、SpriteKit中使用,除此之处,RealityKit创建了另一个代理协议ARSessionDelegate,该协议遵循ARSessionObserver协议,并提供了额外的方法。在RealityKit中,对ARSession运行状况监视结构如下图所示。

ARKit之路-ARSession执行流_第1张图片

  扩展ARView类使其遵循ARSessionDelegate和ARSessionObserver协议后就可以很方便的获取到ARSession运行状态信息。那么通过这两个协议可以监视ARSession哪些运行状态呢?我们可以通过这两个协议提供的方法了解其功能特性,ARSessionObserver协议提供方法如下表所示。

处理类型 方法 描述
跟踪质量 session(ARSession, cameraDidChangeTrackingState: ARCamera) 设备运动跟踪状态发生变化时
中断处理 sessionWasInterrupted(ARSession) 设备运动跟踪中断
、、 sessionInterruptionEnded(ARSession) 设备运动跟踪恢复
、、 sessionShouldAttemptRelocalization(ARSession) 询问代理是否执行重定位
音频数据 session(ARSession, didOutputAudioSampleBuffer: CMSampleBuffer) 新音频数据可用
错误处理 session(ARSession, didFailWithError: Error) ARSession发生错误
协作数据 session(ARSession, didOutputCollaborationData: ARSession.CollaborationData) 协作数据可用

  ARSession执行流从AR应用启动开始会一直不间断的执行,直到使用者关闭AR应用或者遇到错误被迫退出。ARSessionDelegate协议提供的方法如下表所示。

处理类型 方法 描述
摄像头图像帧 session(ARSession, didUpdate: ARFrame) 图像帧数据更新时
虚拟内容更新 session(ARSession, didAdd: [ARAnchor]) 添加ARAnchor时
、、 session(ARSession, didUpdate: [ARAnchor]) ARAnchor更新时
、、 session(ARSession, didRemove: [ARAnchor]) 移除ARAnchor时

下面我们以错误处理为例,学习如何通过使用上述协议捕获ARSession运行状态,示例代码如代码清单2-5所示。

struct ARViewContainer: UIViewRepresentable {
    func makeUIView(context: Context) -> ARView {
        arView = ARView(frame: .zero)
        let config = ARWorldTrackingConfiguration()
        config.planeDetection = .horizontal
        arView.session.run(config, options:[ ])
        arView.session.delegate = arView
        arView.createPlane()
        return arView
    }
    func updateUIView(_ uiView: ARView, context: Context) {
    }
}

extension ARView :ARSessionDelegate{
    public func session(_ session: ARSession, didFailWithError error: Error) {
        guard let arError = error as? ARError else {return}
        let isRecoverable = (arError.code == .worldTrackingFailed)
       if isRecoverable{
            print("由于运动跟踪失败的错误可恢复")
        }
       else{
            print("错误不可恢复,失败Code =\(arError.code),错误描述:\(arError.localizedDescription)")
       }
   }
}

  使用ARSessionDelegate代理协议的第一步是使用arView.session.delegate = arView语句将ARSession代理设置为ARView;第二步扩展ARView,使其遵循ARSessionDelegate协议;第三步是执行协议的相应方法,如本例执行session(ARSession, didFailWithError: Error)方法(ARSessionDelegate协议的所有方法都是可选的,即可以执行也可以不执行),在执行的对应方法中进行事件处理。

  在上述代码清单的错误处理示例中,我们只处理由ARSession引起的错误,通过将error类型转换成ARError可以获取更多有价值的信息,如可以获取到错误码(code),错误码由ARError.Code枚举定义,包含cameraUnauthorized、fileIOFailed、insufficientFeatures等11种错误情况,通过错误码可以非常方便的区分引发错误的原因并依据该原因执行后续操作。

  ARSessionObserver和ARSessionDelegate协议中所有方法均可采用类似的方法进行处理,默认所有方法均在主队列(main queue)中执行,我们也可以在开发时指定方法执行队列。另外,需要注意的是,这两个协议中的方法执行频率并不相同,有的每帧都需要执行,有的只在需要的时候执行,而有的则可能永远都不会执行。

你可能感兴趣的:(ARKit之路)