- Home /
Extrapolating Quaternion Rotation
Hi,
I writing a multi-player game and am having some trouble understanding how to extrapolate a quaternion during prediction on the client side.
For example, let us say I have a quaternion q1 at time t1 and quaternion q2 at time t2 and both are known values that have happened in the passed. On my client I am trying to predict what quaternion q3 will be at time t3 prior to the server providing me the real q3.
Note: t3 > t2 > t1
My quat math is pretty lousy and i'm guessing I can't just slerp outside the 0 - 1 range.
I hope I have explained myself clearly enough any help would be greatly appreciated
Thx
I modified the answer to include a simpler and more precise method based on angle-axis representation. This method works fine, without some hickups that appeared at certain angles in the previous approach. Give it a try - it's way better!
Answer by aldonaletto · Sep 21, 2011 at 02:03 AM
I think this can be done using the following algorithm: find the rotation rot from q1 to q2 multiplying the inverse of q1 by q2 and calculate the "extrapolation factor" dt = (t3-t1)/(t2-1). dt will be a number > 1, where the integer part means full rot rotations from q1. Apply these full rotations while decrementing dt, and when it falls below 1 use Slerp (or Lerp) to apply the last and partial rotation:
var rot = Quaternion.Inverse(q1)*q2; // rot is the rotation occurred from t1 to t2 var dt = (t3 - t1)/(t2 - t1); // dt = extrapolation factor var q4 = q2; while (dt > 1){ q3 = q4; // q3 is the last full rotation q4 = rot * q4; // q4 is the next full rotation dt -= 1; } q3 = Quaternion.Slerp(q3, q4, dt);I haven't tested this; let me know if it has any error.
EDITED: I tested this algorithm, and found a jerky behaviour at certain angles. Then I studied the case a little more and found (after some Google search) a simpler way to do this. The idea is: a Quaternion is just a rotation of some angle around an arbitrary axis - the angle and axis returned by the function ToAngleAxis. Thus, to extrapolate a quaternion, all we have to do is to get the angle-axis representation, multiply the angle by the extrapolation factor, convert it back to quaternion with AngleAxis, then combine this rotation with the first one.
var rot = q2*Quaternion.Inverse(q1); // rot is the rotation from t1 to t2 var dt = (t3 - t1)/(t2 - t1); // dt = extrapolation factor var ang: float; var axis: Vector3; rot.ToAngleAxis(ang, axis); // find axis-angle representation if (ang > 180) ang -= 360; // assume the shortest path ang = ang * dt % 360; // multiply angle by the factor q3 = Quaternion.AngleAxis(ang, axis) * q1; // combine with first rotationI tested this approach, and it works perfectly - even for t3 < t2! - without the strange hickups of the previous method.
This is wonderful.
Thank you so much
Have a great day
$$anonymous$$ark his answer as 'accepted', don't post replies as answers!
@aldonaletto I found your method and I thought that it would be completely safe. But it isn't unfortunately. At some points ToAngleAxis
returns the opposite axis as what it was working with. When that happens, the angle becomes 360-ang. Then, you calculate it with a factor. But this factor is now calculating in the wrong way and an inverse extrapolation is performed. The new quaternion lies withing q1 and q2.
I found an error: the first expression should be:
var rot = q2 * Quaternion.Inverse(q1);
The rotation reversion can be detected when the angle becomes greater than 180: we can just subtract 360 from it - this will force the object to take the shortest path, what is the most frequent case when predicting a rotation.
The fixed code is:
var rot = q2 * Quaternion.Inverse(q1); // rot is the rotation from t1 to t2 var dt = (t3 - t1)/(t2 - t1); // dt = extrapolation factor var ang: float; var axis: Vector3; rot.ToAngleAxis(ang, axis); // find axis-angle representation if (ang > 180) ang -= 360; // assume the shortest path ang = ang * dt % 360; // multiply angle by the factor q3 = Quaternion.AngleAxis(ang, axis) * q1; // combine with first rotation
@aldonaletto Thank you for the effort. I will test it later on in my project.
Answer by Siris · Jul 06, 2014 at 06:38 AM
Here is the same thing in C#:
Quaternion rot = q2 * Quaternion.Inverse( q1 );
double dt = ( t3 - t1 ) / ( t2 - t1 );
float ang = 0.0f;
Vector3 axis = Vector3.zero;
rot.ToAngleAxis(out ang , out axis );
if( ang > 180 )
{
ang -= 360;
}
ang = ang * (float)dt % 360;
q3 = Quaternion.AngleAxis( ang , axis ) * q1;
Hi, I have used the above code for extrapolation quaternion rotation but I am not sure whether I am getting the correct results. How to ensure that that my extrapolation gave me correct results. I tried using reverse engineering method where I used the first quaternion rotation(q1) and the resultant quaternion from extrapolation (q3) and tried to intrapolate to get the quaternion rotation q2, but unfortunately I am not getting q2. I am not sure what is the problem?Can anyone give some suggestions for testing this.