- Home /
calculating the thrust duration to apply to a body to reach a certain height
Im trying to create a helper function for an AI in my game and I need to calculate the duration required duration of applying a force to reach a certain height.
Note that I'm not looking to calculate an instantaneous force/velocity but something similar to how a rocket works, applying a continues force. I've tried looking for rocket equations but they take into consideration change in mass, drag, and other variables I don't need.
My current approach is like so, but it is unsuccessful and I can figure out why or to find another solution:
calculate the velocity needed to reach a height with the SUVAT equations.
calculating the acceleration of the body given the force applied and its mass
dividing the required velocity by the acceleration to get the duration
// m = mass, g = gravity, a = acceleration. float v = Sqrt(2 * g * height); float weight = m * g; float a = (thrust - weight) / m; float duration = v / a;
Any help would be greatly appreciated!
Answer by NanushTol · May 21 at 08:34 PM
I have extended @Bunny83 & @elenzil answers to include the initial velocity as well and I'm adding a detailed explanation after doing some more research.
To solve this problem we need to split the trajectory into 2 parts, the burn (the part where we fire the thruster) and the coasting (the free falling part, where the object is moving upward from the momentum of the thrust duration).
we will create 2 equations to solve "p" which is the height at which we turn off the thrusters. Then we will use "p" to find "t" our burnout time or burn duration.
SUVAT equation V^2 = u^2 +2as.
V = velocity at burnout
u = initial velocity
a = acceleration (F/m)
g = gravity;
s or p = displacement (height at burnout)
h = total height
EQ1, velocity at burnout, calculating from the ground to p:
V = sqrt(u^2 + 2(a-g)p)
EQ2, free fall velocity, calculating from total height to p, notice initial velocity here is 0 as the object
reaches 0 velocity when reaching the peek height:
V = sqrt(0 + 2g(h-p))
EQ3, now we can combine the 2 equations so:
sqrt(u^2 + 2(a-g)p) = sqrt(0 + 2g(h-p))
and solve for "p"
p = -((u^2-2gh)/(2a)
EQ4, now we want to solve for time so we can take s = ut+0.5*at^2 and plug that as our "p", notice that a refers to total acceleration so we will take that into account when rewriting the equation
ut+0.5*(a-g)*t^2) = -((u^2-2gh)/(2a)
now we can solve for "t"
t = (sqrt(ag(2ah - 2gh + u^2)) - au) / a(a - g)
// Test Script, Attach to a game object (cube, sphere or anything with a mesh & collider)
using UnityEditor;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class JumpToTarget : MonoBehaviour
{
public Vector3 thrust;
public float height;
private Rigidbody _rb;
private MeshRenderer _mr;
private float _burnDuration;
private float _burnTimer;
private bool _burnning;
private void Awake()
{
_rb = GetComponent<Rigidbody>();
_mr = GetComponent<MeshRenderer>();
}
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawLine(Vector3.up * (0.5f + height) + Vector3.back * 2f, Vector3.up * (0.5f + height) + Vector3.forward * 2f);
}
private void FixedUpdate()
{
if (_burnning)
{
_mr.material.color = Color.red;
if (_burnTimer >= _burnDuration)
{
_burnning = false;
}
else
{
_rb.AddForce(thrust, ForceMode.Force);
_burnTimer += Time.fixedDeltaTime;
}
}
else
{
_mr.material.color = Color.white;
}
}
private float sqrt(float value)
{
return Mathf.Sqrt(value);
}
public void Jump()
{
// t = (sqrt(a*g*(2*a*h-2*g*h+u*u))-a*u) / (a*(a-g))
float h = height - transform.position.y;
float g = -Physics.gravity.y;
float a = thrust.y / _rb.mass;
float u = _rb.velocity.y;
_burnDuration = (sqrt(a * g * (2 * a * h - 2 * g * h + u * u)) - a * u) / (a * (a - g));
_burnTimer = 0f;
_burnning = true;
}
}
#if UNITY_EDITOR
[CustomEditor(typeof(JumpToTarget))]
public class JumpToTargetEditor : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
JumpToTarget script = (JumpToTarget)target;
if (GUILayout.Button("Jump"))
{
script.Jump();
}
}
}
#endif
Answer by elenzil · May 18 at 07:23 PM
I can get you mostly there, I think.
I'm making heavy use of the formula for the speed of an object that's been accelerating over some distance.
h = the height you want to achieve. this is known.
a = the acceleration while thrust is on. this is known.
p = the height at which you will turn off the thrust. this is not known.
v(p) = the velocity at point p. this is not known.
our key insight is that we have two formulas for v(p):
one is the speed an object would have falling from h to p,
and the other is the speed an object would have accelerating up to p at acceleration a.
v(p) = the speed of an object falling from h to p.
so v(p) = sqrt(2g(h - p)).
but v(p) ALSO = the speed of an object accelerating at a over distance p.
so v(p) = sqrt(2ap).
so sqrt(2g(h-p)) = sqrt(2ap).
solving this for p, we find that p = gh/(a + g).
we also know that p = 1/2(a * t^2).
I think you can combine that with your knowledge of a (you have (thrust-weight)/mass) to calculate t.
thanks! I've never actually worked with unity physics; I'm curious how well these analytic calculations line up with the simulations.
An important detail is that "a" has to be the absolute acceleration. Since gravity is counteracting your thrust, it is actually subtracted from your pure acceleration due to thrust. So usually a = F/m
. However this would be the acceleration without gravity. This actually has some consequences in your result:
p = gh/(a + g)
Since "a" is actually "F/m - g" the actual calculation is the ratio between the upwards acceleration and the downwards acceleration. This scales "h".
p = h * g/(F/m)
This makes logically sense. If your thrust is exactly equal to "g" you get a ratio of 1, so you will have your max speed at the full height. However this is the extreme case which has no actual solution because if your thrust is not large enough to overcome gravity, you don't accelerate at all. So your max speed would be 0 which is also the speed you would have at the max height. Though the time here would essentially be infinite as you will never move at all :)
Though with a large enough force, say twice gravity, you would actually accelerate upwards at g. You would get half the height as the point where you have to turn off your thrust which makes sense since it takes the same amount of time / height to accelerate from 0 to top speed as it takes to decelerate back to 0 at the max height if the effective acceleration / deceleration is the same.
So the thrust duration would simply be this if I haven't made a mistake somewhere:
b = F/m
t = sqrt(2*h*g/(b*b-b*g))
So this would give you the thrust duration based on the thrust force F, the gravity g(positive value) and the desired max height.
I quickly hacked together a p5js example using the formula. Never really used p5, but I think it's a great tool for quick prototyping. Just press the play button. When you click on the actual canvas it should calculate the thrust time, start "thrusting" and automatically turns off after that time. The whole simulation is straight forward, though I used the half velocity trick to eliminate the issues due to discrete time steps. So it's not 100% the same in Unity but should be close.
Note: If you have a quite strong thrust so you reach your max speed quickly, the result could have a large error. The issue is that the simulation happens in discrete timesteps. So, one additional frame thrust could make a huge difference in such a case. Most the time you would probably undershoot the goal slightly. If you thrust one additional frame from the calculated time you will overshoot.
I love it !! Absolutely right on the complication due to my 'a' being absolute acceleration, not just thrust/mass. I figured that would fall out from OP's 'a = (thrust - weight)/m', where weight = mg. Looks equivalent. I made some tiny mods to your p5 demo. Never used it either, does seem like a great tool!
Thank you soo much ! this really helped!
I forgot to mention that I needed this with the initial velocity included into the calculation, So I've extended your initial approach and now it works really nicely. I will write up an organized answer and explanation now and will upload it. Thanks again!