如何在移动目标上找到拦截

时间:2013-07-18 17:01:31

标签: c# math vector intercept

所以这是我的代码大致

Distance = Vector3.Distance(transform.position,Target.transform.position);
float timeToTarget; 
float burnDistance =  Projectile.MetersPerSecond * 2f * 2f * 0.5f;

if (Distance < burnDistance)
{
    timeToTarget = Mathf.Sqrt(2 * Distance / Projectile.MetersPerSecond);
}
else
{
    float velocity = Projectile.MetersPerSecond * 2;
    TimeToTarget = 2 + (Distance - burnDistance) / velocity;
}
AimPoint = Target.transform.position + (Target.transform.rigidbody.velocity * TimeToTarget) + (Random.insideUnitSphere * Accuracy);
Distance = Vector3.Distance(transform.position,AimPoint);
TimeToTarget = Mathf.Sqrt(2 * Distance / Projectile.MetersPerSecond);

我试图用射弹拦截目标。

问题在于找到适合我的目标的时间。

基本上当我找到到目标的距离然后用它来找到目标的时间 它将我的瞄准点改变为目标在时间秒内的位置。 但现在距离发生了变化。现在,我现在距离目标越来越远,我距离我想要击中的距离不远。

基本上当目标远离我时,射弹击中瞄准点所需的时间比距目标距离所预测的要长。 所以我可以通过再次运行算法来解决这个问题。仅使用aimpoint作为目标并获得更接近的近似值。我可以继续这样做,以获得非常接近,但这似乎非常低效。还有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

如果你知道目标的速度矢量V,你可以计算出导弹的速度,以及截取的时间如下:

假设您在P处并且目标位于Q.对于从P发射的导弹,速度U在时间t击中目标,我们必须

P + t*U = Q + t*V

所以

U = V + (Q-P)/t

假设导弹速度 - U的长度固定在s

s*s = V.V + 2*(Q-P).V/t + (Q-P).(Q-P)/(t*t)

或重新安排)

(s*s - V.V)*t*t - 2*(Q-P).V*t - (Q.P).(Q-P) = 0

是t的二次方程。如果对此有正解,那么 你可以发射导弹,速度U由

给出
U = V + (Q-P)/t0

在时间t0点击目标

答案 1 :(得分:0)

如果你的射手&#34;不旋转,你只需要发射射弹以拦截目标,我建议你看看Jeffery Hantin在this post中的出色回答。

另一方面,如果你的身体旋转然后射击,你想让射弹拦截目标......这是一个非常不同的问题。简而言之,它从你在上面的帖子中找到的相同的两个方程开始,但是你为射手的面向矢量和你瞄准的最终位置之间的角度的arc​​os添加了另一个等式。这导致了一些有点令人讨厌的非线性和非二次方程组。我没有解决它们,但我确实使用二进制搜索来“挤压”#34;出答案(或失败)。

我有a much longer and more detailed description on a blog post,以及图片和视频的优点,但我会在这里发布功能(慷慨的评论)。

这是我提出的功能,基本描述:

/* Calculate the future position of a moving target so that 
 * a turret can turn to face the position and fire a projectile.
 *
 * This algorithm works by "guessing" an intial time of impact
 * for the projectile 0.5*(tMin + tMax).  It then calculates
 * the position of the target at that time and computes what the 
 * time for the turret to rotate to that position (tRot0) and
 * the flight time of the projectile (tFlight).  The algorithms
 * drives the difference between tImpact and (tFlight + tRot) to 
 * zero using a binary search. 
 *
 * The "solution" returned by the algorithm is the impact 
 * location.  The shooter should rotate towards this 
 * position and fire immediately.
 *
 * The algorithm will fail (and return false) under the 
 * following conditions:
 * 1. The target is out of range.  It is possible that the 
 *    target is out of range only for a short time but in
 *    range the rest of the time, but this seems like an 
 *    unnecessary edge case.  The turret is assumed to 
 *    "react" by checking range first, then plot to shoot.
 * 2. The target is heading away from the shooter too fast
 *    for the projectile to reach it before tMax.
 * 3. The solution cannot be reached in the number of steps
 *    allocated to the algorithm.  This seems very unlikely
 *    since the default value is 40 steps.
 *
 *  This algorithm uses a call to sqrt and atan2, so it 
 *  should NOT be run continuously.
 *
 *  On the other hand, nominal runs show convergence usually
 *  in about 7 steps, so this may be a good 'do a step per
 *  frame' calculation target.
 *
 */
bool CalculateInterceptShotPosition(const Vec2& pShooter,
                                    const Vec2& vShooter,
                                    const Vec2& pSFacing0,
                                    const Vec2& pTarget0,
                                    const Vec2& vTarget,
                                    float64 sProjectile,
                                    float64 wShooter,
                                    float64 maxDist,
                                    Vec2& solution,
                                    float64 tMax = 4.0,
                                    float64 tMin = 0.0
                                    )
{
   cout << "----------------------------------------------" << endl;
   cout << " Starting Calculation [" << tMin << "," << tMax << "]" << endl;
   cout << "----------------------------------------------" << endl;

   float64 tImpact = (tMin + tMax)/2;
   float64 tImpactLast = tImpact;
   // Tolerance in seconds
   float64 SOLUTION_TOLERANCE_SECONDS = 0.01;
   const int MAX_STEPS = 40;
   for(int idx = 0; idx < MAX_STEPS; idx++)
   {
      // Calculate the position of the target at time tImpact.
      Vec2 pTarget = pTarget0 + tImpact*vTarget;
      // Calulate the angle between the shooter and the target
      // when the impact occurs.
      Vec2 toTarget = pTarget - pShooter;
      float64 dist = toTarget.Length();
      Vec2 pSFacing = (pTarget - pShooter);
      float64 pShootRots = pSFacing.AngleRads();
      float64 tRot = fabs(pShootRots)/wShooter;
      float64 tFlight = dist/sProjectile;
      float64 tShot = tImpact - (tRot + tFlight);
      cout << "Iteration: " << idx
      << " tMin: " << tMin
      << " tMax: " << tMax
      << " tShot: " << tShot
      << " tImpact: " << tImpact
      << " tRot: " << tRot
      << " tFlight: " << tFlight
      << " Impact: " << pTarget.ToString()
      << endl;
      if(dist >= maxDist)
      {
         cout << "FAIL:  TARGET OUT OF RANGE (" << dist << "m >= " << maxDist << "m)" << endl;
         return false;
      }
      tImpactLast = tImpact;
      if(tShot > 0.0)
      {
         tMax = tImpact;
         tImpact = (tMin + tMax)/2;
      }
      else
      {
         tMin = tImpact;
         tImpact = (tMin + tMax)/2;
      }
      if(fabs(tImpact - tImpactLast) < SOLUTION_TOLERANCE_SECONDS)
      {  // WE HAVE A WINNER!!!
         solution = pTarget;
         return true;
      }
   }
   return false;
}