0
\$\begingroup\$

I want to calculate the time that it takes to intercept a moving target "plane" with a projectile.

For example I have two 3 dimensional vectors (2 locations in 3D space).

Vector3 Person = {100, 0, 50};
Vector3 Plane = {200, 50, 100};

Chart of these two positions

Now let's suppose the person has a gun that fires a projectile at 140M/s in a straight line with no acceleration or bullet drop.

Bullet course

I want to hit the plane, which has an initial velocity and a constant acceleration.

Vector3 VelocityPlane = {-10, -10, 0};
Vector3 AccelerationPlane = {0, -10, 0};

Plane trajectory

So what do I want to do:

Using the above information, I want to calculate where I should aim to hit the Plane.

To achieve that I found the following kinematic equation:

$$\text{Future Plane Position} = \text{Position} + \text{Velocity} \cdot \text {Time} + \left(\frac 1 2 \cdot \text{Acceleration} \cdot \text{Time}^2 \right)$$

In C++ Code it would look like this:

Vector calculatePositionToAimAt(double time, Vector startPosition, Vector velocity, Vector accel = 0) {
    return startPosition + (velocity * time) + (0.5 * accel * pow(time, 2));
}

The Problem:

This function above is great! But there is something subtle missing. I don't have the time to calculate the Position where I have to aim for the function above, which happens to be the most important piece of this problem.

For many, the easiest way would probably be simple: Time = Distance / Bulletspeed But that wont work in my case since the Plane has Acceleration and is moving.

So for that I found the following equation:

$$ \vec p_{\text{Plane}} + \vec v_{\text{Plane}} \cdot t + \left(\frac 1 2 \vec a \cdot t^2\right) = \vec p_{\text{Player}} + \vec v_{\text{Bullet}} \cdot t$$

Together with the explanation: Because time is not a vector and is a scalar, You no longer have to use vectors in this equation. You can just input the magnitudes of the vectors instead - which would look like this:

enter image description here

0.9 Seconds is the result. So this works fine.

Now the question is, how can I rewrite this in code so that it automatically solves such equations?

I already have found code that should solve this which looks like so:

double asymetricSingleAcceleratedInterceptionTime(Vector position1, Vector position2, Vector velocity1, Vector velocity2, Vector acceleration2) {
    /*
    sqrt( (2 * a2 * x1) + (2 * a2 * x2) + v1^2 - (2 * v1 * v2) + v2^2 ) - v1 + v2
    t = ------------------------------------------------------------------------------
    a2
    */

    if (acceleration2.x == 0 && acceleration2.y == 0 && acceleration2.z == 0) {
        return asymetricInterceptionTime(position1, position2, velocity1, velocity2);
    }

    return (sqrt(
        (2 * acceleration2 * position1).Length()
        + (2 * acceleration2 * position2).Length()
        + pow(velocity1.Length(), 2)
        - (2 * velocity1 * velocity2).Length()
        + pow(velocity2.Length(), 2))
        - velocity1.Length()
        + velocity2.Length()
        ) / (acceleration2).Length();
}

However, this always gave me wrong results, so I rewrote it a bit and this is what it looks like now:

Vector3 Player = Vector3(100, 0, 50);
Vector3 Plane = Vector3(200, 50, 100);
Vector3 BulletVelocit = Vector3(140,0,0);
Vector3 PlaneVelocit = Vector3(-10,-10,0);
Vector3 PlaneAcceleration = Vector3(0, -10, 0);

float pos1 = Player.Length();
float pos2 = Plane.Length();
float vel1 = BulletVelocit.Length();
float vel2 = PlaneVelocit.Length();
float acc1 = PlaneAcceleration.Length();


float calc1 = (2 * acc1 * pos1);
float calc2 = (2 * acc1 * pos2);
float calc3 = pow(vel1, 2);
float calc4 = (2 * vel1 * vel2);
float calc5 = pow(vel2, 2);
float calc6 = vel1;
float calc7 = vel2;
float calc8 = (acc1);

float time = (sqrt(calc1 - calc2 + calc3 - calc4 + calc5) + calc6 - calc7) / calc8;

std::cout << time;

This actually works but still has 2 problem:

  1. it gives me wrong results when the velocity is minus, and I already know why
  2. it gives me of course only one result and not 2, like above in the picture {0.9, 26.072}

About the first Problem: If I change this code from this:

float calc1 = (2 * acc1 * pos1); //acc1(acceleration) is +10 because of magnitude
float calc2 = (2 * acc1 * pos2);

to this:

float calc1 = (2 * -10 * pos1); //manually setting acceleration to -10 like in the example
float calc2 = (2 * -10 * pos2);

It gives me one right result: -26.072

So the second Problem.. I dont need the -26.072, but I need the other one which is 0.9

So my final questions are:

1. Is there other code that works better to give me the interception time based on velocity, acceleration etc like described above?

2. If not, how do I have to rewrite my code that it gives me the right positive result and not the negative one

3. How do I fix the magnitude acceleration problem which gives me wrong results.

\$\endgroup\$
1
  • \$\begingroup\$ You've written this in a much more convoluted way than necessary, renaming your objects from Target to Ball to Plane etc along the way. I've tried to clean it up a bit, and replace some of the images with correct math markup, but this is all the time I can spend on it just now. Your key error is this: "You can just input the magnitudes of the vectors instead" No, you cannot. See this answer for a walkthrough of how to solve a related case - the same techniques work here too. \$\endgroup\$
    – DMGregory
    Commented Apr 8, 2022 at 12:28

1 Answer 1

0
\$\begingroup\$

This is exactly equivalent to this previous Q&A: Projectile Aim Prediction with Acceleration.

The only difference is that since your projectile doesn't accelerate, your \$\vec a_\text{Bullet} \$ term is \$\vec 0\$.

That gives us the following formula for the time-to-intercept \$t\$:

$$ \begin{align} 0 &= t^4 \left(\frac 1 4 \vec a \cdot \vec a \right)\\ &+ t^3 \left(\vec a \cdot \vec v \right)\\ &+ t^2 \left(\vec a \cdot \vec p + \vec v \cdot \vec v - s^2 \right)\\ &+ t^1 \left(2\vec p \cdot \vec v \right)\\ &+ 1 \left( \vec p \cdot \vec p\right)\\ \end{align}$$

Where \$\vec v, \vec a\$ are the velocity and acceleration of the plane, respectively, \$\vec p = \vec p_\text{Plane} - \vec p_\text{Player}\$ is the initial displacement of the plane from the player's firing position, and \$s\$ is the speed of your projectile.

Plug this into a quartic equation solver to get any positive time value solutions \$t_*\$, then plug each one in here to get the displacement from the firing position at the moment of interception:

$$\vec p_\text{interecept} = \vec p + \vec v t_* + \frac 1 2 \vec a t_*^2$$

And then use that to get your bullet velocity:

$$\vec v_\text{Bullet} = \frac 1 {t_*} \vec p_\text{interecept}$$

\$\endgroup\$
5
  • \$\begingroup\$ Hey, sorry for the confusion. I got your formular working in code now, was just some misunderstanding. What I have trouble with is finding a library or code to solve the quartic equation. I find many "quartic equation solvers" that are x^4 + ax^3 + bx^2 + cx + d but I need ax^4 + bx^3 + cx^2 +dx +e which confuses me. Do you have a library that works with c++? Thanks a lot :) \$\endgroup\$
    – nexo sharp
    Commented Apr 8, 2022 at 21:05
  • \$\begingroup\$ Hint: divide by "a", so you get x^4 + (b/a)x^3 + (c/a)x^2 + (d/a)x + (e/a), and now it's in the first form. \$\endgroup\$
    – DMGregory
    Commented Apr 8, 2022 at 21:25
  • \$\begingroup\$ oh embarrassing that I forgot about that.. thanks a lot u saved my day :) \$\endgroup\$
    – nexo sharp
    Commented Apr 8, 2022 at 21:39
  • \$\begingroup\$ Hey, one last question. I noticed that he Bullet actually has some sort of acceleration itself. I discovered that the engine does not calculates this with an evenly accelerated motion. The Bullet down with a non evenly accelerated motion which depends on the current speed. That fact is represented in the engines formula and description for air friction: f = a / v² this means that a = f * v² which means that acceleration is changing with speed. \$\endgroup\$
    – nexo sharp
    Commented Apr 9, 2022 at 14:51
  • \$\begingroup\$ That's a statement, not a question. If you have a new question to ask, click the "Ask Question" button. \$\endgroup\$
    – DMGregory
    Commented Apr 9, 2022 at 15:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .