• Create Account

## How to solve oscillating spring

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

17 replies to this topic

### #1rumblesushi  Members

159
Like
0Likes
Like

Posted 10 October 2013 - 04:44 PM

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.

### #2Álvaro  Members

20272
Like
3Likes
Like

Posted 11 October 2013 - 07:12 AM

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.

### #3brucedjones  Members

850
Like
2Likes
Like

Posted 11 October 2013 - 07:50 AM

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.

Edited by brucedjones, 11 October 2013 - 07:54 AM.

### #4rumblesushi  Members

159
Like
0Likes
Like

Posted 13 October 2013 - 02:09 PM

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.

### #5rumblesushi  Members

159
Like
0Likes
Like

Posted 20 October 2013 - 12:48 PM

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.

### #6CombatWombat  Members

617
Like
0Likes
Like

Posted 21 October 2013 - 10:52 AM

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.

### #7LorenzoGatti  Members

4094
Like
0Likes
Like

Posted 22 October 2013 - 02:11 AM

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

### #8rumblesushi  Members

159
Like
0Likes
Like

Posted 22 October 2013 - 01:10 PM

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.

### #9rumblesushi  Members

159
Like
0Likes
Like

Posted 22 October 2013 - 01:33 PM

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.

### #10CombatWombat  Members

617
Like
0Likes
Like

Posted 23 October 2013 - 08:22 AM

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.

### #11rumblesushi  Members

159
Like
0Likes
Like

Posted 23 October 2013 - 09:30 PM

Ah I see.

So being that a damped spring does work fine, hover wise, your reason for suggesting a PID thruster was just for better hover behaviour? Smoother and faster transitions to the desired hover height?

Also, could you explain your 2nd point a little more? In particular, I don't understand this line "Take a unit vector normal to your track that passes through P(t+dt)". Everything else makes sense.

Regarding disabling gravity, I recently played Wipeout 2048 - and noticed that in the zone tracks, you stick to the track like glue (or like a rollercoaster) even when going over a steep vertical drop. As if there is no gravity as such, more that your ship is constantly being adjusted to be a set height, as if the PID algorithm for example was adjusting the "error" below or indeed above your desired hover height. Or a bit like spline following behaviour.

In contrast, normal races in 2048 have standard gravity behaviour, more like what I have now in my game, where by going over a large drop would have you soaring through the air and landing a couple of seconds later.

### #12CombatWombat  Members

617
Like
0Likes
Like

Posted 24 October 2013 - 07:53 AM

Also, could you explain your 2nd point a little more? In particular, I don't understand this line "Take a unit vector normal to your track that passes through P(t+dt)". Everything else makes sense.

The point P(t+dt) is your prediction of where you will be at the next time step.

If you draw a line from P(t+dt) to the track, making the line end up perpendicular (normal) to the track surface, that is essentially your "predicted" elevation.

For example, you find this line and it's length is 5 units.  You want to maintain an elevation of 10 units.  You can now extend that line to make it 10 units long.  The new endpoint of that line becomes P(goal).  Now you just need to rotate your velocity vector to intersect with P(goal).

This is very similar to what Lorenzo Gatti said with:

"If the current velocity would cause penetration (downwards into the road), you can project the computed velocity along the tangent plane of the road."

Except that projecting the velocity vector will shorten it (slowing you down).

Rotating the velocity vector will maintain it's length.  Both are valid options depending on what you want.

If you allow rotating your velocity vector both TOWARDS and AWAY from the track, you will get the "spline following" behavior.

If you allow rotating your velocity vector only AWAY from the track, you will not crash into the track, but you will float over jumps normally.

If it were my game, I would go the extra step and compute forces needed to actually create this change in velocity and feed them to the physics engine just like any other force.  This isn't absolutely necessary, but I think it can help to avoid weird edge cases in behavior.

### #13rumblesushi  Members

159
Like
0Likes
Like

Posted 24 October 2013 - 11:04 AM

Cheers Wombat, that's very clear. It was mainly the "passes through" that I found confusing.

It's actually my own physics engine I use, built to be as fast as possible as I use software rendering. I apply the forces before the objects get updated by my physics engine. So yes, they do get added and updated like any other force, it's not a seperate integration.

I'll try out the 2 way velocity adjustment to see if that gets the behavour I want, like the Wipeout zone tracks.

For stability I'm also applying one force per ship. I use 4 additional raycasts just for track orientation.

### #14rumblesushi  Members

159
Like
0Likes
Like

Posted 01 November 2013 - 11:53 AM

CombatWombat - thanks again for recommending PID. Such a simple, clever little algorithm. It was very easy to implement in place of the spring too.

Amazing how closely and smoothly it manages to stick to the target hover height too, despite massive fluctuations in altitude and velocity.

The only slight problem I'm having is a bit of bumpiness on low poly collision geometry, specifically angled bends. It's similar to a very stiff spring in that it doesn't absorb shocks well enough. You get micro judder round inclined bends, where the spring would absorb those quick, sharp changes in terrain perfectly.

The best settings I've found so far for my uses are 0.05, 0.000001, and 0.19 for PID.

### #15Álvaro  Members

20272
Like
0Likes
Like

Posted 01 November 2013 - 12:00 PM

You may want to do something about the coarseness of your track. Even if the underlying track is polygonal, you could use some smooth interpolation between "nodes" or however your track is described.

### #16rumblesushi  Members

159
Like
0Likes
Like

Posted 01 November 2013 - 04:26 PM

I agree, it's always been a problem, having low poly geometry.

I can have seperate collision geom to render geometry, but part of the problem is I develop web games, so (relatively) high poly collision geom is going to add to the file size.

What do you mean by nodes? Spline points or something else? I have a spline for CPU steering and position calculation, and a big triangle mesh for the track.

### #17Álvaro  Members

20272
Like
0Likes
Like

Posted 03 November 2013 - 02:22 AM

Yes, I mean something like spline points. Your collision geometry could be continuously differentiable, described by something like a spline, and then you don't need it to take much space.

### #18rumblesushi  Members

159
Like
0Likes
Like

Posted 03 November 2013 - 02:12 PM

Sure, that would be ideal. I've never experimented with generating geometry from a spline before, do you happen to know of a good reference? Right now my splines are just a series of points used for various things like CPU steering and object placement. They have no bezier curves etc, they are just points.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.