11

I need to flip a quaternion from right:
x = left to right
y = front to back
z = top to bottom

to left handed coordinates where:
x = left to right
y = top to bottom
z = front to back

How would I go about doing this?

Marco A.
  • 43,032
  • 26
  • 132
  • 246
cmann
  • 1,920
  • 4
  • 21
  • 33
  • 1
    Please explain what you're actually trying to do. As is, your question does not make sense. It's okay not to understand how to do something, but you have to give the full story. My **guess** is that your question should read something like "I have a quaternion that represents a rotation in 3 dimensions, but because I'm using a coordinate system that differs from the intended one *in this particular way*, the quaternion doesn't represent the rotation I want. How do I convert it into a quaternion that does the rotation I want?" This is almost a dup of http://stackoverflow.com/questions/1263072 – Anton Geraschenko Aug 14 '09 at 01:54
  • 2
    I didn't think a needed to give more but yes it represents a rotation, or maybe an orientation, in 3d where the z axis is facing up. Now I need to essentially swap the z and y axis so that the y axis is facing up. And yes it is similar to my other question because I'm trying to achieve the same but they are two different questions. – cmann Aug 14 '09 at 09:38

6 Answers6

11

I don't think any of these answers is correct.

Andres is correct that quaternions don't have handedness (*). Handedness (or what I'll call "axis conventions") is a property that humans apply; it's how we map our concepts of "forward, right, up" to the X, Y, Z axes.

These things are true:

  • Pure-rotation matrices (orthogonal, determinant 1, etc) can be converted to a unit quaternion and back, recovering the original matrix.
  • Matrices that are not pure rotations (ones that have determinant -1, for example matrices that flip a single axis) are also called "improper rotations", and cannot be converted to a unit quaternion and back. Your mat_to_quat() routine may not blow up, but it won't give you the right answer (in the sense that quat_to_mat(mat_to_quat(M)) == M).
  • A change-of-basis that swaps handedness has determinant -1. It is an improper rotation: equivalent to a rotation (maybe identity) composed with a mirroring about the origin.

To change the basis of a quaternion, say from ROS (right-handed) to Unity (left-handed), we can use the method of .

mat3x3 ros_to_unity = /* construct this by hand */;
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. We know mat_to_quat() only works on pure-rotation matrices. How do we know that m_unity is a pure rotation? It's certainly conceivable that it's not, because unity_to_ros and ros_to_unity both have determinant -1 (as a result of the handedness switch).

The hand-wavy answer is that the handedness is switching twice, so the result has no handedness switch. The deeper answer has to do with the fact that similarity transformations preserve certain aspects of the operator, but I don't have enough math to make the proof.

Note that this will give you a correct result, but you can probably do it more quickly if unity_to_ros is a simple matrix (say, with just an axis swap). But you should probably derive that faster method by expanding the math done here.

(*) Actually, there is the distinction between Hamilton and JPL quaternions; but everybody uses Hamilton so there's no need to muddy the waters with that.

Paul Du Bois
  • 2,097
  • 1
  • 20
  • 31
7

I think that the solution is:

Given:    Right Hand: {w,x,y,z}
Convert:  Left Hand: {-w,z,y,x}

In unity:

 new Quaternion(rhQz,rhQy,rhQx,-rhQw)
Mendi Barel
  • 3,350
  • 1
  • 23
  • 24
  • This is what actually worked here; the only thing was that we needed {y,z,-w,x} (so the 'y' needed negation). That might be because I'm doing something wrong though; this was in an OpenGL app where I calculate a modelView matrix, then send this as a quaternion to Unity and try to setup the camera there. – Ruud van Gaal Jun 21 '17 at 15:43
  • This should not work unless you're using really weird quaternion data structures. The w value is conventionally either the first or last value in the tuple, and is also not directly associated with any spatial direction, so it should never end up in third position. – Sty Sep 20 '17 at 17:06
  • I was trying to adjust the rotation of a bone from one armature to another with different handedness, I think this elegantly solved my issue! Thanks! – Logic1 Oct 15 '17 at 16:10
  • Maybe I messed up somewhere in translation, but for some reason Option 1 is not equivalent to Option 2. I tried to set them into a camera inside Unity3D's editor. Option 2 works for me. – Sepehr Oct 31 '18 at 19:55
  • 1
    Curious, how do you mathematically prove these to be equal? based on their dot products? – Sepehr Oct 31 '18 at 19:56
6

Ok, just to be clear, quaternions don't actually have handedness. They are handless(see wikipedia article on quaternions). HOWEVER, the conversion to a matrix from a quaternion does have handedness associated with it. See http://osdir.com/ml/games.devel.algorithms/2002-11/msg00318.html If your code performs this conversion, you may have to have two separate functions to convert to a left handed matrix or a right handed matrix.

Hope that helps.

Andres
  • 5,012
  • 3
  • 24
  • 36
  • 4
    I think what the user is really asking is "how does changing the handedness of my basis affect my rotation quaternion?" which is a valid question. Orientation is a datum about the vectorspace, not its transformations (including quaternion and matrix representations.) – rschwieb Jul 08 '15 at 17:47
  • That osdir thread is not correct. Conversion from quaternion to 3x3 matrix does not involve handedness of any sort. It is purely "solve for the matrix M such that Mv = qv" (assuming you're using column vectors). See http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/ for the derivation. – Paul Du Bois Aug 29 '17 at 18:57
2

Once you do that, you no longer have a quaternion, i.e. the usual rules for multiplying them won't work. The identity i^2 = j^2 = k^2 = ijk = -1 will no longer hold if you swap j and k (y and z in your right handed system).

Jim Lewis
  • 43,505
  • 7
  • 82
  • 96
  • 1
    So are you saying that you can't change the quaternion? – cmann Aug 13 '09 at 22:39
  • @cmann Not if you want to preserve the usual properties. I suppose one could derive a whole other set of rules for LH-quaternions...but why? What are you trying to accomplish? Maybe there's an easier way; perhaps converting LH to RH coordinates, doing your rotations or whatever, then converting back to the LH system? – Jim Lewis Aug 13 '09 at 22:54
  • 2
    I'm trying to export data from Blender to OpenGL – cmann Aug 14 '09 at 09:31
0

http://www.gamedev.net/community/forums/topic.asp?topic_id=459925

To paraphrase, negate the axis.

Amber
  • 507,862
  • 82
  • 626
  • 550
  • 1
    The post you cited actually answers a different question -- the original poster seems to have used "left handed" to mean "rotate in the opposite direction". That's quite different from swapping the Y and Z axes as cmann wants to do. – Jim Lewis Aug 13 '09 at 22:31
0

I know this question is old, but the method below is tested and works. I used pyquaternion to manipulate the quaternions.

To go from right to left. Find the axis and angle of the right hand quaternion. Then convert the axis to left hand coordinates. Negate the right hand angle to get the left hand angle. Construct quaternion with left handed axis and left hand angle.