user826846
user826846

Reputation: 11

Simple Euler Physics, Weird Behaviour

I have this simple euler integrator. For finding precise collision times it should handle negative dt's as well (I divide the frame time and simulate back when I detect a collision).

For some reason

someBody.update(1.0);
someBody.update(-0.3);
someBody.update(-0.3);
someBody.update(0.6);

gives different results than:

someBody.update(1.0);

It might be because I use euler instead of RK4 or verlet?

Here's the code for the integrator:

void Body::update(double dt)
{
    if (dt > 0) velocity += acceleration * (dt*dt);
    else velocity -= acceleration * (dt*dt);
    pos += velocity * dt;
    rotation += angularVelocity * dt;
}

Thanks a lot!

Maarten

Upvotes: 0

Views: 472

Answers (3)

user826846
user826846

Reputation: 11

Thanks, the acceleration was indeed wrong.

I use a fixed timestep for each frame. This function is to run the simulation for partial frames. So I ignore the accaleraion completely now. This way everything within a frame happens linearly and the acceleration is only added in between frames.

The problem persists though. I think it might be the floating point errors as poited out by Magicianeer.

Although I think these errors would not add up so dramatically. In around 50 frames a bouncing object goes from it's full height (100) to about half that height. In around 200 frames it's still on the floor. When I don't call multiple the updates within the frame it's all fine.

I'll try keeping the position at the end of the frame and putting it back after doing the partial frame simulations. That way the errors won't add up over multiple frames.

Upvotes: 0

tomasz
tomasz

Reputation: 13072

The reason is math. Let's focus on velocity variable:

If you call:

someBody.update(1.0)

you'll get:

velocity += acceleration * 1

But if you call:

someBody.update(1.0);
someBody.update(-0.3);
someBody.update(-0.3);
someBody.update(0.6);

you will get:

velocity += acceleration * (1 - 0.3^2 - 0.32^2 + 0.6^2)

(which gives velocity += acceleration * 1.18)

You should have simply velocity += acceleration * dt;

Upvotes: 3

Magicianeer
Magicianeer

Reputation: 2180

Suspect floating point error accumulation in Body::update. Example: 1 + 2 + 3 + 4 = 10 but 1.0 + 2.0 + 3.0 + 4.0 = something else.

The easiest fix is to round the results after each major computation step.

Upvotes: 0

Related Questions