How to solve oscillating spring

Started by
16 comments, last by rumblesushi 10 years, 5 months ago

Hello,

I'm in the middle of making a futuristic racer, and in essence I'm using a sort of spring to keep the ships hovering above the track.

Very simple process. I cast a ray out of the bottom of the ship, along it's Y axis, and if the ray hits the road I calculate the magnitude of the penetration distance into the road.

Then simply do

velocity += roadNormal * (penetrationMag * k)

where k is 0.01

Obviously this does keep the ship hovering, but with constant bobbing up and down. I've tried a few (probably hacky) things, but just can't stop it at all.

Any good ideas of how to implement damping on a simple spring system like this?

Cheers.

Advertisement

Try something like this:

velocity += roadNormal * (penetrationMag * k - small_number * component_of_the_velocity_along_roadNormal);

Look up "damped harmonic oscillator" if you want to learn the math behind it.

The equation of motion should be,

M*a+C*v+K*x = F

Where we have mass, M, acceleration, a, Damping constant, C, velocity, v, spring stiffness, K, position, x, and applied force F.

Noting the differential terms, v = dx/dt, and a = dv/dt.

Normally we divide this system through by mass so that,

a + (C/M)*v + (K/M) * x = F/M

We then turn this into a linear system of ordinary differential equations.

x1 = x

x2 = dx1/dt

x3 = F/M - (C/M)*x2 - (K/M) * x1

Applying Eulers method, noting that x1-x3 are functions of time, we get,

x1(t+1) = x1(t)+h*x2(t)

x2(t+1) = x2(t) + h*x3(t)

where for clarity,

x3(t) = F/M - (C/M)*x2(t) - (K/M) * x1(t)

and h is your time step.

Thanks for the replies.

Alvaro, so just project the velocity onto the roadNormal? How small a number would you imagine to work best?

If I can't get the correct behaviour by tweaking my existing function with this, I'll rewrite it with brucedjones' equations.

As it happens subtracting a % of the velocity was one of the first things I tried (as per damped spring equations), but it made the ship go haywire and bounce miles into the air.

I thought my overall implementation must be too different for it to work, but actually I just had to invert the projected velocity onto the y axis.

That works very well and does indeed stop the infinite oscillations.

With a spring stiffness coefficient of 0.01, and a physics rate of 120hz, I found I needed a damping coefficient of around 0.04 to stop bounciness. 0.01 results in a very bouncy ship, that takes a while to settle at the target spring length. 0.06 settles quick with no bouncing but has a weaker spring, sometimes resulting in the ship hitting the ground.

What do you think is the best way of keeping the ship stuck to the track like glue (or like a rollercoaster), as if there is an infinite amount of gravity, so it never leaves the track? Having a huge amount of gravity is no good as the spring then becomes too weak. What I want is to have a method of keeping it exactly to the track as descrived, then switching to a normal gravity behaviour when going over a designated jump pad.

Instead of the spring, maybe implement it as "thrusters".

Basically allow your ship to apply a force towards/away from the track to control its elevation. Maintain a "desired" elevation (setpoint). Then you "just" need a control algorithm to set your required force amount to maintain that set point.

That algorithm could be something simple like PID.

Or since in game's programming our system is already following a known "model" you could use a model predictive controller.

IE: Your ship knows its mass. It knows all the external forces acting on it. Your ship also can "look ahead" a few time steps and see how the track will change. From this you can calculate a required "vertical thruster force" to hold your elevation.

Essentially you need to solve for:

"What force do I need to add to this system to make my elevation equal to "y" at t+dt (the next time step)?"

When you want to "jump" and be subject to gravity normally, you just disable the thrusters.

Hell, throw a graphical thruster particle effect on there, and it might make for a nice looking feature.

I don't see why you would allow bobbing. If the current velocity would cause penetration (downwards into the road), you can project the computed velocity along the tangent plane of the road (i.e. a bit of slow down due to friction) and use that, possibly triggering an extra slowdown or an accident if the interpenetrating velocity or displacement component exceeds some threshold. If velocity points away from the road, or into the road but with no immediate collision, you can apply a vertical thrust to maintain the desired height as CombatWombat suggests.

Omae Wa Mou Shindeiru

Actually I was considering something like the thruster particles, as although my engine is a slow, web based software engine, particles are one thing I can do fast.

One thing though, how is the thruster implementation significantly different to a spring? They both apply a force proportional to current length Vs target length. Is the main difference in your suggestion the lack of gravity?

I read up on PID too, thanks for the tip, seems like the tricky part is just tweaking the 3 numbers to get the desired behaviour.

I don't see why you would allow bobbing. If the current velocity would cause penetration (downwards into the road), you can project the computed velocity along the tangent plane of the road (i.e. a bit of slow down due to friction) and use that, possibly triggering an extra slowdown or an accident if the interpenetrating velocity or displacement component exceeds some threshold. If velocity points away from the road, or into the road but with no immediate collision, you can apply a vertical thrust to maintain the desired height as CombatWombat suggests.

Purely because a spring was the first thing I tried, and before I successfully implemented damping to the spring, the bobbing is a byproduct of basic undamped spring+gravity.

The bobbing is eliminated entirely now, I'm just playing with gravity being switched on an off, and about to try Combat's PID implementation and no gravity, rather than a spring.

The bobbing is eliminated entirely now, I'm just playing with gravity being switched on an off, and about to try Combat's PID implementation and no gravity, rather than a spring.

I'm not suggesting you ever disable gravity. That's kind of hacky and leads to programming for special cases.

I see a few options.

1) Have a thruster force normal to the track. You measure your currect height vs your desired height. This is "error" in your PID loop. Adjust PID parameters to get the desired effect. This will not be completely rigid, but it should look pretty "natural", since if you had a real hovering race ship, it would probably work something like this.

2) Take your current position at time t. Predict a new position at t+dt. (Use the integrator you already have). Find the height over the track at P(t+dt) (predictedHeight). Take a unit vector normal to your track that passes through P(t+dt). Scale it by desiredHeight / predictedHeight. This gives you a point P(goal) at (t+dt).

You can directly rotate your velocity vector such that it passes through P(goal).

You can calculate a force required to do this and apply it to your physics model.

This topic is closed to new replies.

Advertisement