Calculating angular acceleration with moment of inertia

Godot Version

4.6.1 (double precision build)

Question

Hi everyone,

I am trying to verify some calculations for a pilot AI against the engine, so I’m currently writing some test scenarios.
I am struggling a lot when it comes to angular acceleration, specifically the moment of inertia. It probably doesn’t help that my math isn’t great, so please excuse any obvious errors.

I have prepared a small test scene that you can find here: GitHub - RinneT/godot-angular-physics-test: Test scenario for calculation of angular movement in Godot · GitHub

Note that while I use a double precision build of Godot, that should not be required to run the scene.

I have written two functions to calculate

  • the rotation in radians after constant acceleration in rad/sec² over a given time in seconds.
  • the torque in Nm required to achieve the constant acceleration
## Calculate the Angular rotation after time (along a single axis)
## https://www.sciencing.com/revolutions-angular-acceleration-5805078/
## Params:
## angle_start: Starting angle of the object
## ang_velocity_start: Starting angular velocity
## acceleration: constant acceleration
## time: time
func get_rotation_from_angular_acceleration(angle_start: float, ang_velocity_start: float, acceleration: float, time: float) -> float:
	return angle_start + ang_velocity_start + 0.5 * acceleration * pow(time, 2)

## Get the torque required for a given acceleration
## Params
## moment_of_inertia: Moment of Inertia in kg/m²
## accelertaion: acceleration in rad/sec²
func get_torque_for_acceleration(moment_of_inertia: float, acceleration: float) -> float:
	return moment_of_inertia * acceleration	

As input, I need the moment of inertia, which I get via:
PhysicsServer3D.body_get_direct_state(test_capsule.get_rid()).inverse_inertia.inverse()
I know that I can also get it via the inertia_tensor, but the values are the same.

Currently I restrict any acceleration to the x-axis for simplicity.
Unfortunately, the resulting acceleration is far off from what is predicted.
I wonder if the moment of inertia unit is wrong. For the formula above, it needs to be in kg/m².

I also notice that there is a strong difference between applying torque each tick, and setting a constant torque once.
The test scene in the Github repo has a toggle to switch between the two.

I apply the torque as follows (not ideal, but I thought it works as a test case):

## Not very efficient, but this is a proof of concept, after all
func _process(delta: float) -> void:
	if (apply_torque_constant && constant_torque.is_equal_approx(Vector3.ZERO)):
		add_constant_torque(requested_torque)
	else:
		apply_torque(requested_torque)

Any help to understand what is happening and if I’m doing anything fundamentally wrong would be greatly appreciated.

You should use a

_physics_process(_delta:float):

instead of _process(_delta:float)

as the former is called every time a physics tick happens.

So yes

torque = I × alpha

And you might also want to try the function

apply_torque_impulse

Heres a result from a google search, take a look at the _physics_process() function

1 Like

They are not the same. inertia tensor is a basis and it will change as the body rotates.

Try this: apply the torque each tick in _physics_process(). To calculate the torque get the inertia tensor and just transform the angular acceleration vector by it. Angular acceleration vector should have direction that coincides with the rotation axis and magnitude equal to acceleration magnitude.

So:

func _physics_process():
	var inertia_tensor: Basis = PhysicsServer3D.body_get_direct_state(get_rid()).inverse_inertia_tensor.inverse()
	var alpha_magnitude = 5.0
	var alpha = Vector3(1.0, 1.0, 1.0).normalized() * alpha_magnitude
	apply_torque(inertia_tensor * alpha)
1 Like

You guys are amazing, I didn’t expect a response so quickly!

Moving the torque application to _physics_process() already fixes the issue on one axis!
I’ll add a handle to modify the axis for the inertia_tensor, as I think I need a bit more hands-on to understand it better.

Thanks so much!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.