My 3D RigidBody harmonic oscillator is unstable. Help please!

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By cschlick

I am trying to connect rigid bodies by springs. I created this test project trying to do a simple harmonic oscillation around an equilibrium position, but the oscillations are unstable, with progressively increasing magnitude.

If I wasn’t using Godot, I would use velocity verlet to do the integration and change position explicitly. But from reading the documentation, it seems that using RigidBody add_force() is preferable. But maybe I am using it wrong… Any tips are really appreciated.

The example project is here: GitHub - cschlick/Harmonic-Oscillator: Simple harmonic oscillator using godot

And the key part is:

extends RigidBody
    
# starting position of the RigidBody is Vector3(0,2,0)
 	
func _physics_process(delta):

	var pos = global_transform.origin # the current position
	var eq_position = Vector3(0,0,0) # the equilibrium position
	var m = 1 # mass
	var x = (pos-eq_position) # displacement from equilibrium position
	var k = 10 # spring constant
	var f = -k*x # Hookes law
	add_force(f,Vector3(0,0,0))

An update, instead of calculating the force using the body’s current position, I extrapolate a new position after the delta. This makes a huge improvement, but there is still a very small amount of instability. I think for my purposes this will work, but I will leave this open for a while to see if anyone has any comments.

func _physics_process(delta):
	var current_pos = global_transform.origin
	var future_pos = current_pos+linear_velocity*delta
	var eq_position = Vector3(0,0,0) # the equilibrium position
	var m = 1 # mass
	var x = (future_pos-eq_position) # displacement from equilibrium position
	var k = 10 # spring constant
	var f = -k*x # Hookes law
	add_force(f,Vector3(0,0,0))

cschlick | 2020-04-28 18:18