I'm currently working on an app that has to track yaw (rotation around z-axis). The user will have the iPhone in landscape orientation pointing to an object like a car in front of him. As the user starts walking around the object I have to track the yaw for a complete 360 rotation.
I'm currently using CoreMotion with CMQuaternion to track the rotation:
private func startDeviceMotionUpdates() {
if motionManager.isDeviceMotionAvailable {
let queue = OperationQueue()
motionManager.deviceMotionUpdateInterval = 1 / 60
motionManager.startDeviceMotionUpdates(using: .xArbitraryZVertical, to: queue, withHandler: { (motion, error) in
guard let motion = motion else { return }
let quat = motion.attitude.quaternion
let yaw = 2 * (quat.x * quat.y + quat.w * quat.z)
let yawDegrees = self.degreesFromRadians(yaw)
print(yawDegrees)
})
}
}
private func stopDeviceMotionUpdates() {
motionManager.stopDeviceMotionUpdates()
}
private func degreesFromRadians(_ radians: Double) -> Double {
return radians * 180 / .pi
}
This currently works fine as long as the roll or pitch of the device doesn't change.
What I would like to know is:
- Why does the yaw change when the roll or pitch of device changes?
- How can I accurately track the yaw around the z-axis without it being affected by change on the x and y-axis?
I've been banging my head for two weeks against this problem. I would really appreciate if someone could help me understand why this is happening and how to get around it.