Sign in to follow this  

Lerping a rotation

This topic is 2587 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a small problem.
My multiplayer game currently has a packet being delivered every 100ms.
The packet contains position and a heading angle which is -pi to pi.

I am actually rendering 100ms behind real server time in order to be able to lerp the positions (which work fine). I tried to lerp the heading angle this way and it works but theres a sudden snapback at the end of every rotation. I just cant figure out what it could be

//lerp:
//return a + (b - a) * t;


float h1 = (*ito).headings.front(); //Heading 100ms ago
float h2 = (*ito).headings.back(); //Current server heading
float currh = 0.0f; //Lerped heading
currh = Math::lerp(h1, h2, zlerp);
//zlerp = elapsed time since last update / 100.0 (ms) This works perfect for pos


Anyone could know what im doing wrong?

Share this post


Link to post
Share on other sites
You can't lerp between angles without problems. You can either use SLERP or normalize the angles, find the fastest route from one angle to another (remember - angle is equal to the remainder of a division between that angle and the "full circle angle" in the same units, 2 pi radians or 360 degrees), modify the 2nd angle to make it fit the fastest route and only then do a lerp between those angles.

http://en.wikipedia.org/wiki/Modulo_operation

Share this post


Link to post
Share on other sites
I calculate the shortest difference between two angles like this:

d = b - a;
a = abs(d);
s = sign(d);
if (a > pi) {
d = s * (2 * pi - a) * -1;
}//if


now you can:

lerp = a + d * i;


you can map back into (-pi,pi) range using the same code again:

a = abs(d);
s = sign(d);
if (a > pi) {
d = s * (2 * pi - a) * -1;
}//if


this uses less cycles than modulo

Share this post


Link to post
Share on other sites
Thanks for reply.
That seems to help but my maths isnt that great?
Do you have a quick example of what you said? or should I go ahead learning slerp.
Also why is your user rating so low? :S

-edit thanks skytiger. I got an example now. cheers :D

Share this post


Link to post
Share on other sites
Quote:
Original post by bubu LV
Quote:
Original post by snake5
You can either use SLERP or normalize the angles


Isn't slerp only for 3d rotation, not 1d angle?


SLERP gets you between points on a sphere.

What do points on a sphere have to do with rotations?

In 3d, you can represent a rotation as a unit quaternion; the unit quaternions lie on a sphere in four dimensions, so you can use SLERP to get between them.

In 2d, you can represent a rotation as a unit vector. The unit vectors lie on a sphere in 2 dimensions (i.e., a circle), so you can use SLERP to get between them.

In both cases, this does what you want because the notion of distance on the sphere agrees with what you'd want to call the distance between two rotations.

Share this post


Link to post
Share on other sites
Quote:
Original post by skytiger
I calculate the shortest difference between two angles like this:

*** Source Snippet Removed ***

now you can:

*** Source Snippet Removed ***

you can map back into (-pi,pi) range using the same code again:

*** Source Snippet Removed ***

this uses less cycles than modulo


What is sign() ? Is that a function you made yourself? cant find it anywhere in standard libraries

Share this post


Link to post
Share on other sites
Ok I tried using slerp and it seems to be working very well.
Except for one slight error.
The rotations are smooth as hell except sometimes it stops rotation and quickly rotates the other way.

Please can someone who is familiar with slerps check this code. I would be very greatful. Im sure its some simple error im making


float h1 = (*ito).headings.front(); //100ms behind server time
float h2 = (*ito).headings.back(); //Current server time
float hcurr = 0.0f;

Quaternion hh1, hh2, ff;
float uu, uu2, uu3;
hh1.fromHeadPitchRoll(h1, 0.0f, 0.0f);
hh2.fromHeadPitchRoll(h2, 0.0f, 0.0f);
ff = Quaternion::slerp(hh1, hh2, zlerp); //zlerp = time since last update / 100.0
ff.toHeadPitchRoll(uu, uu2, uu3); //uu should be the slerped heading angle



the actual slerp function is from a well known maths library so im pretty sure its correct

Share this post


Link to post
Share on other sites
Quote:
Original post by rgibson11
the actual slerp function is from a well known maths library so im pretty sure its correct
What math library is it? Does the SLERP function in question correct for quaternion aliasing?

Share this post


Link to post
Share on other sites
Quote:
I tried to lerp the heading angle this way and it works but theres a sudden snapback at the end of every rotation. I just cant figure out what it could be


The shortest path between -179 degrees and 179 degrees is 2 degrees. Lerp functions see that as 358 degrees.... That's usually the problem.

Quote:
Original post by rgibson11
The rotations are smooth as hell except sometimes it stops rotation and quickly rotates the other way.


It sounds as though the slerp function you are using is not performing a dot product to (potentially) flip the second quat? Does this fix it?


float h1 = (*ito).headings.front(); //100ms behind server time
float h2 = (*ito).headings.back(); //Current server time
float hcurr = 0.0f;

Quaternion hh1, hh2, ff;
float uu, uu2, uu3;
hh1.fromHeadPitchRoll(h1, 0.0f, 0.0f);
hh2.fromHeadPitchRoll(h2, 0.0f, 0.0f);
if(Quaternion::dot(hh1, hh2) < 0)
{
hh2.x = -hh2.x;
hh2.y = -hh2.y;
hh2.z = -hh2.z;
hh2.w = -hh2.w;
}
ff = Quaternion::slerp(hh1, hh2, zlerp); //zlerp = time since last update / 100.0
ff.toHeadPitchRoll(uu, uu2, uu3); //uu should be the slerped heading angle

Share this post


Link to post
Share on other sites
Quote:
Original post by RobTheBloke
Quote:
I tried to lerp the heading angle this way and it works but theres a sudden snapback at the end of every rotation. I just cant figure out what it could be


The shortest path between -179 degrees and 179 degrees is 2 degrees. Lerp functions see that as 358 degrees.... That's usually the problem.

Quote:
Original post by rgibson11
The rotations are smooth as hell except sometimes it stops rotation and quickly rotates the other way.


It sounds as though the slerp function you are using is not performing a dot product to (potentially) flip the second quat? Does this fix it?

*** Source Snippet Removed ***


You are absolutely amazing, works perfectly now. Thanks so much. ++Rating;

Share this post


Link to post
Share on other sites

This topic is 2587 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this