- Home /
Invert quaternion rotation
Hi, i am having issues with quaternions rotations.
I am getting a quaternion from my Arduino board and trying to rotate an object, in this way:
Quaternion q = arduino.getQuaternion ();
transform.rotation = Quaternion.Slerp(transform.rotation, q, Time.deltaTime * arduino.getEasingValue());
But the rotation is not coherent with the current gyro position (the axis are swapped). I can't change the physical orientation of the chip, but i tried to realign the axis using a Vector3, like that:
Quaternion q = arduino.getQuaternion ();
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(q.eulerAngles.y, -q.eulerAngles.z, -q.eulerAngles.x), Time.deltaTime * arduino.getEasingValue());
Now the rotation is coherent, but i have gimbal lock issues. Is there a way to obtain the same results without using EulerAngles? I need to rotate on x by using the y value, on x using the -z, on z using the -x. I guess i have to use Quaternion.AngleAxis, but i am not getting how to do it properly. Thank you!
$$anonymous$$aybe try turning the Quaternion into a Vector3, fixing that for the wrong axis and converting back to a Quat? That would lose information about local spin, but I don't think arduino gives you that anyway -- it's probably just giving you a local UP (or whatever) as a quaternion.
Or, this sounds like a solved problem somewhere in a math forum. Changing axis has got to be common.
that's what i have tried to do as you can see in the code, but i experience gymbal lock! And yes, my arduino gives me a correct quaternion (not a converted vector3!)
No, he means a quaternion can be expressed as two direction vectors, usually "forward" and "up". If you multiply Vector3.forward with your quaternion you get the rotated forward vector. Doing the same with Vector3.up will give you the up vector.
Now you should fix the vector representation probably by rotating and / or mirroring the vectors at certain axis. Finally you just have to use Quaternion.LookRotation to convert the forward and up vector back to a quaternion.
and this approach will not be affected by gymbal lock?
Answer by Eno-Khaon · Feb 20, 2016 at 07:42 PM
I would suggest utilizing an extra empty object to convert your rotations accurately.
Namely, use your first example to rotate an empty object, to get proper orientation to prepare to convert to a new set of axes.
Quaternion q = arduino.getQuaternion ();
emptyObject.rotation = Quaternion.Slerp(emptyObject.rotation, q, Time.deltaTime * arduino.getEasingValue());
Then, you can break down each axis and convert them for use in your visible object. However, doing this requires special attention paid to the order of operations. According to Unity's documentation on Euler Angles,
The x, y, and z angles represent a rotation z degrees around the z axis, x degrees around the x axis, and y degrees around the y axis (in that order).
Applying this in your case, then, can be done like this:
Vector3 v = emptyObject.eulerAngles;
transform.rotation = Quaternion.AngleAxis(v.y, Vector3.right) * Quaternion.AngleAxis(-v.x, Vector3.forward) * Quaternion.AngleAxis(-v.z, Vector3.up);
The angles are applied matching the order of Unity's application of axes, in the correct order, but are then applied to the relative axes to which they now correlate.
The idea works, but it's still suffering from gymbal lock issues, due to the Vector3 data!
Hmm... what direction(s) is it facing when this happens? Or, rather, what is the orientation of the Arduino input vs. how it is reflected in Unity in this case?
Ohh, wait... When you said roll and pitch were inverted, did you mean I had them swapped with each other, then?
If so, that changes it from
transform.rotation = Quaternion.AngleAxis(v.y, Vector3.right) * Quaternion.AngleAxis(-v.x, Vector3.forward) * Quaternion.AngleAxis(-v.z, Vector3.up);
to
transform.rotation = Quaternion.AngleAxis(v.y, Vector3.forward) * Quaternion.AngleAxis(-v.x, Vector3.right) * Quaternion.AngleAxis(-v.z, Vector3.up);
ins$$anonymous$$d.
At any rate, the rotation axes (forward/right/up) can all be modified freely to try different results. The main thing to keep consistent are the inputs into the final rotation (v.y, v.x, v.z).
Your answer
