Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quaternion reaching gimbal lock

In attempt to avoid angle lock when performing rotations I've tried to switch over to Quaternions. Somehow, I'm still managing to reach gimbal lock.

I'm not sure if its due to the math I've implemented, or a design error, so please point out if I should change my approach for my object coordinates.

Each of my objects hold an X,Y,Z value, and a pitch,yaw,roll value. When I change a rotation value, the object recalculates its vertices based on the above information. This logic is as follows:

    // vertex array
    vertices[x] -= /*Offset by origin point*/;

    // Quat.'s representing rotation around xyz axes
    Quaternion q1 = Quaternion(glm::vec3(1,0,0),pitch);
    Quaternion q2 = Quaternion(glm::vec3(0,1,0),yaw); 
    Quaternion q3 = Quaternion(glm::vec3(0,0,1),roll); 

    // total rotation
    Quaternion TotalRot = ( (q3 * q2) * (q1) ); 

    // conversion of original coordinates to quaternion
    Quaternion Point1 = Quaternion(0, vertices[x].x(), vertices[x].y(), vertices[x].z()); 

    // resulting rotated point
    Quaternion Point2 = Quaternion( (TotalRot * Point1) * TotalRot.inverse() );

    // placing new point back into vertices array
    vertices[x] = QVector3D(round(Point2.v.x),round(Point2.v.y),round(Point2.v.z));
    vertices[x]+= /*Undo origin point offset*/;

"vertices[]" is the objects vertex array. The origin point offset commented out above is just so that the object is rotated around the proper origin point, so it is shifted relative to 0,0,0 since rotations occur around that point (right?).

I have a pictorial representation of my problem, where I first yaw by 90, pitch by 45, then roll by -90, but the roll axis became parallel to the pitch axis:

problemexample

Edit:

I tried multiplying those 3 axis quaternions together, then multiplied by a 4x4 matrix, followed by multiplying that by my vertex point, but I still gimbal lock/reach singularity!

    Quaternion q1 = (1,0,0,pitch);
    Quaternion q2 = (0,1,0,yaw);
    Quaternion q3 = (0,0,1,roll);
    Quaternion qtot = (q1*q2)*q3;
    Quaternion p1(0, vertices[x].x(), vertices[x].y(), vertices[x].z());
    QMatrix4x4 m;
    m.rotate(qtot);
    QVector4D v = m*p1;
    vertices[x] = QVector3D(v.x(),v.y(),v.z());
like image 867
Yattabyte Avatar asked Feb 28 '15 00:02

Yattabyte


People also ask

Do quaternions suffer from gimbal lock?

Quaternions are an alternate way to describe orientation or rotations in 3D space using an ordered set of four numbers. They have the ability to uniquely describe any three-dimensional rotation about an arbitrary axis and do not suffer from gimbal lock.

How do quaternions avoid gimbal locks?

The only way to avoid gimbal lock is to use quaternion instead of euler to represent rotations. In this specific situation, unless both rotate manip and direction manip use quaternion, the gimbal lock behavior can NOT be avoided.

How do you get over a gimbal lock?

Solutions. This problem may be overcome by use of a fourth gimbal, actively driven by a motor so as to maintain a large angle between roll and yaw gimbal axes. Another solution is to rotate one or more of the gimbals to an arbitrary position when gimbal lock is detected and thus reset the device.


1 Answers

If you take a Euler angles representation and turn it into quaternions just for doing the vector rotations, then you are still just using Euler angles. The gimbal lock problem will remain as long as you have Euler angles involved anywhere. You need to switch completely to quaternions and never go through a Euler angles representation anywhere at all if you want to completely eliminate that problem.

The basic way to do it is that you can use Euler angles at the far ends of your calculations (as the original input or as the ultimate output) if that is more convenient for you (e.g., Euler angles are often a more "human-readable" representation). But, use quaternions for everything else (and you can convert occasionally to rotation matrices, because they are more efficient for rotating vectors), and never do intermediary conversions to any of the "bad" rotation representations (Euler angles, axis-angles, etc.). The "gimbal-lock-free" benefits of quaternions and rotation matrices only apply if you stick with those two representations throughout all your calculations.

So, on one side, you have the singular representations (the formal term for "gimbal lock" is singularity):

  • Euler angles (of any kind, of which there are 12, by the way); and
  • axis-angle.

And on the other side, you have the singularity-free representations:

  • quaternions (more efficient memory-wise and for composition operations); and
  • rotation matrices (more efficient for applying rotations to vectors).

Whenever you operate (like putting several rotations together, or moving a rotating object) with a singular representation, you will have to worry about that singularity in every calculation you do. When you do those same operations with a singularity-free representation, then you don't have to worry about that (but you do have to worry about the constraints, which is the unit-norm constraint for quaternions and the proper orthogonality for rotation matrices). And of course, any time you convert to or from a singular representation, you have to worry about the singularity. This is why you should only do the conversions at the far ends of your calculations (when entering or leaving), and stick with the non-singular representations all through your calculations otherwise.

The only good purpose for Euler angles is for human readability, period.

like image 161
Mikael Persson Avatar answered Nov 03 '22 06:11

Mikael Persson