Reputation: 3364
I my 3d program, the rotation of object is represented by the quaternion like [0.130526, 0.0, 0.0, 0.991445]
. The program works with right-handed coordinate system with the Z axis pointing up (like in 3ds max):
On the other hand, my application use left-handed coordinate system and the Y axis is up:
How can I transform my quaternion from one coordinate system to another, with the respect for which axis is up?
Upvotes: 13
Views: 23326
Reputation: 6307
Geometric algebra solution just for fun.
I'll write uv for the geometric product of vectors u and v.
It's commutative for parallel vectors: uv = vu when u ∥ v,
anticommutative for orthogonal vectors: uv = −vu when u ⊥ v,
and associative: (uv)w = u(vw) = uvw.
Furthermore, uu = |u|² (the square of the length).
Let (x, y, z) be the old right-handed basis.
Vectors in the basis are orthogonal, so xy = −yx, yz = −zy, zx = −xz,
and have length 1, so xx = yy = zz = 1.
The quaternion basis (1, i, j, k) corresponds to the multivector basis (1, zy, xz, yx).
You can check that all the quaternion identities work. For example:
A quaternion in the old basis can be written as s + b⋅zy + c⋅xz + d⋅yx.
A quaternion in the new basis can be written as S + B⋅yz + C⋅xy + D⋅zx. (We've swapped y and z.)
Solving for the new coefficients, we get S=s, B=−b, C=−d and D=−c.
There are two conventions for writing quaternion coefficients: [s, b,c,d]
and [b,c,d, s]
.
[s=0.130526, b=0, c=0, d=0.991445]
transforms to [S=0.130526, B=0, C=-0.991445, D=0]
.[b=0.130526, c=0, d=0, s=0.991445]
transforms to [B=-0.130526, C=0, D=0, S=0.991445]
.Upvotes: 2
Reputation: 2171
This is a condensed version of an answer to a slightly different question.
The problem you ask about arises even if the two coordinate systems are same-handed; it turns out that handedness flips don't make the problem significantly harder. Here is how to do it in general. To change the basis of a quaternion, say from ROS (right-handed, Z up) to Unity (left-handed, Y up):
mat3x3 ros_to_unity = /* construct this by hand by mapping input axes to output axes */;
mat3x3 unity_to_ros = ros_to_unity.inverse();
quat q_ros = ...;
mat3x3 m_unity = ros_to_unity * mat3x3(q_ros) * unity_to_ros;
quat q_unity = mat_to_quat(m_unity);
Lines 1-4 are simply the method of https://stackoverflow.com/a/39519079/194921: "How do you perform a change-of-basis on a matrix?"
Line 5 is interesting; not all matrices convert to quats, but if ros_to_unity is correct, then this conversion will succeed.
Note that this will give you a correct result, but it goes through a lot of work -- conversion to and from a matrix, some multiplies, an inversion. But you can examine its results and then write a special-case version that rearranges or flips axes, like the one aka.nice derived.
Upvotes: 4
Reputation: 9382
A rotation of angle x around axis (u,v,w) can be represented by quaternion with real part cos(x/2) and unreal part sin(x/2)*(u,v,w).
If axis coordinates are (u,v,w) in original trihedron, they will be (u,w,v) in your trihedron.
Thus if original quaternion was (a,b,c,d) - a+ib+jc+kd - the quaternion must be transformed to (a,b,d,c) in your trihedron.
EDIT
But because your trihedron is left handed, the angle also has to be reversed, so the same rotation can finally be expressed by the quaternion (a,-b,-d,-c) in your trihedron.
Upvotes: 15