Steve
Steve

Reputation: 85

NSV, Euler Integration Confusion

I'm trying to get my head around these integration methods and I'm thouroughly confused.

Here is the code:

public void update_euler(float timeDelta){
    vPos.y += vVelocity.y * timeDelta; 
    vVelocity.y += gravity.y * timeDelta;
}


public void update_nsv(float timeDelta){    
    vVelocity.y += gravity.y*timeDelta;
    vPos.y += vVelocity.y * timeDelta; 
}


public void onDrawFrame(GL10 gl) {      
    currentTime = System.currentTimeMillis();
    float timeDelta = currentTime - startTime;
    startTime = currentTime;
    timeDelta *= 1.0f/1000;;

//  update_RK4(timeDelta);
//  update_nsv(timeDelta);
//  update_euler(timeDelta);
//  update_velocity_verlet(timeDelta);
}

Firstly, I just want to make sure I've got these right.

I am simulating a perfectly elastic ball bouncing, so on the bounce I just reverse the velocity.

The Euler method, the ball bounces higher on each bounce. Is this due to an error in my code or is this due to the innacuracy of the method. I've read that with the Euler integration you lose energy over time. Well I'm gaining it and I don't know why.

The nsv method: I don't quite understand how this is different to the Eular method, but in any case the ball bounces lower on each bounce. It is losing energy which I've read isnt meant to happen with the nsv method. Why am I losing energy?

(The velocity verlet and RK4 methods are working as I'd expect them to).

I get the impression I'm lacking a fundamental bit of information on this subject, but I don't know what.

I do realise my timestep is lacking, and updating it to run the physics using a static timestep would stop me losing/gaining energy, but I am trying to understand what is going on.

Any help would be appreciated.

Upvotes: 0

Views: 326

Answers (3)

duffymo
duffymo

Reputation: 308938

The integration introduces artificial damping into the system. I believe you can determine ho much by doing a Fourier analysis on the integration scheme, but I'd have to refresh my memory on the details.

Upvotes: 0

btilly
btilly

Reputation: 46445

To add another option to @Beta's answer, if you average the two methods, your error should disappear (except for issues around handling the actual bounce).

public void update_avg(float timeDelta){    
    vVelocity.y += gravity.y*timeDelta/2;
    vPos.y += vVelocity.y * timeDelta; 
    vVelocity.y += gravity.y*timeDelta/2;
}

What I'm doing here is updating the velocity to the average velocity over the interval, then updating the position based on that velocity, then updating the velocity to the velocity at the end of the interval.

If you have a more complicated scenario that you want to model, consider using the Runge-Kutta Method to solve differential equations of the form y' = f(x, y). (Note that here y can be a set of different variables. So in your case you'd have d(position, velocity)/dt = (velocity, -gravity). And the code I gave you works out to be the same as the second-order version of that method.

Upvotes: 2

Beta
Beta

Reputation: 99134

In real life, the ball moves upward and decelerates, reaches the apex (apogee) where its velocity is zero for a split-second, then moves downward and accelerates. Over any time interval it is exchanging kinetic energy (being fast) with potential energy (being high).

In the Euler method, it moves with constant velocity for the duration of the interval, then at the end of the interval it suddenly changes its velocity. So on the upward journey it goes up at high speed, then slows down, having gained more altitude than it should have. On the downward leg it creeps down slowly, losing little altitude, then speeds up.

In the nsv method, the opposite happens: on the way up it loses speed "too soon" and doesn't get very high, on the way down it hurries and reaches the ground without building up much speed.

The two methods are the same in the limit as timeDelta goes to zero. (If that statement made no sense, don't sweat it, it's just calculus.) If you make timeDelta small, the effect should fade. Or you could use energy as your primary variable, not {position, velocity}, but the math would be a little more complicated.

Upvotes: 1

Related Questions