4

I want to get the degree of Rotation of all three axis. I am trying to achieve with landscape mode. When rotate device from left to right (Y-rotation), I want the degree covered once user set a left end and rotatae to right. So we need the degree 360 when it reached the starting point. So for the y-rotation, using the following calculation and it is fine.

let q = sceneView.pointOfView.orientation
let yRotation = Float.pi - atan2f( (2*q.y*q.w)-(2*q.x*q.z), 1-(2*pow(q.y,2))-(2*pow(q.z,2)) )

Ref: Getting the rotation of device around the world origin's y axis in ARKit

Similarly, want the Z-rotation, for Z-rotation , no need for 360 degree rotation. But need accurate value when rotate about upto 90 degree This is fine if we use the

var zRotation = sceneView.pointOfView.eulerAngles.z

But this will be wrong* if we rotate the device on left to right (Y-direction ) some degree and then check the Z rotation, we will get the Z-rotation values as near to 180 degree rather than near to 0

So tried a bad way to get the Z rotation like:

var zRotation = sceneView.pointOfView.eulerAngles.z
if abs(sceneView.pointOfVieweulerAngles.z.toDegree) > 90 {
    zRotation = (abs(cameraNode.eulerAngles.z.toDegree) - 180).toRadian
}

But this is not accurate, we can see a jumb the Z-rotation value when subtracting 180.

Could you suggest a proper method..

X-rotation value is simialr to Z-rotation, getting values near to 180 when check after rotate left to right (Y-rotation) some degree.

Thanks

Edited: Sep 3, 2109 For x and y, Now I am using

let xRotation = sceneView!.session.currentFrame!.camera.eulerAngles.x
let zRotation = sceneView!.session.currentFrame!.camera.eulerAngles.z
jpulikkottil
  • 666
  • 9
  • 24
  • please comment if my question need more clarification or details – jpulikkottil Aug 29 '19 at 06:19
  • 1
    What you are confronting is an issue called Gimble Lock (https://en.wikipedia.org/wiki/Gimbal_lock), which is an inherent fundamental problem with Euler Angles (https://en.wikipedia.org/wiki/Euler_angles), which you are using. It is for this reason that everything under the hood in 3D graphics uses Quaternions (https://en.wikipedia.org/wiki/Quaternion) for angle of rotation. What is the specific use case? -- Perhaps I can suggest an alternate solution. – drewster Sep 03 '19 at 17:03
  • I am trying to capture a panorama video. Left to right and bottom-top directions. When taking left-right (Y)rotation, I want to know the exact Z-rotation and X-Rotation angles to validate and to centering frame as per AR object – jpulikkottil Sep 03 '19 at 17:51
  • Do you plan to capture more than one horizontal strip? Or just a single horizontal strip (left to right), and you just want to check the up/down pivot to make sure the phone is being held level? – drewster Sep 03 '19 at 19:20
  • Yes, I want to capture multiple horizontal and vertical footages. And to make sure how much deviations is there. In left-right footage, I want to know the X and Z-rotation value for each frame. And for bottom-top footage, I want to know the Y and Z-rotation value for each frame. – jpulikkottil Sep 04 '19 at 04:11

1 Answers1

2

If you disable the landscape orientation (left & right), you will get pretty good data for x, y and z rotation.

if let q = self?.sceneView.pointOfView?.orientation {

            let heading = atan2f( (2 * q.y * q.w) - (2 * q.x * q.z), 1 - (2 * pow(q.y,2)) - (2 * pow(q.z,2)) )
            let attitude = asinf( (2 * q.x * q.y) + (2 * q.z * q.w) )
            let bank = atan2f( (2 * q.x * q.w) - (2 * q.y * q.z), 1 - (2 * pow(q.x,2)) - (2 * pow(q.z,2)) )

            print("X: \(attitude * (180.0 / .pi)) Y: \(heading * (180.0 / .pi)) Z: \(bank * (180.0 / .pi))")

    }

If you allow Landscape Orientation then you will get different values. Once the device goes from Portrait to Landscape, you will get rotation data as if the whole coordinate space has been rotated by pi/2 radians. Then you have to tweak the data (Add or Substract pi/2) to get correct values. Is there a way to convert the coordinate system after a change to Landscape Orientation?

So if you don't want your device window to rotate with orientation, disselect the Landscape mode. Though you can get all orientation info to perform any UI changes:

if UIDevice.current.orientation == UIDeviceOrientation.faceUp {
                print("faceUp")
            } else if UIDevice.current.orientation == UIDeviceOrientation.landscapeRight {
                print("landscapeRight")
            } else if UIDevice.current.orientation == UIDeviceOrientation.portrait {
                print("portrait")
            } else if UIDevice.current.orientation == UIDeviceOrientation.portraitUpsideDown {
                print("portraitUpsideDown")
            }
Amyth
  • 383
  • 3
  • 9
  • I am intializing the AR only with Landscape mode (and need the rotated degrees with landscape mode) , So the above solution doesn't fit for my case. – jpulikkottil Sep 13 '19 at 13:19