I have a 9 DOF IMU sensor connected through an Arduino and the values are exposed as public static floats.
So I have float UnitySerialPort.x, y, z, w. Values are between -1 and 1. I want to use these values to transform/rotate an object. All the examples I can find are either in JS or just for euler x,y,z transforms only.
wow, i canât believe Iâm going to say this but⌠it looks like youâve got the 4 axis of the quaternion⌠So you want to set the quaternion attributes directly
Quaternion myRotation = new Quaternion(myXFloat, myYFloat, myZFloat, myWFloat);
I posted this in answers too but itâs been like an hour and my comments arenât showing up. Iâll just switch to here.
I take an initial reading from the sensor, I get X=0.0025, Y = -0.7203, Z=0.0197, W = 0.6934
I set that as a quaternion called initialQ. I want that rotation to equal my gameobjectâs original location. I then want to move it from that point.
In the update loop I run this. newQ are the new readings I get 10 times per second. No matter what newQ values are the resulting finalQ is always 0, 0, 0, 0.
Any idea why itâs rounding the float values all the way to the nearest tenth?
Quaternion newQ = new Quaternion (x, y, z, w);
Quaternion finalQ = new Quaternion ();
Quaternion inverseQ = Quaternion.Inverse (newQ);
When you call ToString on a Quaternion (which is implicitly being done when you call Debug.Log with a quat in it), unity just formats the number to 1 decimal place for display purposes. If you ToString the individual floats, youâll see the full value is actually there.
As for your codeâŚ
Quaternion newQ = new Quaternion (x, y, z, w);
//i'm assuming x,y,z,w are polled from your arduino
Quaternion finalQ = new Quaternion ();
//you've just created a quaterion of <0,0,0,0>
Quaternion inverseQ = Quaternion.Inverse (newQ);
//this one I have a question about, I'll get to that later, outside of this code block
finalQ.Equals ((initialQ * newQ * inverseQ));
//Equals? Equals is a method that returns a boolean if the value passed in is equal
//in the case of this, true would be returned if initialQ is also <0,0,0,0>
If you want to set finalQ equal to that arithmetic operation youâd say:
finalQ = initialQ * newQ * inverseQ;
As for my questionâŚ
Why are you multiplying newQ by its inverse?
To give you an idea of what youâve just done by doing so, Iâll use scalars.
x * inv(x) = x * 1/x = 1
Youâve effectively resulted in the identity value. In the case of the Quaternion, you got an identity quat⌠an orientation of no rotation. This value can be found as Quaternion.identity, and if you multiply any quat by it, you result in the same quat (just like a scalar * 1 equals that scalar).
This is part of the definition of an inverse function, that the composition of that function in relation to its origin function will be the identity function:
So when you say:
initialQ * newQ * inverseQ
The result will be initialQ (of course there may be minor float error introduced, so it may not be exactly initialQ, but pretty damn close).
I saw that formula for multiplying transforms in a post and tried it and realized after I posted this when I did some math that it would result in exactly what you described. I have the gameobject responding ok but the trouble now is that the first transform.rotate I do moves the object to an entirely different area. I thought rotate was just supposed to rotate it when leave it in itâs original location.
It looks like the first FinalQ (quaternion that is applied to the rotation) is 0, 0, 0, 0.99999.
The object starts in location, 0, 6.9, 0 and ends up I would approximate around 0, 6.9, 285. Rotate can move it that far? Once itâs in that new location it basically stays there and then just rotates in place.