Hi guys, I’ve been struggling with this problem for a couple days now and i can’t find a solution. I’ve searched on the forum but can’t find a proper way to do this.
Here’s my problem:
I Have an IMU sensor that sends a data frame containing 4 Quaternion values and 3 Acceleration along the axis.
I’ve placed a cube in the game view and i want to rotate the cube as i rotate the sensor.Applying the Quaternion to the transoform.rotation of the object doesen’t seem to work, since the rotation works on different axis. I probably need to setup an initial Quaternion and than rotate from that with an offset.
How can i do such an initialization? And then how can i rotate from that every time a get a new Quaternion?
The quaternion are already Unit Quaternion and the acceleration range is from (-9,81 to 9,81)
I think you’d need to post more info on what the 4 quaternion values represent in your IMU sensor.
You can create a pseudo-orientation from the accelerometer values but it won’t be correct (for example, your phone turned upside down will give the same XYZ accelerometer values as if it was turned the other way around).
For example, creating a roll and pitch from the accelerometer values would use this equation:
float fRoll = Mathf.Atan2( -Input.acceleration.y , Input.acceleration.z );
fRoll *= Mathf.Rad2Deg;
float fPitch = Mathf.Atan2( Input.acceleration.x , Mathf.Sqrt(Input.acceleration.y*Input.acceleration.y + Input.acceleration.z*Input.acceleration.z) );
fPitch *= Mathf.Rad2Deg;
You can then put this pitch and roll into your transform as eulerAngles.
p.s. I’m using Input.acceleration which is -1 to +1 under normal gravity. You might need to normalise your accelerometer inputs by dividing them by 9.81
Thanks for the reply but the problem is that: i don’t want to use acceleration for rotating the object, i just need it for the initialization of the first Quaternion. By the way my sensor sends 4 byte wich i converted into Unit quaternion (q.x,q.y,q.z,q.w)
If I understand your question correctly, it is simply a matter of getting an initial quaternion from wherever (it could even be the transform.rotation of your object, as read in the Start method). And then on each frame, multiply this by your quaternion from the IMU. Something like:
transform.rotation = imuRotation * originalRotation;
I apologize for my bad english, yes this works fine for object rotation but the problem is the initial orientation. If i start in upright position i find the cube already rotated by 45° on the Z axis. I probably shouls use the first Quaternion for “sync” the data received and the current orientation. But just can’t figure out how.
Ah. I think I see.
OK, look at it this way: you want to take the difference between the current IMU rotation and the first IMU rotation, and apply this difference to your object.
You can find that with Quaternion.SetFromToRotation. So it would look something like this:
// original rotation of our object
Quaternion initialObjRotation;
// original rotation of the IMU
Quaternion initialIMURotation;
bool imuInitialized = false;
// Temporary quaternion (kept around just to for efficiency)
Quaternion diff;
void Start() {
initialObjRotation = transform.rotation;
diff = new Quaternion();
}
public void HandleIMURotation(Quaternion imuRot) {
if (!imuInitialized) {
// This is the first IMU reading; just store it as
// the initial IMU rotation.
initialIMURotation = imuRot;
imuInitialized = true;
} else {
// This is a subsequent reading; find out how the
// IMU has changed since the start, and apply that
// same change to our object.
diff.SetFromToRotation(initialIMURotation, imuRot);
transform.rotation = diff * initialRotation;
}
}
SetFromRotation apparenlty needs Vector3 in its arguments, i used InitialIMURot.eulerAngles and imuRot.eulerAngles but doesen’t seems to work
Oops! You’re right! I was thinking it computed the rotation from one orientation to another, but it doesn’t do that.
OK then, we’ll have to compute it differently. Algebra suggests that this ought to work (in place of line 26 above):
diff = imuRot * Quaternion.Inverse(initialRotation);
But my math could be wrong. (Quaternions are tricky in that A * B is not the same thing as B * A — the order matters.) Please give it a try and let us know what you find!