10

I am trying to rotate an object by 45 degrees using quaternions about Y-Axis. After Specifying the Quaternion i am trying to get the Rotation Matrix. But the values I see are incorrect

Eigen::Quaterniond q;
q.x() = 0;
q.y() = 1;
q.z() = 0;
q.w() = PI/8;    // Half of the rotation angle must be specified, even IDK why

Eigen::Matrix3d R = q.normalized().toRotationMatrix();
std::cout << "R=" << std::endl << R << std::endl;

OUTPUT :

R=
-0.732    -0   -0.680
     0     1       -0
 0.680     0   -0.732


Since the OpenGL Rotation Matrix along Y-Axis should be :

enter image description here

Therefore my expected output should be :

R=
 0.707     0    0.707
     0     1        0
-0.707     0    0.707

Not only are the values off by a small percent the wrong signs on the values are causing some unexpected rotations. Because of the negative signs my cube is doing a 180 degree turn plus the specified angle. I have broken my head over this for the whole day. Can some one tell me what I am doing wrong ?

DollarAkshay
  • 2,063
  • 1
  • 21
  • 39
  • 45 degrees is `pi / 4` – Rostislav Apr 08 '16 at 14:02
  • I don't know squat about quaternions, but I do know that /8 corresponds to 22.5°. 45° is /4. – Logicrat Apr 08 '16 at 14:02
  • 1
    @Logicrat Even i dont know why, but you have to specify half of the angle. So If I have to rotate by `PI/4` I have to specify it as `PI/8` – DollarAkshay Apr 08 '16 at 14:09
  • Ah yes, that's true - completely forgot about that - haven't used quats in like 5 years. Where does your definition of PI come from? How accurate is it? – Rostislav Apr 08 '16 at 14:15
  • @Rostislav Its pretty accurate `const double PI = 3.1415926535;` – DollarAkshay Apr 08 '16 at 14:16
  • I actually implemented my own Quaternion class at first. I thought my implementation must be wrong. But then even the Eigen Library seems to be giving the exact same result. – DollarAkshay Apr 08 '16 at 14:17
  • well, I'd say it would still make sense to use a more accurate one from [](https://www.quantstart.com/articles/Mathematical-Constants-in-C) to avoid any error accumulation. – Rostislav Apr 08 '16 at 14:24
  • Oh wait, the w, x, y, z coordinates are not defined as you initialize them - they should be defined as shown [here](https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation) - i.e. `w = cos(theta/2), x = axis_x * sin(theta / 2), y = axis_y * sin(theta / 2), z = axis_z * sin(theta / 2)`. Or alternatively in [eigen](https://eigen.tuxfamily.org/dox/classEigen_1_1Quaternion.html), use this constructor `Quaternion (const AngleAxisType &aa)` – Rostislav Apr 08 '16 at 14:30

1 Answers1

25

The way you initialize your quaternion is incorrect. If you directly initialize the coordinates of quaternion, you should take the definition into account:

enter image description here

Alternatively, the Quaternion class in Eigen provides a constructor from an axis-angle representation.

This code:

#include <Eigen/Geometry>
#include <iostream>

void outputAsMatrix(const Eigen::Quaterniond& q)
{
    std::cout << "R=" << std::endl << q.normalized().toRotationMatrix() << std::endl;
}

void main()
{
    auto angle = M_PI / 4;
    auto sinA = std::sin(angle / 2);
    auto cosA = std::cos(angle / 2);

    Eigen::Quaterniond q;
    q.x() = 0 * sinA;
    q.y() = 1 * sinA;
    q.z() = 0 * sinA;
    q.w() = cosA;    

    outputAsMatrix(q);
    outputAsMatrix(Eigen::Quaterniond{Eigen::AngleAxisd{angle, Eigen::Vector3d{0, 1, 0}}});
}

outputs what you expect:

R=
 0.707107         0  0.707107
        0         1         0
-0.707107         0  0.707107
R=
 0.707107         0  0.707107
        0         1         0
-0.707107         0  0.707107
Rostislav
  • 3,857
  • 18
  • 30