Find the angle to hit target at x,y,z

Hello,

I have an initial velocity, a target, height difference.

I am having a hell of a time trying to figure out how to shoot a projectile so that it hits the target.

So I think I need to find the angle of which to shoot the missile to reach the target.

I had an equation like : angle = 1/2 Mathf.Asin(gravity * distSqr - 2 * Height / Vsqr * dist)

but I was having issues with that, any one done this before or have any suggestions?

This is first-year physics homework but since I’ve forgotten that and we have computers what I would do would forward-solve iterations until they converge on a hit, assuming you’re not doing this too often per frame.

I understand that this is a physics problem. The problem is the equation I have is returning NaN, so it appears either I am missing something, or the equation is not doing what it is suppose to do. I am looking for someone with a suggestion on projectile trajectory. I am not sure what you mean Troy with forward solve iterations, I am dealing with velocity, angle and forces. Therefore I need to shoot the projectile at a certain angle in order to hit a target.

The current Equation I have:

where

G = -9.8
H = height difference
L = distance from target
V = initial velocity

Angle = .5 * Mathf.Asin((GL^2 - 2 * h) / (v^2 * d));

For some reason returns me NaN - which generally means the velocity is not high enough, but it doesn’t matter how much I change v, it still doesn’t return a number?

bump

Does anyone have any knowledge in this projectile trajectory stuff?

maybe this helps you: Projectile motion - Wikipedia

but away from this, there must a variable that is equals zero or simply not set.

have you checked that every var in your formular has a valid value?

By forward solve I mean run a fake shot simulation and see where the shot misses and then iteratively adjust the aiming angle until you converge on a solution.

This is a bit more complicated with a black-box physics engine like PhysX.

NaN does not mean zero, it means the number has gone bad, likely by dividing zero over zero.

If you want to solve the problem analytically, the common approach is to find the time of flight to the target:

dy = t * vy - 0.5g(t*t)

dy is target y - firer y
vy is the initial vertical velocity of the shot.

and solve for t

With the time to target and horizontal components (x,z) of the velocity vector you can work out the horizontal error (position of target - (horizontal velocity * time to target + position of firer).

Working on the horizontal plane, then apply geometry to solve the angle of the triangle you have.

fwiw this is covered in Chapter 4 of Halliday Resnick, which unfortunately I took 23 years ago.

I’m working on an example for this - just haven’t finished it yet!

Okay so using the equation on the wiki is correct. It is the angle with the inverse tangent. It will give you two angles, one being the larger arc where it passes between two points, and the other where the first point it passes is the target.

I was bored tonight; here’s a demo. . .

WASD moves the tank around, space fires.

edit: added tank velocity to shell velocity, which will cause the shell to miss if the tank is moving since that’s not compensated for

220175–7991–$cannonier_120.zip (1.07 MB)

5 Likes

I love you, the “CannonController.cs” saved me
this part in particular:

    void AdjustAim()
    {
        // first orient turret azimuth at target:

        Vector3 target_pos0 = target.transform.position;
       
        target_pos0.y = turret.transform.position.y;

        turret.transform.LookAt(target_pos0);

        // rotate vector to target into local frame:

        Vector3 target_vec = target.transform.position - emitter.transform.position;
       
        target_vec = emitter.transform.InverseTransformDirection(target_vec);
       
        float x = target_vec.z;
        float y = target_vec.y;
        float v = shot_vector0.z;
        float g = 9.8f;

        // formula courtesy wikipedia:

        float v2 = v*v;
        float v4 = v2*v2;
        float x2 = x*x;

        float theta = Mathf.Atan2(v2 - Mathf.Sqrt(v4 - g*(g*x2+2*y*v2)), g*x);

        // adjust aim angle upwards by theta:

        turret.transform.Rotate(new Vector3(-theta*Mathf.Rad2Deg, 0, 0));

        info.text = "Range X = " + x + "  Range Y = " + y + "  theta = " + theta*Mathf.Rad2Deg;
    }
3 Likes

Thanks so much dude! That was exactly what I was looking for!