iOS ARKit - 计算设备在三个方向上的旋转角度

4

我希望获取所有三个轴的旋转角度。我试图在横屏模式下实现这一点。 当设备从左侧旋转到右侧(Y-旋转)时,我希望当用户设置一个左端并向右旋转时,度数只覆盖一次。因此,当达到起始点时,我们需要度数360。因此,对于y-旋转,使用以下计算即可。

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)) )

参考:在ARKit中获取设备围绕世界原点Y轴的旋转角度

同样,想要Z轴旋转角度,对于Z轴旋转,不需要360度旋转。但需要在旋转约90度时获得精确值。 如果我们使用

var zRotation = sceneView.pointOfView.eulerAngles.z

如果我们将设备向左或向右(Y方向)旋转一定角度,然后检查Z轴旋转角度,那么如果仅仅使用原来的方法,则会出现错误,Z轴旋转角度应该接近180度而不是0度。
所以我尝试了一种不好的方法来获取Z轴的旋转角度:
var zRotation = sceneView.pointOfView.eulerAngles.z
if abs(sceneView.pointOfVieweulerAngles.z.toDegree) > 90 {
    zRotation = (abs(cameraNode.eulerAngles.z.toDegree) - 180).toRadian
}

但这并不准确,我们可以看到当减去180时,Z旋转值出现跳跃。

你能建议一个合适的方法吗?

X旋转值类似于Z旋转,在左右(Y旋转)旋转一定度数后检查时,获取接近180的值。

谢谢。

更新:2019年9月3日 对于X和Y,我现在正在使用

let xRotation = sceneView!.session.currentFrame!.camera.eulerAngles.x
let zRotation = sceneView!.session.currentFrame!.camera.eulerAngles.z

请翻译以下与编程有关的内容,从英文到中文。仅返回翻译的文本:如果我的问题需要更多澄清或细节,请留言。 - jpulikkottil
1
你面临的问题被称为万向节锁定(Gimbal Lock)(https://en.wikipedia.org/wiki/Gimbal_lock),这是使用欧拉角(https://en.wikipedia.org/wiki/Euler_angles)时固有的基本问题。正因为如此,在3D图形的底层中,一切都使用四元数(https://en.wikipedia.org/wiki/Quaternion)来表示旋转角度。具体用途是什么?也许我可以提供替代方案。 - drewster
我正在尝试捕捉全景视频。从左到右和从下到上的方向。在进行左右(Y)旋转时,我想知道确切的Z旋转和X旋转角度,以验证并根据AR对象居中帧。 - jpulikkottil
你计划捕捉多个水平条带吗?还是只捕捉单个水平条带(从左到右),并且只想检查上下枢轴以确保手机保持水平? - drewster
是的,我想捕捉多个水平和垂直镜头,并确保有多少偏差。在左右镜头中,我想知道每帧的X和Z旋转值。对于底部-顶部镜头,我想知道每帧的Y和Z旋转值。 - jpulikkottil
1个回答

2
如果禁用横向方向(左右),您将获得相当不错的x、y和z旋转数据。
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))")

    }

如果允许横屏方向,您将获得不同的值。一旦设备从纵向变为横向,您将获得旋转数据,就好像整个坐标空间已经被旋转了π/2弧度。然后,您需要调整数据(加或减π/2)以获得正确的值。如何在更改为横屏方向后转换坐标系统? 如果您不希望设备窗口随着方向旋转,请取消选择横屏模式。尽管您可以获取所有方向信息来执行任何UI更改:
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")
            }

我只使用横向模式初始化AR(并需要横向模式下的旋转度数),因此上述解决方案不适用于我的情况。 - jpulikkottil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接