9
votes

I have the following problem: A quaternion (q1) from a motion capturing device needs to be corrected by the yaw angle (and only yaw!) from another orientation quaternion (q2) derived by a second tracked object, so that the pitch and roll of q1 is the same as before but q1 has the yaw of q2.

The working solution is converting the quats to matrices, then I do the calculations to extract the rotation angle and then I do the heading correction. But this results in a "flipping" when directly in direction of a certain axis (e.g. after 0° - 359°). Also tried other conversions which are not convenient.

Is there any possibility to do the math directly on the quaternions without conversions to matrices or euler angles (i.e. so I can set the corrected quaternion as quaternion for the tracked object)?

As said - the correction should include only the rotation around the up-axis (yaw). I have not many programming possibilities regarding math classes (VSL Script from Virtools is unfortunately pretty limited in this direction). Anyone has some advice?

4
I think this is something for math.stackexchange.comIshtar
Thanks for this hint - didn´t know that a special math board exists :)Raboon

4 Answers

2
votes

For this task euler angles are the best thing to use, as their advantage (the only advantage at all) lies in the separation into individual roations around orthogonal axes. So convert both quaternions to an euler angle convention that fits your needs and just substitute q1's yaw angle by q2's.

Of course you need to use a matching euler angle convention, one where the other rotations don't depend on the yaw angle (so the yaw rotation is applied first when transforming a point?), so that you can just change the angle without influencing the other axes. When converting the resulting euler angle triple back to a quaternion, you should get a unique representation again, or am I missing something?

1
votes

You can remove the yaw part of the quaternion by calculating the yaw part, and then applying its inverse. Let's assume that your quaternions are quat(w,x,y,z) == w + xi + yj + zk), and yaw is defined around the Z axis (euler 123 or 213 from this paper).

Note that in these frames, a rotation by yaw around the Z axis is represented with the quaternion quat(cos(yaw/2), 0, 0, sin(yaw/2)).

Decomposing quaternions into euler angles, we have yaw as:

yaw = atan2(-2*x*y + 2*w*z, +w*w +x*x -y*y -z*z); // 123 angles (page 24)
yaw = atan2(-2*x*y + 2*w*z, +w*w -x*x +y*y -z*z); // 213 angles (page 28)

From which we can derive that

quat quat_2yaw = quat(w*w +x*x -y*y -z*z, 0, 0, -2*x*y + 2*w*z).normalize(); // 123 angles
quat quat_2yaw = quat(w*w -x*x +y*y -z*z, 0, 0, -2*x*y + 2*w*z).normalize(); // 213 angles

An easy way to halve the angle of a quaternion is to add it to the identity quaternion and normalize:

quat quat_yaw = (1 + quat_2yaw).normalize();

To answer your original question - we want to take the yaw from q1, and replace q2s yaw with it. We can do that as follows:

q2 = get_quat_yaw(q1) * get_quat_yaw(q2).conj() * q2;
0
votes

Short answer: Yes it is possible. You can formulate rotations (about an arbitrary axis) and perform it with quaternion operations.

Long answer: See the Wikipedia article on Quaternions and rotations. I guess the problem you describe is the gimbal lock.

0
votes

If you have quaternions Q1 and Q2 and your 'up' direction is y, then if you take out the y component of Q1 and renormalize, then you get a quaternion with no yaw component. Likewise, if you take out the x and z components of Q2, then you get a quaternion with only the yaw component. Multiply the second to the first (using quaternion multiplication) and you're there.

Q1[2] = 0;
normalize4d(Q1);
Q2[1] = 0;
Q2[3] = 0;
normalize4d(Q2);
Q3 = quatMult(Q2,Q1);

Of course, you might want to check the special case where there has been a rotation by exactly (or close to) 180 degrees since that can make things numerically unstable when you try to normalize a vector with very small magnitude.