出于效率原因,我的后端使用Euler旋转 (万向节锁不是一个因素,所以请不要评论它)。
如果给定数据提供四元数,我怎么能将其转换为准确的Euler?
我见过的大多数方法都使用asin作为Y轴,但是建议的方法是使用3 atan2函数来提高准确度。
另外我应该提一下,我按照OpenGL术语进行轴表示,其中Z是您的监视器深度,关系式:
{ X: width, Y: height, Z: depth }
因此,如果您提供示例代码,请提供以下内容:
{ X: pitch, Y: yaw, Z: roll }
答案 0 :(得分:1)
这个概念并非微不足道,而是寻求开源。在您之前,有很多人已经实现了这一点: Quaternion.java 行:289,toAngles。事实上,它主要是数学应该可以很容易地转换为您的偏好语言。角度也恰好按照你要求的顺序(俯仰,偏航,滚动)
public float[] toAngles(float[] angles) {
if (angles == null) {
angles = new float[3];
} else if (angles.length != 3) {
throw new IllegalArgumentException("Angles array must have three elements");
}
float sqw = w * w;
float sqx = x * x;
float sqy = y * y;
float sqz = z * z;
float unit = sqx + sqy + sqz + sqw; // if normalized is one, otherwise
// is correction factor
float test = x * y + z * w;
if (test > 0.499 * unit) { // singularity at north pole
angles[1] = 2 * FastMath.atan2(x, w);
angles[2] = FastMath.HALF_PI;
angles[0] = 0;
} else if (test < -0.499 * unit) { // singularity at south pole
angles[1] = -2 * FastMath.atan2(x, w);
angles[2] = -FastMath.HALF_PI;
angles[0] = 0;
} else {
angles[1] = FastMath.atan2(2 * y * w - 2 * x * z, sqx - sqy - sqz + sqw); // roll or heading
angles[2] = FastMath.asin(2 * test / unit); // pitch or attitude
angles[0] = FastMath.atan2(2 * x * w - 2 * y * z, -sqx + sqy - sqz + sqw); // yaw or bank
}
return angles;
}