The object can't rotate around z axis in SceneKit

I am doing an app with a functionality like a 3D compass, it can point to the direction where I want. The code is

extension AR: CLLocationManagerDelegate{

motionManager.deviceMotionUpdateInterval = 1.0/60.0
if motionManager.isDeviceMotionAvailable {
motionManager.startDeviceMotionUpdates(to: OperationQueue.main, withHandler: { (devMotion, error) -> Void in

})}

}


}

func orient(q:CMQuaternion,angle:Float) -> SCNQuaternion{
let gq1: GLKQuaternion = GLKQuaternionMakeWithAngleAndAxis(GLKMathDegreesToRadians(-angle), 0, 0, 1)
// add a rotation in z axis
let gq2: GLKQuaternion = GLKQuaternionMake(Float(q.x), Float(q.y), Float(q.z), Float(q.w))
// the current orientation
let qp: GLKQuaternion = GLKQuaternionMultiply(gq1, gq2)
// get the "new" orientation
var rq = CMQuaternion()
rq.x = Double(qp.x)
rq.y = Double(qp.y)
rq.z = Double(qp.z)
rq.w = Double(qp.w)
return SCNQuaternion(Float(rq.x), Float(rq.y), Float(rq.z), -Float(rq.w))
}


At first I got the device's orientation to apply to my object ("node") in z axis so that it can point to the right direction. However, I figure out there is gimbal lock coming. When I rotate the device in x & y axis, the object can rotate in x & y axis as well. But if I rotate the device in z axis, there are two situations:

one, the device is holding up, the object still rotates in y axis (Seems rotation in z axis disappears).

two, the device is lying down, the object rotates in z axis.

How can I avoid first situation?

• You literally tagged the question with "quaternion", so you probably have your answer... Feb 20, 2017 at 8:43
• Actually none of them in my mind works... Now I have totally no idea about it. Did I do wrong quaternion calculation? Feb 20, 2017 at 8:46
• Do you rotate the quaternion or do you create a new one every frame? Feb 20, 2017 at 8:51
• I make a new quaternion(let's call it rotation quaternion) which rotates around z axis and then I multiply with another quaternion( get from iPhone's sensor, let's call it sensor quaternion) to get the desire quaternion. Since I set motionManager.deviceMotionUpdateInterval = 1.0/60.0, I believe the three quaternions (rotation quaternion, sensor quaternion, desire quaternion) will change continuously so that the object can point to the right direction at any time. Feb 20, 2017 at 9:19