# Projectile Range Equation in 3D Space

1. Jul 18, 2009

### Macmenace

Hi,

I'm working on a computer simulation to launch an object from point A to point B in 3D space.

I'm currently using the range equation:

Range = ( Vo^2 * sin( 2 * theta ) ) / gravity

and I solved for Vo and got:

Vo = sqrt( ( Range * gravity ) / sin( 2 * theta ) )

I'm currently using a constant theta of 45 degrees, and this equation works perfectly for launching an object when A and B's y-component are the SAME. If the y-component varies the object over shoots or under shoots its target.

My problem is that the y-component of A and B can be different. Is there another equation or consideration I should take into account if I want to know the initial velocity an object needs to travel a specific range in 3D space?

2. Jul 18, 2009

### Nabeshin

The theta in the range equation is the angle with respect to the x-y plane the projectile is being launched at. The range equation makes no account for the angle with respect to, say, the x-axis, that the projectile is being launched in (The line AB and the x-axis).

So if you want to hit a target B, you have to also factor in the angle $$\phi$$ that the line AB makes with the x-axis, because this is the angle you want to fire at. I hope this can make some intuitive geometric sense to you.

Assuming the point A to be at the origin and point B to be represented in cartesian coordinates (x,y), then:
$$\phi=\arctan{\left(\frac{y}{x}\right)}$$

Hope this helps!

3. Jul 18, 2009

### cepheid

Staff Emeritus
Hello Macmenace, Welcome to PF!

A and B are just points in space, so it doesn't make much sense to talk about their "y-component." Do you mean their y-coordinates are different (i.e. A and B are at different heights?). If so, your range equation is not valid, because it was derived under the assumption that the projectile starts and ends at y = 0. To show this explicitly, we have the two equations for the particle's trajectory (which come from basic kinematics:

$$y(t) = y(0) + v_y(0)t - \frac{1}{2}gt^2$$​
$$x(t) = x(0) + v_x(0)t$$​

Now, you figure out for what duration the projectile will be in the air $t_f [/tex] by solving for y(t) = 0 (meaning the projectile has hit the ground again). You also assume that it starts on the ground (y(0) = 0). Can you see that neither of these assumptions is valid in your case? Anyway, let's see what happens when we make these assumptions first, and then go back later and do the derivation without these assumptions: $$y(t) = y(0) + v_y(0)t - \frac{1}{2}gt^2$$​ $$0 = 0 + v_y(0)t_f - \frac{1}{2}gt_f^2$$​ $$v_y(0) t_f = \frac{1}{2}gt_f^2$$​ We see from this that: $$t_f = \frac{2v_y(0)}{g}$$​ To see how far horizontally the projectile will travel during this time interval we calculate: $$x(t_f) = x(0) + v_x(0)t_f$$​ Let's assume x(0) = 0. Then the range is given by: $$x(t_f) = v_x(0)\frac{2v_y(0)}{g}$$​ $$x(t_f) = \frac{2v_x(0) v_y(0)}{g} = \frac{2v(0)\cos \theta v(0) \sin \theta}{g} = \frac{2v^2(0)\cos \theta \sin \theta}{g} = \frac{v^2(0) \sin(2 \theta)}{g}$$​ This is your range equation and you can see that it is ONLY valid under the assumption that the projectile starts and ends at y = 0. If, instead, we assume that the projectile starts at height yA and ends at yB, then we must go back and re-derive the range equation under these new assumptions. For convenience, let's set yA = 0. Then we have: $$y_B = 0 + v_y(0)t_f - \frac{1}{2}gt_f^2$$​ This is a quadratic equation for t, the solution of which is: $$t_f = \frac{v_y(0)}{g} \pm \sqrt{\frac{v_y^2(0)}{g^2} - \frac{2}{g}y_B}$$​ Some notes: 1. there are two times at which the projectile reaches height yB. The first is the earlier time (on the way up). The second is on the way down (the later time). We are concerned with the later one (which corresponds to the plus sign). 2. The part under the square root is negative ONLY if [itex] v_y^2(0) < 2gy_B$ which corresponds to the case in which the projectile does not have enough initial energy to reach height yB in the first place and therefore there is no solution. We will assume that the projectile is given enough energy.

Plugging this value for the time to reach yB into the x equation, we obtain:

$$x(t_f) =\frac{v^2(0) \cos \theta \sin \theta}{g} + v(0)\cos \theta \sqrt{\frac{v^2(0)\sin^2 \theta}{g^2} - \frac{2}{g}y_B}$$​

THIS is your new range equation. Now all you have to do is solve for theta. (LOL! Not so easy as it sounds...)

EDIT: Or you could decide on a theta and solve for v(0) (easier).

Last edited: Jul 18, 2009
4. Jul 18, 2009

### Macmenace

Wow! Thank you for the swift and in depth replies.

Solving for theta would be nuts so I decided to keep it a constant 45 degrees and solve for Vo as you suggested.

$$x(t_f) =\frac{v^2(0) \cos \theta \sin \theta}{g} + v(0)\cos \theta \sqrt{\frac{v^2(0)\sin^2 \theta}{g^2} - \frac{2}{g}y_B}$$

I began by evaluating my constants and made:

$$C0 =\frac{\cos \theta \sin \theta}{g}$$

$$C1 =\cos \theta$$

$$C2 =\frac{\sin^2 \theta}{g^2}$$

$$C3 =\frac{2}{g}$$

And got:

$$Range^2 = C0 v^2(0) + C1 v(0) \sqrt{C2 v^2(0) - C3 y_B}$$

Now this is where my algerba becomes painfully rusty. I got this far but have no idea how to solve for V(0) from here?

$$Range^2 = v^2(0)( (C0^2 + C1^2 C2) v^2(0) - C1^2 C3 y_B} )$$

Am I headed down the right track and how should I finish this?

5. Jul 19, 2009

### cepheid

Staff Emeritus
Hi Macmenace,

To avoid clutter, I am going to replace the function notation ( v(t) evaluated at t = 0 was denoted v(0) ) with just v0 for the initial speed.

I think there is a problem with your expression. You wrote:

$$(\textrm{range})^2 = C_0 v_0^2 + C_1v_0 \sqrt{C_2 v_0^2 - C_3 y_B}$$
However, this is just the expression for the range, not the range squared:

$$\textrm{range} = C_0 v_0^2 + C_1v_0 \sqrt{C_2 v_0^2 - C_3 y_B}$$

If you were going to square it, it would become:

$$(\textrm{range})^2 = \left[ C_0 v_0^2 + C_1v_0 \sqrt{C_2 v_0^2 - C_3 y_B} \right]^2$$

$$= \left[ C_0 v_0^2 + C_1v_0 \sqrt{C_2 v_0^2 - C_3 y_B} \right] \left[ C_0 v_0^2 + C_1v_0 \sqrt{C_2 v_0^2 - C_3 y_B} \right]$$

Now, to expand this, every term in the first expression in square brackets would have to be multiplied by every term in the second expression in square brackets. I think you can see that this is not going to help us much. So the answer is, I'm not sure how to solve this algebraically.

To be honest, I just solved this graphically. I.e. I plotted range as a function of v0 for a given θ = π/4 (45 degrees). I then figured out for what value of v0 my range would have the desired value. Using a value for the range of 100 m and a height of yB = 10 m, I obtained a v0 of around 33 m/s.

Nabeshin's post got me thinking that there might be an easier way to do this. It's quite true that we can use a line drawn from A to B to define a new coordinate system that is inclined relative to the one we're using. I.e. we define xʹ and yʹ axes that are rotated counterclockwise compared to the x and y axes by an angle ϕ given by:

$$\phi = \arctan\left(\frac{y_B}{x_B}\right)$$

as Nabeshin said. This is shown in the figure below.

http://img204.imageshack.us/img204/4369/projectile.th.jpg [Broken]

The thinking is that, relative to the primed axes, the projectile starts and stops at the same "height" (yʹ = 0), leading us to hope that the algebra might be simpler in this coordinate system. When we write down our equations of motion, we have to make sure that we project the effect of gravity into components along these new axes so that:

$$y^{\prime} = v_0 (\sin \alpha)t - \frac{1}{2}(g \cos \phi)t^2$$

$$x^{\prime} = v_0 (\cos \alpha)t - \frac{1}{2}(g \sin \phi)t^2$$ ​

where α is the launch angle relative to the xʹ axis, as shown.

We can solve for the final time tf once again from the condition that yʹ = 0 at the end of the motion, obtaining:

$$t_f = \frac{2v_0 \sin \alpha}{g \cos \phi}$$ ​

Substituting this into the xʹ equation gives us:

$$x^{\prime} = v_0^2 \frac{\sin(2 \alpha)}{g \cos \phi} - v_0^2 \frac{2 \sin \phi \sin^2 \alpha}{g \cos^2 \phi}$$ ​

This is much easier to solve because it is of the form:

$$x^{\prime} = v_0^2 (C_1 - C_2)$$ ​

There are two "tricks" that we have to keep in mind:

1. If we want the actual launch angle θ with respect to the ground (x-axis) to be 45 degrees, then we must bear in mind that:

θ = α + ϕ​

Therefore:

α = π/4 - ϕ​

(This is clear from looking at the picture)

2. xʹ is not the range, it is the distance travelled along the xʹ axis. If we want the range, we must bear in mind that:

xʹ = x/cosϕ​

(This is also clear from looking at the picture)

Substituting in the values for the angles, and using xB = 100 m, yB = 10 m, I obtain v0 = 33.0151 m/s, which is in agreement with my previous result. The difference is that by working in the primed coordinate system, I was able to solve the problem algebraically. I'm not sure if this is what Nabeshin had in mind, but it works.

Last edited by a moderator: May 4, 2017
6. Jul 19, 2009

### Macmenace

Sorry for the late reply. Thank you for going to all the trouble of graphing and beginning to expand the formula.

I sat down with a friend last night and we worked out a solution that works exceedingly well in game simulation standards, but cheats a little bit physics wise.

I will post the solution we came up with in C++. It is pretty easy to follow, hopefully I commented it well. The one somewhat hazy portion is that you have to choose a "arc height" for the projectile rather than a angle. We just made this "arc height" a scaler of the distance between the start and end points.

Here it is:

Code (Text):

Vector3 CalcArcVelocity( Vector3& dir, float horChange, float vertChange, float arcScale )
{
//Normalize the direction vector.
dir.Normalize();

//Decide on the highest vertical height to shoot for,
//this is arbitrary based on what type of arc you are trying to achieve.
float clampedVertChange = Clamp( arcScale * vertChange, MIN_ARC, MAX_ARC );
//The delta of the total vertical change and the change you are shooting for.
float vertDelta = clampedVertChange - vertChange;

//Get the gravity magnitude, 9.8 m/s^2
float gravMag = -PhyDefines::phyData.GRAVITY.Magnitude();

//How long it will take to reach the apex of our launch.
float timeUp = real_sqrt( clampedVertChange / (-0.5f * gravMag ) );
//How long are total flight will take.
float timeTotal = timeUp + real_sqrt( vertDelta / (-0.5f * gravMag ) );

//The initial velocity along the y-axis.
float v0YMag = -gravMag * timeUp;
//The initial velocity in the xz-plane.
float v0XZMag = horChange / timeTotal;

//Our final initial velocity vector.
return Vector3( dir.x * v0XZMag, v0YMag, dir.z * v0XZMag );
}

Thank you again for all the information. It was a supreme help!