为什么CMMotionManager停止重启后偏航报错?

Why does CMMotionManager report incorrect yaw after stopping and restarting?

我正在使用 CMMotionManager 获取设备姿态,运行 遇到一个奇怪的问题,它在第一次启动时运行良好,但在停止和启动后,偏航值增加了一倍。

我使用 startDeviceMotionUpdates(using: .xTrueNorthZVertical) 启动它并检查 SceneKit 场景的渲染循环中的偏航值。如果我将 phone 平放在 table 上并将其旋转 90°,它会显示偏航角发生 90° 的变化。完美。

如果我使用 stopDeviceMotionUpdates() 停止它,再次启动它并执行相同的 90° 旋转,我希望看到相同的 90° 变化。但相反,它显示了 180° 的旋转!

这似乎只有在第一次使用 (using:) 语法启动时才会发生。我正在 iPhone 5 和 iOS 10.0.2 上使用 xCode 8.0.

对其进行测试

要重新创建,请使用 "Game" 模板创建一个新项目,并将 GameViewController.swift 中的代码替换为以下代码:

import UIKit
import SceneKit
import CoreMotion

class GameViewController: UIViewController, SCNSceneRendererDelegate {

    static let motionManager = CMMotionManager()

    var scnView: SCNView!
    var scnScene: SCNScene!

    override func viewDidLoad() {
        super.viewDidLoad()
        scnView = self.view as! SCNView
        scnView.delegate = self
        scnScene = SCNScene()
        scnView.scene = scnScene
        scnView.isPlaying = true

        GameViewController.motionManager.startDeviceMotionUpdates(using: .xTrueNorthZVertical)
        // stop and start it again to cause doubling
        GameViewController.motionManager.stopDeviceMotionUpdates()
        GameViewController.motionManager.startDeviceMotionUpdates(using: .xTrueNorthZVertical)

    }

    func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
        if let motion = GameViewController.motionManager.deviceMotion {
            print(Int(motion.attitude.yaw * 180/M_PI))
        }
    }
}

此代码启动 CMMotionManger,然后立即停止并再次启动。将 phone 旋转 90°,您会看到它显示 180° 偏航。显然这不是一个实际的例子,只是一个显示问题的简化版本。在我的实际用例中,当我在其中使用它的 SceneKit 视图被关闭时,我会停止 CMMotionManager,并在打开另一个 SceneKit 视图时重新启动它。

目前我的解决方法是一旦启动 CMMotionManager 就永远不要停止它。它有效,但文档特别说明 "You must call stopDeviceMotionUpdates() when you no longer want your app to process device-motion updates.",因此这似乎不是一个很好的解决方案。

为什么 CMMotionManager 在停止和启动后给出错误的值,我该如何解决?

CMMotion manager 给出调用start函数时的转角。

如果您需要更新,那么您不应该停止更新。当不需要关联之前的位置时停止它

此行为在安装 iOS 10.1 后消失,因此推测这是一个已修复的错误。