Why does my position interpolation code result in “jumpy” motion?

I am developing an android game with box2d and use a fixed timestep system for advancing the physics.

However as I use this system it requires the box2d positions to be interpolates. I read this article and have implemented an interpolation method very much like the one in the article.

The method seems to work nicely on the computer but on my phone the positions of objects are very jumpy. There is of course a big frame rate difference between PC and phone, but I think this algorithm should not mind that.

Here is the just of the code if you don't feel like looking at the article :

void PhysicsSystem::smoothStates_ ()
{
const float oneMinusRatio = 1.f - fixedTimestepAccumulatorRatio_;

for (b2Body * b = world_->GetBodyList (); b != NULL; b = b->GetNext ())
{
if (b->GetType () == b2_staticBody)
{
continue;
}

PhysicsComponent & c = PhysicsComponent::b2BodyToPhysicsComponent (* b);
c.smoothedPosition_ =
fixedTimestepAccumulatorRatio_ * b->GetPosition () +
oneMinusRatio * c.previousPosition_;
c.smoothedAngle_ =
fixedTimestepAccumulatorRatio_ * b->GetAngle () +
oneMinusRatio * c.previousAngle_;
}
}


Does anyone know why my game is acting like this?

Thanks for the help

EDIT: Here is some logging as suggested in the comments bellow log data

EDIT2 : This log shows the jumpy effect I think ( you can see the position diff is sometimes positive and sometimes negative - and the object are just falling, it should be constant)log data 2

• what fixedTimestepAccumulatorRatio_ is and how it is computed? A log of your positions and interpolation alpha for the "jumpy" object can be very eloquent – FxIII Oct 19 '11 at 14:49
• fixedTimestepAccumulatorRatio is the alpha value which is the remaining time unprocessed divided by the fixed_timestep. I will make a log of those in a while. – Jason Oct 19 '11 at 15:02
• @FxIII: I have added some logging data for a single item in my game – Jason Oct 19 '11 at 15:20
• are those logging coming from the phone? – FxIII Oct 19 '11 at 19:19
• @FxIII yes they are – Jason Oct 19 '11 at 19:41

Looking at your second log file, I'm wondering if you're calling resetSmoothStates() in the right place?

On lines 42, 46, 50, and 54 you can see that the original position stays at a constant [661.2183], indicating there hasn't been a physics update. On line 43, it looks like you're smoothing between the previous original position, [671.2361], and the new one, [661.2183]. But on line 47 the interpolated value snaps to the new position, [661.2183], and stays there until you get a new physics update.

Make sure previousPosition_ is only being updated when there's a new physics update, not every frame. (i.e make sure you're only calling resetSmoothStates() inside of the for (int i = 0; i < nStepsClamped; ++ i) block)

• +1, I think you've nailed it. Somewhere, resetSmoothStates_() is being called when it shouldn't, causing all objects to jump to their latest calculated position and stay there until the next physics update. – Ilmari Karonen Oct 27 '11 at 23:08
• I Was away and did not get to check this but it could very well be it even though I think it is called every round but I will check – Jason Nov 3 '11 at 18:28

Problem:

Your computer can achieve the target fixed physics framerate, but your phone cannot.

Solutions:

1. Reduce the physics framerate (Increase FIXED_TIMESTEP).
2. Reduce the physics calculations needed per frame.
3. Do you absolutely need interpolation? Just render the uninterpolated state. Interpolation is only for making the rendering look smoother. Dropping it could significantly reduce the calculations required per frame.
4. Get a faster phone!

Explanation:

Check if the phone is hitting the MAX_STEPS constant. If it is, that means the phone cannot complete the physics calculations fast enough to achieve the (logical) fixed framerate. As a result it's cheating the physics simulator of some simulation time by capping how much more time can be added to the accumulator. This will of course change the resulting physics.

Glenn Fiedler explains it pretty well:

The spiral of death occurs when your physics simulation cannot keep up with the steps it’s being asked to take. If your simulation is told: “OK, please simulate X seconds worth of physics” and if it takes Y seconds to do so where Y > X, then it doesn’t take Einstein to realize that over time your simulation falls behind. In order to ensure a stable update, I recommend having some headroom. You really need to ensure that it takes significantly less than X seconds of real time to update X seconds worth of physics simulation. If you can do this then your physics engine can “catch up” from any temporary spike by simulating more frames. Alternatively you can clamp at a maximum # of steps per-frame and the simulation will appear to slow down under heavy load. Arguably this is better than spiraling to death, assuming of course that the heavy load is just a temporary spike.

• The frames per second on my phone is around 60 and the FIXED_TIME step is 1/60. Do you still think this is it? I also have a different version of MAX_STEPS (if the delta_time is larger then 0.25 then I keep it at 0.25 – Jason Oct 19 '11 at 16:21
• anyways.. after lots of checking this is not the issue – Jason Oct 20 '11 at 18:02