Resetting ARKit coordinates

2019-04-29 09:44发布

问题:

I have a simple question. If I wanted to start a game and place the board right in front of me:

gameBoard!.position = SCNVector3(0, 0, -0.6)

This works until I leave the game and come back again. Can I show the game board in exact same position in front of camera or 0.6m in front of me? I might have physically moved to another position.

回答1:

If you want to reset you ARSession, you have to pause, remove all nodes and rerun your session by resetting tracking and removing anchors.

I made a reset button that does it whenever i want to reset:

@IBAction func reset(_ sender: Any) {

    sceneView.session.pause()
    sceneView.scene.rootNode.enumerateChildNodes { (node, stop) in
        node.removeFromParentNode()
    }
    sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
}

Or put it in your session was interrupted function!



回答2:

This should be possible using the option resetTracking when you call run on your ARSession again.

Example:

if let configuration = sceneView.session.configuration {
    sceneView.session.run(configuration,
                          options: .resetTracking)
}


回答3:

"This works until I leave the game and come back again."

You can't track camera position in the background. Whenever your app goes to the background and camera turns off, you're losing your position, and sessionWasInterrupted(_:) will be called.

A session is interrupted when it fails to receive camera or motion sensing data. Session interruptions occur whenever camera capture is not available—for example, when your app is in the background or there are multiple foreground apps—or when the device is too busy to process motion sensor data.



回答4:

To reset ARSession in ARKit framework is quite easy:

class ViewController: UIViewController, ARSCNViewDelegate, ARSessionDelegate {

    @IBOutlet var arView: ARSCNView!
    @IBOutlet weak var sessionInfoLabel: UILabel!

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        let configuration = ARWorldTrackingConfiguration()
        configuration.planeDetection = [.horizontal, .vertical]
        arView.session.run(configuration)
        arView.session.delegate = self
    }
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        arView.session.pause()
    }
    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        guard let planeAnchor = anchor as? ARPlaneAnchor else { 
            return 
        }
        let plane = Plane(anchor: planeAnchor, in: arView)
        node.addChildNode(plane)
    }
    func sessionInterruptionEnded(_ session: ARSession) {
        resetSessionTracking()
        sessionInfoLabel.text = "ARSession's interruption has ended" 
    }
    private func resetSessionTracking() {
        let config = ARWorldTrackingConfiguration()
        config.planeDetection = [.vertical, .horizontal]
        arView.scene.rootNode.enumerateChildNodes { (childNode, _) in
            childNode.removeFromParentNode()
        }
        arView.session.run(config, options: [.removeExistingAnchors, 
                                             .resetTracking, ])
    }
}

Hope this helps.