Reputation: 23
I need to rotate an object to have an exact rotation relative to real world. Therefore calling Input.gyro.attitude
returns a Quaternion representing the position of the device. On the other hand, this forces me to compute every rotation based upon this quaternion as default rotation.
An easy way to set some object facing upwards would be the following:
Vector3 up = Input.gyro.attitude.eulerAngles;
...
transform.rotation = Quaternion.Euler(up.x, up.y, up.z);
This rotates up.z
around z, then up.x
around x, and up.y
around y.
My problem is, that the coordinate system is not quite right, in my app the y and z axis swapped (I'm using Vuforia, so it's always relative to the marker), meaning that an rotation around z results in a rotation around y and the other way around. Here things get difficult: Obviously
transform.rotation = Quaternion.Euler(up.x, up.z, up.y);
fails, since this still rotates first around z, but now with up.y
. The correct order would be to create a rotation, that rotates first around y, then x, then z.
Since the Euler Angles are retrieved from a Quaternion,
transform.rotation = Quaternion.identity;
transform.Rotate(0, up.eulerAngles.z, 0);
transform.Rotate(up.eulerAngles.x, 0, 0);
transform.Rotate(0, 0, up.eulerAngles.y);
won't work either, of course.
However, I can't find a way to do this. Am I overlooking something?
Upvotes: 2
Views: 4528
Reputation: 2684
This might not be mathematically correct but i was using an IMU to change the orientation/rotation of a cube. For me the roll and pitch were swapped. To correct this i just swapped around the x,y and z and it was corrected.
This is the important bit of my code:
float w = float.Parse(values[1]);
float x = float.Parse(values[2]);
float y = float.Parse(values[3]);
float z = float.Parse(values[4]);
/// Original code with swapped yaw and pitch
// this.transform.localRotation = Quaternion.Lerp(this.transform.localRotation, new Quaternion(w, x, y, z), Time.deltaTime * speedFactor);
/// Corrected code with correct yaw and pitch (I inverted the x,y and z because they were inverted but matched the correct axis)
this.transform.localRotation = Quaternion.Lerp(this.transform.localRotation, new Quaternion(w, -y, -z, -x), Time.deltaTime * speedFactor);
Also fyi I was using the uduino library with this tutorial: https://marcteyssier.com/uduino/projects/connect-a-imu-to-unity
Again maybe not correct mathematically but I didn't need to use Euler angles (so avoid their problems) and it seems to work.
I hope this helps.
Upvotes: 0
Reputation: 201
You should be able to multiply a series of calls to Quaternion.AngleAxis in the order you want, I believe. Have to tried something something like this?
transform.rotation = Quaternion.identity *
Quaternion.AngleAxis(up.eulerAngles.y, Vector3.up) *
Quaternion.AngleAxis(up.eulerAngles.x, Vector3.forward) *
Quaternion.AngleAxis(up.euelerAngles.z, Vector3.right);
Upvotes: 3