Monday, September 10, 2018

c# - Projectile Aim Prediction with Acceleration


I'm trying to solve the classic shoot moving object problem but with acceleration attached to that changes it from a quadratic to quartic formula but my math skills are not this good sadly as i prefer to speak in code and not formulas.


i found this https://wiki.beyondunreal.com/Legacy:Projectile_Aiming. i ported it and it's almost what i'm looking for but missing control over the acceleration as its only made for gravity or no gravity and even this i got working only with tricks and modifying it without knowing what i'm doing is getting me only that far.


I made myself a Prototype Interface for the minimum of what i'm trying to get out of it


public class PredictionResult {
public bool IsInRange; // can we even hit the target?
public Vector3[] ShotVelocity; // should be up to 4 possible values
public float[] ShotImpactTime; // how long each shot takes to arrive at the predicted target
public Vector3[] ShotImpactLocation; // somewhat redundant yet still useful if available
}

// only really the delta between start and target matter but its up to the function
// same for startVel and targetVel where startVel is the shooters speed that gets added to the bullet
// the bullet and target can have different accelerations (standing on ground => no gravity or bullet is not affect by gravity)
public PredictionResult ShootAtTarget(Vector3 start, Vector3 target, Vector3 startVel, Vector3 targetVel, Vector3 bulletAccel, Vector3 targetAccel, float bulletSpeed);

any help solving this would be great



Answer



To make things a little simpler, let's work within the inertial frame of our launcher. That means our projectile will be firing from the point (0, 0, 0).


(You can subtract any arbitrary firing position from the target position to get this state of affairs for the purpose of the calculations, then add it back when you need work with the resulting path)


Let's define:



unknowns



  • v_p the launch velocity of our projectile relative to the launcher (vector)

  • t the time after launch when our projectile impacts the target (scalar)


knowns



  • s the speed of our projectile (scalar)

  • p_T the offset from the launcher to the target at the time of firing (vector)

  • v_T the velocity of the target relative to the launcher at the time of firing (vector)


  • a_T the constant acceleration of the target (vector)

  • a_p the constant acceleration of the projectile (vector)


Using our parametric equation for motion over time under constant acceleration...


p(t) = p(0) + v * t + (a/2.0) * t^2

We know that at the time of impact we want:


v_p * t + (a_p/2.0) * t^2 = p_T + v_T * t + (a_T/2.0) * t^2

Rearranging to isolate v_p, we get:



v_p = (1/t)(t^2(a_T - a_p)/2.0 + t * v_T + p_T)

Let's define a = a_T - a_p since they'll appear paired from here on in.


Applying our speed constraint: (Here · refers to a dot product between vectors)


s = ||v_p||

s^2 = v_p·v_p
s^2 = (1/t^2)(t^4(a·a/4.0) + t^3(a·v_t) + t^2(a·p_T + v_T·v_T) + t(2.0 * v_T·p_T) + p_T·p_T)

Rearranging:



  t^4 * (a·a/4.0)
+ t^3 * (a·v_T)
+ t^2 * (a·p_T + v_T·v_T - s^2)
+ t * (2.0 * v_T·p_T)
+ p_T·p_T
= 0

That's a quartic equation in t, which is not the most fun to solve. When the target is stationary, the t^3 and t terms vanish and we can use quadratic formula to solve for t^2, but for the general case of a moving target there's not much we can do but bite the bullet.


You can either plug this into a math library to solve the polynomial, write your own polynomial solver, or approximate a solution using an iterative method like Newton's.


However you choose to go about it, you'll come out with up to 4 time values at which you can successfully intercept the target. Some could be negative, corresponding to projectiles being lobbed from the target sometime in the past to arrive at the firing position at time zero travelling at the desired speed - discard those and consider only the positive time values. (You might get none, if the target is simply out of firing range or moving too fast to intercept)



To turn any of these remaining valid time values into a launch velocity, do the following:




  1. Plug your t value into the formula for the target's position


    p(t) = p_T + v_T * t + (a_T/2.0) * t^2


    This gives you the position of the target at the time of impact. Since this is the net offset in space that your projectile will have to bridge, we'll call this vector travel




  2. Calculate the initial velocity (aim direction & speed) of an arc travelling to this point in space & time:


    v_p = travel / t - (a_p/2.0) * t





By construction, launching the projectile with this velocity v_p will intersect the target's movement while respecting the initial speed constraint we started with, to within the numerical accuracy of the operations we took to get here. (Some rounding can be introduced at each step)


Here's an animation of this formula at work:


Animated gif of projectile interceptions


This little test rig generates random target positions/velocities/accelerations and projectile gravity values, then calculates up to four intercept trajectories.


The white ball is the target, moving along its trajectory before t=0 (black curve) to its position at the time of firing (grey dot) and continuing along its future trajectory t > 0 (greycurve). Its path is marked by red dots at the solution points.


The intercepting projectiles and their trajectories appear in cyan & green at t = 0 and arc to intercept the target at their corresponding impact times.


For completeness, I also show the negative solutions if there are any, in yellow or magenta, firing from the target when it crosses a negative solution time and arriving at the firing point in the center at t = 0.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...