Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 欧拉角到四元数,然后四元数到欧拉角_C++_Math_Rotation_Quaternions_Euler Angles - Fatal编程技术网

C++ 欧拉角到四元数,然后四元数到欧拉角

C++ 欧拉角到四元数,然后四元数到欧拉角,c++,math,rotation,quaternions,euler-angles,C++,Math,Rotation,Quaternions,Euler Angles,我使用lib glm()来测试四元数,但我有一个问题;当我将欧拉角转换为四元数,然后立即将四元数转换为欧拉角时,我的结果与初始欧拉角完全不同。这正常吗?这可能是因为轮换不是公共的吗 代码测试: #include <glm\quaternion.hpp> #include <math.h> #define PI M_PI #define RADTODEG(x) ( (x) * 180.0 / PI ) #define DEGTORAD(x) ( (x) * PI / 18

我使用lib glm()来测试四元数,但我有一个问题;当我将欧拉角转换为四元数,然后立即将四元数转换为欧拉角时,我的结果与初始欧拉角完全不同。这正常吗?这可能是因为轮换不是公共的吗

代码测试:

#include <glm\quaternion.hpp>
#include <math.h>

#define PI M_PI
#define RADTODEG(x) ( (x) * 180.0 / PI )
#define DEGTORAD(x) ( (x) * PI / 180.0 )

int         main( void )
{
    float RotX = 90.f;
    float RotY = 180.f;
    float RotZ = -270.f;

    if ( RotX || RotY || RotZ )
    {
        std::cout << "Init: x= " << RotX << ", y= " << RotY << ", z= " << RotZ << "\n";
        glm::quat key_quat(glm::detail::tvec3<float>(DEGTORAD( RotX ),
                                                     DEGTORAD( RotY ),
                                                     DEGTORAD( RotZ )));
        glm::detail::tvec3<float> v = glm::eulerAngles(key_quat);

        /*  // the result is even worse with this code here
        RotX = RADTODEG(v.x);
        RotY = RADTODEG(v.y);
        RotZ = RADTODEG(v.z);
        */

        RotX = v.x;
        RotY = v.y;
        RotZ = v.z;

        std::cout << "Final: x= " << RotX << ", y= " << RotY << ", z= " << RotZ << "\n";
    }
    return (0);
}
提前谢谢你是的,这很正常。使用Euler角表示相同的旋转


我个人不喜欢欧拉角,我会避免它们。另外,它们也是。

看看这一页。它拥有处理3D转换所需的一切(甚至一些代码示例!)


如果最终需要四元数到欧拉角,但需要任意旋转顺序,我遇到了一个带有转换代码的站点。有时候,诀窍就是找到正确的旋转顺序。(顺便说一句,有两个相同字母的阶数,如XYX,是正确的欧拉角,但如XYZ,是泰特-布莱恩角)

以下是链接:

下面是代码:

///////////////////////////////
// Quaternion to Euler
///////////////////////////////
enum RotSeq{zyx, zyz, zxy, zxz, yxz, yxy, yzx, yzy, xyz, xyx, xzy,xzx};

void twoaxisrot(double r11, double r12, double r21, double r31, double r32, double res[]){
  res[0] = atan2( r11, r12 );
  res[1] = acos ( r21 );
  res[2] = atan2( r31, r32 );
}

void threeaxisrot(double r11, double r12, double r21, double r31, double r32, double res[]){
  res[0] = atan2( r31, r32 );
  res[1] = asin ( r21 );
  res[2] = atan2( r11, r12 );
}

void quaternion2Euler(const Quaternion& q, double res[], RotSeq rotSeq)
{
    switch(rotSeq){
    case zyx:
      threeaxisrot( 2*(q.x*q.y + q.w*q.z),
                     q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                    -2*(q.x*q.z - q.w*q.y),
                     2*(q.y*q.z + q.w*q.x),
                     q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                     res);
      break;

    case zyz:
      twoaxisrot( 2*(q.y*q.z - q.w*q.x),
                   2*(q.x*q.z + q.w*q.y),
                   q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                   2*(q.y*q.z + q.w*q.x),
                  -2*(q.x*q.z - q.w*q.y),
                  res);
      break;

    case zxy:
      threeaxisrot( -2*(q.x*q.y - q.w*q.z),
                      q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                      2*(q.y*q.z + q.w*q.x),
                     -2*(q.x*q.z - q.w*q.y),
                      q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                      res);
      break;

    case zxz:
      twoaxisrot( 2*(q.x*q.z + q.w*q.y),
                  -2*(q.y*q.z - q.w*q.x),
                   q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                   2*(q.x*q.z - q.w*q.y),
                   2*(q.y*q.z + q.w*q.x),
                   res);
      break;

    case yxz:
      threeaxisrot( 2*(q.x*q.z + q.w*q.y),
                     q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                    -2*(q.y*q.z - q.w*q.x),
                     2*(q.x*q.y + q.w*q.z),
                     q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                     res);
      break;

    case yxy:
      twoaxisrot( 2*(q.x*q.y - q.w*q.z),
                   2*(q.y*q.z + q.w*q.x),
                   q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                   2*(q.x*q.y + q.w*q.z),
                  -2*(q.y*q.z - q.w*q.x),
                  res);
      break;

    case yzx:
      threeaxisrot( -2*(q.x*q.z - q.w*q.y),
                      q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                      2*(q.x*q.y + q.w*q.z),
                     -2*(q.y*q.z - q.w*q.x),
                      q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                      res);
      break;

    case yzy:
      twoaxisrot( 2*(q.y*q.z + q.w*q.x),
                  -2*(q.x*q.y - q.w*q.z),
                   q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                   2*(q.y*q.z - q.w*q.x),
                   2*(q.x*q.y + q.w*q.z),
                   res);
      break;

    case xyz:
      threeaxisrot( -2*(q.y*q.z - q.w*q.x),
                    q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                    2*(q.x*q.z + q.w*q.y),
                   -2*(q.x*q.y - q.w*q.z),
                    q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                    res);
      break;

    case xyx:
      twoaxisrot( 2*(q.x*q.y + q.w*q.z),
                  -2*(q.x*q.z - q.w*q.y),
                   q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                   2*(q.x*q.y - q.w*q.z),
                   2*(q.x*q.z + q.w*q.y),
                   res);
      break;

    case xzy:
      threeaxisrot( 2*(q.y*q.z + q.w*q.x),
                     q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                    -2*(q.x*q.y - q.w*q.z),
                     2*(q.x*q.z + q.w*q.y),
                     q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                     res);
      break;

    case xzx:
      twoaxisrot( 2*(q.x*q.z - q.w*q.y),
                   2*(q.x*q.y + q.w*q.z),
                   q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                   2*(q.x*q.z + q.w*q.y),
                  -2*(q.x*q.y - q.w*q.z),
                  res);
      break;
    default:
      std::cout << "Unknown rotation sequence" << std::endl;
      break;
   }
}
///////////////////////////////
//四元数到欧拉
///////////////////////////////
enum RotSeq{zyx,zyz,zxy,zxz,yxz,yxy,yzx,yzy,xyz,xyz,xzy,xzx};
void twoaxisrot(双r11,双r12,双r21,双r31,双r32,双res[])){
res[0]=atan2(r11,r12);
res[1]=acos(r21);
res[2]=atan2(r31,r32);
}
无效三轴旋转(双r11、双r12、双r21、双r31、双r32、双res[){
res[0]=atan2(r31,r32);
res[1]=asin(r21);
res[2]=atan2(r11,r12);
}
无效四元数2规则(常数四元数和q,双精度[],循环顺序循环顺序)
{
开关(rotSeq){
案例zyx:
三轴旋转(2*(q.x*q.y+q.w*q.z),
q、 w*q.w+q.x*q.x-q.y*q.y-q.z*q.z,
-2*(q.x*q.z-q.w*q.y),
2*(q.y*q.z+q.w*q.x),
q、 w*q.w-q.x*q.x-q.y*q.y+q.z*q.z,
res);
打破
案例zyz:
twoaxisrot(2*(q.y*q.z-q.w*q.x),
2*(q.x*q.z+q.w*q.y),
q、 w*q.w-q.x*q.x-q.y*q.y+q.z*q.z,
2*(q.y*q.z+q.w*q.x),
-2*(q.x*q.z-q.w*q.y),
res);
打破
案例zxy:
三轴旋转(-2*(q.x*q.y-q.w*q.z),
q、 w*q.w-q.x*q.x+q.y*q.y-q.z*q.z,
2*(q.y*q.z+q.w*q.x),
-2*(q.x*q.z-q.w*q.y),
q、 w*q.w-q.x*q.x-q.y*q.y+q.z*q.z,
res);
打破
案例zxz:
twoaxisrot(2*(q.x*q.z+q.w*q.y),
-2*(q.y*q.z-q.w*q.x),
q、 w*q.w-q.x*q.x-q.y*q.y+q.z*q.z,
2*(q.x*q.z-q.w*q.y),
2*(q.y*q.z+q.w*q.x),
res);
打破
案例yxz:
三轴旋转(2*(q.x*q.z+q.w*q.y),
q、 w*q.w-q.x*q.x-q.y*q.y+q.z*q.z,
-2*(q.y*q.z-q.w*q.x),
2*(q.x*q.y+q.w*q.z),
q、 w*q.w-q.x*q.x+q.y*q.y-q.z*q.z,
res);
打破
案例yxy:
twoaxisrot(2*(q.x*q.y-q.w*q.z),
2*(q.y*q.z+q.w*q.x),
q、 w*q.w-q.x*q.x+q.y*q.y-q.z*q.z,
2*(q.x*q.y+q.w*q.z),
-2*(q.y*q.z-q.w*q.x),
res);
打破
案例yzx:
三轴旋转(-2*(q.x*q.z-q.w*q.y),
q、 w*q.w+q.x*q.x-q.y*q.y-q.z*q.z,
2*(q.x*q.y+q.w*q.z),
-2*(q.y*q.z-q.w*q.x),
q、 w*q.w-q.x*q.x+q.y*q.y-q.z*q.z,
res);
打破
案例yzy:
twoaxisrot(2*(q.y*q.z+q.w*q.x),
-2*(q.x*q.y-q.w*q.z),
q、 w*q.w-q.x*q.x+q.y*q.y-q.z*q.z,
2*(q.y*q.z-q.w*q.x),
2*(q.x*q.y+q.w*q.z),
res);
打破
案例xyz:
三轴旋转(-2*(q.y*q.z-q.w*q.x),
q、 w*q.w-q.x*q.x-q.y*q.y+q.z*q.z,
2*(q.x*q.z+q.w*q.y),
-2*(q.x*q.y-q.w*q.z),
q、 w*q.w+q.x*q.x-q.y*q.y-q.z*q.z,
res);
打破
案例xyx:
twoaxisrot(2*(q.x*q.y+q.w*q.z),
-2*(q.x*q.z-q.w*q.y),
q、 w*q.w+q.x*q.x-q.y*q.y-q.z*q.z,
2*(q.x*q.y-q.w*q.z),
2*(q.x*q.z+q.w*q.y),
res);
打破
案例xzy:
三轴旋转(2*(q.y*q.z+q.w*q.x),
q、 w*q.w-q.x*q.x+q.y*q.y-q.z*q.z,
-2*(q.x*q.y-q.w*q.z),
2*(q.x*q.z+q.w*q.y),
q、 w*q.w+q.x*q.x-q.y*q.y-q.z*q.z,
res);
打破
案例xzx:
twoaxisrot(2*(q.x*q.z-q.w*q.y),
2*(q.x*q.y+q.w*q.z),
q、 w*q.w+q.x*q.x-q.y*q.y-q.z*q.z,
2*(q.x*q.z+q.w*q.y),
-2*(q.x*q.y-q.w*q.z),
res);
打破
违约:
标准::coutEuler->四元数

摘自Three.js

下面是一段对我有用的代码:

函数eulerToQuaternion(eulerXYZ){
var c1=数学cos(eulerXYZ[0]/2),
c2=数学cos(eulerXYZ[1]/2),
c3=数学cos(eulerXYZ[2]/2),
s1=数学sin(eulerXYZ[0]/2),
s2=数学sin(eulerXYZ[1]/2),
s3=数学sin(eulerXYZ[2]/2),
x=s1*c2*c3+c1*s2*s3,
y=c1*s2*c3-s1*c2*s3,
z=c1*c2*s3+s1*s2*c3,
w=c1*c2*c3-s1*s2*s3;
返回[x,y,z,w];
};
函数计算(){
var quat=eulertoqaternion([document.querySelector('#x').value,document.querySelector('#y').value,document.querySelector('#z').value]);
document.querySelector(“#result”).innerHTML=q
///////////////////////////////
// Quaternion to Euler
///////////////////////////////
enum RotSeq{zyx, zyz, zxy, zxz, yxz, yxy, yzx, yzy, xyz, xyx, xzy,xzx};

void twoaxisrot(double r11, double r12, double r21, double r31, double r32, double res[]){
  res[0] = atan2( r11, r12 );
  res[1] = acos ( r21 );
  res[2] = atan2( r31, r32 );
}

void threeaxisrot(double r11, double r12, double r21, double r31, double r32, double res[]){
  res[0] = atan2( r31, r32 );
  res[1] = asin ( r21 );
  res[2] = atan2( r11, r12 );
}

void quaternion2Euler(const Quaternion& q, double res[], RotSeq rotSeq)
{
    switch(rotSeq){
    case zyx:
      threeaxisrot( 2*(q.x*q.y + q.w*q.z),
                     q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                    -2*(q.x*q.z - q.w*q.y),
                     2*(q.y*q.z + q.w*q.x),
                     q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                     res);
      break;

    case zyz:
      twoaxisrot( 2*(q.y*q.z - q.w*q.x),
                   2*(q.x*q.z + q.w*q.y),
                   q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                   2*(q.y*q.z + q.w*q.x),
                  -2*(q.x*q.z - q.w*q.y),
                  res);
      break;

    case zxy:
      threeaxisrot( -2*(q.x*q.y - q.w*q.z),
                      q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                      2*(q.y*q.z + q.w*q.x),
                     -2*(q.x*q.z - q.w*q.y),
                      q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                      res);
      break;

    case zxz:
      twoaxisrot( 2*(q.x*q.z + q.w*q.y),
                  -2*(q.y*q.z - q.w*q.x),
                   q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                   2*(q.x*q.z - q.w*q.y),
                   2*(q.y*q.z + q.w*q.x),
                   res);
      break;

    case yxz:
      threeaxisrot( 2*(q.x*q.z + q.w*q.y),
                     q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                    -2*(q.y*q.z - q.w*q.x),
                     2*(q.x*q.y + q.w*q.z),
                     q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                     res);
      break;

    case yxy:
      twoaxisrot( 2*(q.x*q.y - q.w*q.z),
                   2*(q.y*q.z + q.w*q.x),
                   q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                   2*(q.x*q.y + q.w*q.z),
                  -2*(q.y*q.z - q.w*q.x),
                  res);
      break;

    case yzx:
      threeaxisrot( -2*(q.x*q.z - q.w*q.y),
                      q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                      2*(q.x*q.y + q.w*q.z),
                     -2*(q.y*q.z - q.w*q.x),
                      q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                      res);
      break;

    case yzy:
      twoaxisrot( 2*(q.y*q.z + q.w*q.x),
                  -2*(q.x*q.y - q.w*q.z),
                   q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                   2*(q.y*q.z - q.w*q.x),
                   2*(q.x*q.y + q.w*q.z),
                   res);
      break;

    case xyz:
      threeaxisrot( -2*(q.y*q.z - q.w*q.x),
                    q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                    2*(q.x*q.z + q.w*q.y),
                   -2*(q.x*q.y - q.w*q.z),
                    q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                    res);
      break;

    case xyx:
      twoaxisrot( 2*(q.x*q.y + q.w*q.z),
                  -2*(q.x*q.z - q.w*q.y),
                   q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                   2*(q.x*q.y - q.w*q.z),
                   2*(q.x*q.z + q.w*q.y),
                   res);
      break;

    case xzy:
      threeaxisrot( 2*(q.y*q.z + q.w*q.x),
                     q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                    -2*(q.x*q.y - q.w*q.z),
                     2*(q.x*q.z + q.w*q.y),
                     q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                     res);
      break;

    case xzx:
      twoaxisrot( 2*(q.x*q.z - q.w*q.y),
                   2*(q.x*q.y + q.w*q.z),
                   q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                   2*(q.x*q.z + q.w*q.y),
                  -2*(q.x*q.y - q.w*q.z),
                  res);
      break;
    default:
      std::cout << "Unknown rotation sequence" << std::endl;
      break;
   }
}