Stable Spring Physics

860fe478a2545d6c07b88c759292499e
0
SmokingRope 101 Dec 10, 2008 at 18:07

Hello, i’m playing with 2D physics. I’ve got this object i want to oscillate. I decided that the motion of a spring would be ideal for representing this oscilation. The object is at maximum velocity at the spring’s resting point (R) and gradually decelerates until at some distance (D) the object stops and starts going the other way. I want to maintain the distance D so it oscillates forever.

I’m using velocity-verlet integration, i’ve tried a few things and my object doesn’t want to adhere to that stopping distance D.The theoretical spring constant k=1 where it should be stable, instead means it skyrockets out of control, anything less means it does so faster, any more and it eventually comes to rest. I tried adding a small damping force to it but this also makes it stop.

I’m not altogether surprised, and am pretty sure I need to fake-it. What I am thinking of doing is waiting for the object to get close to R, and if the velocity exceeds the desired speed, i’ll correct it. I could also wait for the object to get to D and zero the velocity out. Is there any best solution to this or can i just kinda pick one at my leisure?

4 Replies

Please log in or register to post a reply.

8676d29610e6c98d6dd2d9c38528cd9c
0
alphadog 101 Dec 10, 2008 at 20:09

What’s wrong with a simple harmonic oscillator?

x(t) = A cos(sqrt(k/m) * t)

where A is the initial displacement, k is your spring constant, m is the mass and t is time.

860fe478a2545d6c07b88c759292499e
0
SmokingRope 101 Dec 11, 2008 at 01:28

I’ve tried to adhere to a strict component-based design. Presently i just have my verlet physics component. I can probably extract the interface and make the simple harmonic oscillator fit nicely.

My project includes more than just oscillating springs, and i hadn’t even considered breaking out of my physics system! :lol:

8676d29610e6c98d6dd2d9c38528cd9c
0
alphadog 101 Dec 11, 2008 at 14:21

From my unexperienced and peripheral understanding, you should be able to get Verlet to work. Dampening is not what you want, as this simply is a force that slowly forces the system back to equilibrium. Rather, you need to impose constraints, which usually involves correcting for position.

Another good place for this would be GameDev’s physics forum. I’ve seen lots of spring system discussions there, including Verlet/Euler/RK stuff…

860fe478a2545d6c07b88c759292499e
0
SmokingRope 101 Dec 11, 2008 at 23:11

I haven’t searched Gamedev specifically, but my understanding is that there is no cure-all for instability with spring forces.
The reason springs are unstable is because the fixed time step means that sometimes things overshoot.

I went ahead and wrote a generic solution that manually recalculates the velocity as it passes over the spring’s resting point. This works.

PositionComponent *l_pos = (PositionComponent*)component(GameObject::CID_POSITION);
PhysicsComponent *l_phys = (PhysicsComponent*)component(GameObject::CID_PHYSICS);
const float g_SpringConstant = 1.0f;
const float g_Mass = 1.0f;
const float g_Distance = 32.0f;

Vector2 l_tangent, l_perp;

l_tangent = l_pos->get() - m_Center;

if( l_tangent.Length2() < 1.0f )
{
    l_perp = l_tangent;
    l_perp.Perp();
    l_perp.Normalize();

    float l_dist = l_tangent.Magnitude();
    l_tangent.Normalize(l_dist);
    l_dist = sqrt((g_Distance - l_dist)*(g_Distance - l_dist)*g_SpringConstant/g_Mass);

    l_perp = l_perp.Dot(l_phys->velocity()) * l_perp;
    l_tangent = l_tangent.Dot(l_phys->velocity()) * l_tangent;
    l_tangent.Normalize();

    l_phys->setVelocity(l_perp + l_tangent * l_dist);
}

my spring is oscilating on the X-axis (mass and the spring constant are also one) so this is an overly complicated solution, but the idea is:

don’t touch the component of the velocity that is perpendicular to the spring force
make the component that is tangent to the spring force have the expected value.

The only problem here is if my oscillating object overshoots too much when it passes the center.