2

I previously asked a question about this topic here, and now I'd want to review if the offered solutions worked, and then frame a new inquiry based on the difficulties and issues that resulted.

So my previous post briefly summarized, what I'm attempting to do is calculate the Impact point of a Bullet and a moving Target in 3D Space based on the Bullet's Position, Target Position, Bulletspeed, Target Velocity and Target Acceleration.

The only variable I was lacking to estimate the impact point was the time it would take the bullet to reach the target, which I could solve using the formula below thanks to this post:

formula

Right now I'm using this C++ quartic solver which gives me the time from the formula above which looks like this:

    double t4calc = (TargetAcceleration.Dot(TargetAcceleration)) / 4;
    double t3calc = (TargetAceleration.Dot(TargetVelocity));
    double t2calc = TargetAcceleration.Dot(relativepos) + velocity.Dot(TargetVelocity) - bulletspeed * bulletspeed;
    double t1calc = 2.0 * destination.Dot(TargetVelocity);
    double tcalc = (relativepos.Dot(relativepos));

    std::complex<double>* solutions = solve_quartic(t3calc / t4calc, t2calc / t4calc, t1calc / t4calc, tcalc / t4calc);

using solutions->real() it returns the time it takes to hit the target in seconds.

The Problem:

Since I assumed that the Bullet's velocity is constant and hence does not contain acceleration, the function above only include the target's acceleration but disregard the bullet's acceleration.

Now I discovered that the Bullet has also an acceleration and that it slows down over time.

Unfortunately, I can't just use a constant acceleration like -10M/s since the bullet's speed and acceleration also fluctuates based on the pitch view angle of the player.

Because using the pitch view angle for a f(x,y) calculation would be tedious, I decided to switch from viewangle to relative height and distance of the target, as my pitch view angle varies depending on how high and far the target is from me.

So, collecting some data and testing around, as well as using curve fitting, I was able to obtain the following function, which gives me the Time the Bullet need to Reach the Target in Seconds, based on the relative height and distance of the Target:

double a0 = 0.28891;
double a1 = 0.00147988;
double a2 = 0.0000116694;

double x1 = DistanceToTarget;
double x2 = Targetheight - Playerheight; //relative height of Target

double TimeToTarget = a0 + (a1 * (x1^1.2)) + (a2 * (x2^1.75)) //Returns Time in seconds it needs to reach the Target (If Target is stationary)

Okay so using the function above I could get the time which the Bullet needs to hit the Target (if the Target is not moving and standing at one point).

But of course I want the Time it needs to hit the Target if the Target is moving and accelerating..

So now I could calculate the bulletspeed in M/s by dividing the current distance to the target by the time obtained from the function above and insert it into the quartic solver function to get the time which the bullet needs to hit the moving and accelerating target based on the predicted position right...

Wrong.. this won't be accurate for the quartic solver function above, since it would use the bulletspeed computed for the target's current distance, while it should be using the bulletspeed calculated for the target's distance at impact. I hope you can follow me here.. if not feel free to ask about it.

Final Question:

So to solve this problem I'm wondering whether I can somehow include this TimeToTarget function into the previous quartic function. Otherwise the speed will be calculated incorrectly and the result will be wrong.

Spektre
  • 49,595
  • 11
  • 110
  • 380
nexo sharp
  • 19
  • 5
  • I must second DMGregory's comment that *"you've written this in a much more convoluted way than necessary".* **What information do you start with?** Do you know the bullet's acceleration as a function of time? Is it -- dare I ask? -- a function of the the bullet's velocity? – Beta Apr 10 '22 at 02:04
  • Hey @Beta it's "convoluted" because I had already asked questions on stackoverflow before, and each time people complained that not enough information was given. "What information do you start with" Bullet's Position, Target Position, Bulletspeed, Target Velocity and Target Acceleration. "Do you know the bullet's acceleration as a function of time?" "Is it a function of the the bullet's velocity?" technically both as the function gives you the time it needs to reach the target based on the distance and relative height, so you could also get the velocity and accel based on time with it. – nexo sharp Apr 10 '22 at 09:21
  • So If a function for acceleration and velocity over time would help you to find a solution, I would be very happy to give them to you. – nexo sharp Apr 10 '22 at 09:24
  • You have a function that gives the time needed to reach the target -- but you don't because there's something else the function can't handle -- but then you do again. If you don't know the bullet's initial velocity *(which is not the same thing as its speed),* then you cannot solve this problem -- but then you can because of an assumption you didn't mention earlier -- but then maybe you can't. If you have a formula for velocity as a function of time, *then you do not need to know anything about acceleration,* -- only hang on, maybe you do because maybe you've left something out again. – Beta Apr 10 '22 at 13:53
  • @Beta Well as already said, the formular above basically works as a function for velocity of time, let me explain what I mean with that. For example the target is 100 meters higher than you and has a distance of 200 meters. You input that into the formular above and you get the time which the rocket needs to hit the target, for example 4 Seconds. Now if you just divide the time by the distance (200 meters / 4 seconds) you get the velocity of the rocket at 4 seconds which in this case would be 50 M/s. So the bullet would have a velocity of 50M/s at 4 seconds. – nexo sharp Apr 10 '22 at 14:05
  • If however you want a simple function of time, where you can just enter the time and then automatically get the velocity of the rocket at that time, i can't give you that, because as explained in my question above, the rocket has a different velocity based on your pitch angle. So for example if I fire the rocket at a target that is 100 meters high and 400 meters away, the rocket would have a velocity of 50M/s after 4 seconds, but if I fire at a target that is 500 meters high and 400 meters away, the rocket would have a velocity of 40M/s after 4 seconds. So different Velocity after same time. – nexo sharp Apr 10 '22 at 14:09
  • Accordingly, to get the velocity at time x, you always have to enter two values. First the time, and second the relative height of the target. – nexo sharp Apr 10 '22 at 14:10
  • If, as you keep saying, you have a formula that gives the time of impact, then once you have that you can forget everything else about the bullet. Just look at the target and use **x** = **xo** + **vo**t + **a**t^2/2. – Beta Apr 10 '22 at 14:20

1 Answers1

1

if by slowing you mean just gravity and not air friction like kv^2 or kv^3 then you can compute this very simply using 2 pass approach:

  1. definitions

    for simplicity lets assume bullet is p0,v0 and ball is p1,v1 ... meaning position,velocity and global acceleration a applying on both... so Newton d'Alembert physics dictates:

    v0+=a*dt; p0+=v0*dt;
    v1+=a*dt; p1+=v1*dt;
    

    for updating time by dt ...

  2. estimate bullet speed

    simple direct line of sight is enough for this so:

    v0=normalize(p1-p0)*v;
    

    where v is your bullet start speed.

  3. compute the collision time

    simply by solving t in:

    (p0+(v0*t)+(0.5*a*t*t)) = (p1+(v1*t)+(0.5*a*t*t));
    t = (p1-p0)/(v0-v1);
    

    as this is one solution per each axis use the smallest result above zero from the 3 see get_solution function in the example below

  4. compute difference of position between both p0,p1 after t

    simply by:

    dp=(p1-p0)+((v1-v0)*t);
    

    and correct initial v0 estimate so after t seconds the difference will be zero:

    v0+=dp/t;
    
  5. compute real time

    again either use:

    t = (p1-p0)/(v0-v1);
    

    or if you need to account for radiuses of both objects then:

    t = ((r0+r1-p0+p1)/(v0-v1));
    

However note that this approach will change the |v0| "slightly" so in case its a problem you should fit the v0 using spherical coordinates instead...

Here small C++/VCL example (just adaptation of my previous answer example)

//$$---- Form CPP ----
//---------------------------------------------------------------------------
#include <vcl.h>
#include "GLSL_math.h"
#pragma hdrstop
#include "win_main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TMain *Main;
//---------------------------------------------------------------------------
vec3 p0=vec3(  0,  0,  0),v0=vec3(  0,  0,0);   // bullet
vec3 p1=vec3(150,100,  0),v1=vec3(-50,-30,0);   // ball
vec3 a =vec3(0,-10,0);                          // global acceleration
//---------------------------------------------------------------------------
float t0=0.0;               // time to hit
const float r0= 2.0;        // bullet radius
const float r1=15.0;        // ball radius
float x0,y0,z0,x1,y1,z1;    // walls
//---------------------------------------------------------------------------
float get_solution(vec3 tt)
    {
    float t=0.0;
    // t = min(tt)
    if (t<tt.x) t=tt.x;
    if (t<tt.y) t=tt.y;
    if (t<tt.z) t=tt.z;
    return t;
    }
//---------------------------------------------------------------------------
void shoot()
    {
    const float v=250.0;            // bullet start speed
    int i;
    float t;
    vec3 dp;
    p0=vec3(0.5*(x0+x1),y0+r0,0);   // reset shot start position

    // solve t for colision:
    //  (p0+(v0*t)+(0.5*a*t*t)) - (p1+(v1*t)+(0.5*a*t*t)) = r0+r1;
    //  t = (r0+r1-p0+p1)/(v0-v1);

    v0=normalize(p1-p0)*v;          // v0 estimate
    t=get_solution((p1-p0)/(v0-v1));// time estimate
    dp=(p1-p0)+((v1-v0)*t);         // diference after time t
    v0+=dp/t;                       // correct v0 estimate
    t0=get_solution((r0+r1-p0+p1)/(v0-v1)); // real time to collision
    }
//---------------------------------------------------------------------------
void update(double dt)
    {
    int e=0;
    // Newton/d'Lambert simulation
    v0+=a*dt; p0+=v0*dt;
    v1+=a*dt; p1+=v1*dt;
    t0-=dt;
    // bullet timeout
    if (t0<=0.0) e=1;
    // bullet hit the target
    if (length(p1-p0)<=r1+r0) e=1;
    // bullet colision with wall
    if (p0.x<x0+r0) e=1;
    if (p0.x>x1-r0) e=1;
    if (p0.y<y0+r0) e=1;
    if (p0.y>y1-r0) e=1;
    if (p0.z<z0+r0) e=1;
    if (p0.z>z1-r0) e=1;
    // ball colision with wall
    if (p1.x<x0+r1){ p1.x=x0+r1; v1.x=-v1.x; }
    if (p1.x>x1-r1){ p1.x=x1-r1; v1.x=-v1.x; }
    if (p1.y<y0+r1){ p1.y=y0+r1; v1.y=-v1.y; }
    if (p1.y>y1-r1){ p1.y=y1-r1; v1.y=-v1.y; }
    if (p1.z<z0+r1){ p1.z=z0+r1; v1.z=-v1.z; }
    if (p1.z>z1-r1){ p1.z=z1-r1; v1.z=-v1.z; }
    // shoot again if needed
    if (e) shoot();
    }
//---------------------------------------------------------------------------
void TMain::draw()
    {
    if (!_redraw) return;
    float x,y,r;

    // clear buffer
    bmp->Canvas->Brush->Color=clBlack;
    bmp->Canvas->FillRect(TRect(0,0,xs,ys));

    // walls
    bmp->Canvas->Pen->Color=clWhite;
    bmp->Canvas->Brush->Color=clBlack;
    bmp->Canvas->Rectangle(x0,ys-y0,x1,ys-y1);

    // ball
    bmp->Canvas->Pen->Color=clAqua;
    bmp->Canvas->Brush->Color=clBlue;
    x=p1.x; y=ys-p1.y; r=r1;
    bmp->Canvas->Ellipse(x-r,y-r,x+r,y+r);
    // bullet
    x=p0.x; y=ys-p0.y; r=r0;
    bmp->Canvas->Ellipse(x-r,y-r,x+r,y+r);

    bmp->Canvas->Brush->Color=clBlack;
    bmp->Canvas->Font->Color=clYellow;
    bmp->Canvas->TextOutA(0,0,AnsiString().sprintf("time to hit: %.3fs",t0));

    // render backbuffer
    Main->Canvas->Draw(0,0,bmp);
    _redraw=false;
    }
//---------------------------------------------------------------------------
__fastcall TMain::TMain(TComponent* Owner) : TForm(Owner)
    {
    bmp=new Graphics::TBitmap;
    bmp->HandleType=bmDIB;
    bmp->PixelFormat=pf32bit;
    pyx=NULL;
    _redraw=true;
    }
//---------------------------------------------------------------------------
void __fastcall TMain::FormDestroy(TObject *Sender)
    {
    if (pyx) delete[] pyx;
    delete bmp;
    }
//---------------------------------------------------------------------------
void __fastcall TMain::FormResize(TObject *Sender)
    {
    xs=ClientWidth;  xs2=xs>>1;
    ys=ClientHeight; ys2=ys>>1;
    bmp->Width=xs;
    bmp->Height=ys;
    if (pyx) delete[] pyx;
    pyx=new int*[ys];
    for (int y=0;y<ys;y++) pyx[y]=(int*) bmp->ScanLine[y];
    _redraw=true;

    int w=32;
    // boundaries
    x0=w; x1=xs-w;
    y0=w; y1=ys-w;
    z0=-100; z1=+100;

    p1=vec3(x1-r1,y1-r1,0);
    shoot();

    update(0.0);
    }
//---------------------------------------------------------------------------
void __fastcall TMain::FormPaint(TObject *Sender)
    {
    _redraw=true;
    }
//---------------------------------------------------------------------------
void __fastcall TMain::tim_redrawTimer(TObject *Sender)
    {
    update(0.04);
    _redraw=true;
    draw();
    }
//---------------------------------------------------------------------------

and preview:

preview

again the important stuff is function shoot() which aims and shoot bullet p0,v0 so it hits p1,v1 after t0 seconds... function update(dt) just simulates time and handle the collisions ...

Spektre
  • 49,595
  • 11
  • 110
  • 380
  • Hey, thank you for your reply. the deacceleration is calculated by gravity, airfriction and pitch angle, which is the function above that I shared in my post. If I could use that function instead to calculate the time at impact that would be perfect. – nexo sharp Apr 10 '22 at 14:14
  • @nexosharp 1. no you did not share any equation about friction (at least I do not see any) ... time to impact is something entirely else 2. what does pitch angle has to do wit anything? if you use acceleration of gravity field (your `(0,-10,0)`) then the velocity will be slowing differently at different angles yes that is right however you do not use this angle in equations as vector math do this on its own automaticaly (you know `dot(a,b)` is like `cos(angle_between_a_b)*|a|*|b|` 3. you are mixing 1D equations with 3D again which will lead to wrong results that is doable only if you project – Spektre Apr 10 '22 at 17:42
  • hey thanks for your reply. The friction is already calculated inside the time to impact calculation as I used curve fitting based on multiple tests at different ranges and heights. I found another function now, added my time calculation to it and it actually works perfect now. thanks for your thread anyway :) – nexo sharp Apr 10 '22 at 18:25
  • @nexosharp that is the problem without direct equation we can not derive solution that matches your case and infer it from impact equation which is based on god knows what is not a good idea ... – Spektre Apr 10 '22 at 19:40