Python 3.x 如何准确地将四元数转换为欧拉数?

Python 3.x 如何准确地将四元数转换为欧拉数?,python-3.x,opengl,Python 3.x,Opengl,出于效率原因,我的后端使用Euler旋转 (万向节锁不是一个因素,因此请不要对此发表评论) 如果给定的数据提供了一个四元数,我如何将其转换为精确的欧拉 我见过的大多数方法都使用asin表示Y轴,但有一种建议的方法是使用3个atan2函数来提高精度 此外,我还应该提到,我遵循OpenGL中关于轴表示的术语,其中Z是显示器的深度,与: { X: width, Y: height, Z: depth } 因此,如果您提供示例代码,请提供如下旋转: { X: pitch, Y: yaw, Z: rol

出于效率原因,我的后端使用Euler旋转 (万向节锁不是一个因素,因此请不要对此发表评论)

如果给定的数据提供了一个四元数,我如何将其转换为精确的欧拉

我见过的大多数方法都使用asin表示Y轴,但有一种建议的方法是使用3个atan2函数来提高精度

此外,我还应该提到,我遵循OpenGL中关于轴表示的术语,其中Z是显示器的深度,与:

{ X: width, Y: height, Z: depth }
因此,如果您提供示例代码,请提供如下旋转:

{ X: pitch, Y: yaw, Z: roll }

这一概念并不琐碎,而是着眼于开源。在您之前,有很多人已经实现了这一点: 电话号码:289,toAngles。事实上,这主要是数学,应该很容易转换为您的首选语言。角度也恰好符合您要求的顺序(俯仰、偏航、横摇)

public float[]到角(float[]角度){
如果(角度==null){
角度=新浮动[3];
}否则如果(角度.长度!=3){
抛出新的IllegalArgumentException(“角度数组必须有三个元素”);
}
浮点数sqw=w*w;
浮点数sqx=x*x;
浮点sqy=y*y;
浮点sqz=z*z;
float unit=sqx+sqy+sqz+sqw;//如果规格化为1,则为
//是修正系数
浮动试验=x*y+z*w;
如果(测试>0.499*单位){//北极奇点
角度[1]=2*FastMath.atan2(x,w);
角度[2]=FastMath.HALF_PI;
角度[0]=0;
}否则如果(测试<-0.499*单位){//南极奇点
角度[1]=-2*FastMath.atan2(x,w);
角度[2]=-FastMath.HALF_PI;
角度[0]=0;
}否则{
角度[1]=FastMath.atan2(2*y*w-2*x*z,sqx-sqy-sqz+sqw);//滚动或航向
角度[2]=FastMath.asin(2*测试/单位);//俯仰或姿态
角度[0]=FastMath.atan2(2*x*w-2*y*z,-sqx+sqy-sqz+sqw);//偏航或倾斜
}
返回角;
}

您是否尝试过atan2方法?如果是这样的话,问题是什么?不,我还没有使用C,所以你可以期待我不理解代码。。。C和数学概念有什么关系?顺便说一句,你指的是哪种代码?你需要实现这一点的方程式可以找到,例如,请不要在你的帖子中添加投票评论:下层选民倾向于投票并继续前进,所以你想看到的人早就离开了。我很欣赏手机的使用,但是如果我觉得这项工作还没有完成,那么我也会投反对票(我在这里也会投反对票,但是-3就足够了)。对“示例代码”的期望可能也没有帮助,但我只是在猜测。这个网站上有很多活跃的编辑,帮助改进帖子,他们不想感觉有很多新的工作正在为他们产生
:-)
。刚刚意识到这与BDL提供的wiki解决方案没有什么不同:不能旋转Y(显示器高度)超过90°,方向似乎不正确{X:偏航,Y:滚转,Z:俯仰}将飞机朝上放置,使其左翼朝向你。在我使用发动机期间(大约7年),我没有注意到任何此类问题。我想你也可以看看FromAngels方法,以确保Quat的构造正确。我确信你使用的引擎始终遵循它自己的标准,但它的YZX标准使事情更加混乱,这就是为什么我要求使用XYZ。其次,我的(正确的)标准(Z=监视器深度),这个方向意味着你不能向后看,但只能看你的两侧…这就是为什么我要求3个atan2函数。总之,它和这个特殊方法的任何其他版本一样好,这就是为什么我投了赞成票。
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;
}