# Interception estimation algorithm - Accelerate towards and 0/0 matching

## Recommended Posts

The following is a description of the technique, not the problem itself. One of the things I've made for my 2D graphics/physics library is a generic interception method. It takes two motion handlers, does math to prepare them for interception (Puts the seeker at 0, 0 position/velocity and adjusts the other relative) and then points one at the other and moves it forward x Seconds. It then tests to see wether it went too far or not far enough, adjusts the Seconds and repeats. MotionHandler is abstract and, for the purposes of this question, is NewtonianMotionHandler (Handles position, velocity, acceleration and forces, using Velocity Verlet) The problem: It acts like an effective, but indecisive mix between accelerating directly towards the seekee and going for a 0/0 position/velocity intercept. That is to say, it starts decelerating as it nears the target, but not enough for an actual 0/0 intercept. What I'd like: 1) An explanation of why (I think at some point, it starts calculating an intercept "behind" itself) 2) Help in converting it into two methods, one of which accelerates continuously towards the target and the other which results in a 0/0 position/velocity intercept. Thanks for any and all help; I know this isn't simple. That's why I'm asking. :)
        public static bool SeekCalculate(MotionHandler seeker, MotionHandler seekee, out Vector2 pointOfInterception)
{
double seconds = 500.0 /*, highSeconds = 2.0, lowSeconds = 0.0 */;
IMotionData seekerMD = seeker.MotionDataGet,
seekeeMD = seekee.MotionDataGet;
seekerMD.ForcesGS = new List<Force>();
seekeeMD.ForcesGS = new List<Force>();

Double lowHighTime = 1000.0;
Double highLowTime = 0.0;
do
{
seekerMD = seeker.MotionDataGet;
seekeeMD = seekee.MotionDataGet;
// seekerMD.Forces = new List<Force>(seeker.motionData.Forces);
// seekeeMD.Forces = new List<Force>(seekee.motionData.Forces);
seekerMD.ForcesGS.Clear();
seekeeMD.ForcesGS.Clear();

seekeeMD.PositionGS = seekeeMD.PositionGS - seekerMD.PositionGS;
seekerMD.PositionGS = Vector2.Zero;
seekeeMD.VelocityGS = seekeeMD.VelocityGS - seekerMD.VelocityGS;
seekerMD.VelocityGS = Vector2.Zero;

seekerMD.MoveTo(seekeeMD.PositionGS, 1.0);

seeker.Simulate(seconds, ref seekerMD);
seekee.Simulate(seconds, ref seekeeMD);

if ((seekerMD.PositionGS.Length / seekeeMD.PositionGS.Length) > 1.000)
// if (((seekerMD.Position + seekerMD.Velocity * seconds).Length / (seekeeMD.Position + seekeeMD.Velocity * seconds).Length) > 1.000)
{
if (seconds < lowHighTime)
lowHighTime = seconds;
}
else if ((seekerMD.PositionGS.Length / seekeeMD.PositionGS.Length) < 1.000)
// else if (((seekerMD.Position + seekerMD.Velocity * seconds).Length / (seekeeMD.Position + seekeeMD.Velocity * seconds).Length) < 1.000)
{
if (seconds > highLowTime)
highLowTime = seconds;
}
seconds = MathExtensions.MathExt.Lerp(highLowTime, lowHighTime, 0.5);
} while (Math.Abs((seekeeMD.PositionGS.Length / seekerMD.PositionGS.Length) - 1.0) > 0.0001);
// } while (Math.Abs(((seekerMD.Position + seekerMD.Velocity * seconds).Length / (seekeeMD.Position + seekeeMD.Velocity * seconds).Length) - 1.0) < 0.001);

pointOfInterception = seekeeMD.PositionGS + seeker.MotionDataGet.PositionGS;

return true;
}



##### Share on other sites
Ok, I've got it to match course and speed; working on a straight-line intercept. The second equation is my tired attempt. I've been doing collision physics work.

        public static bool SeekCalculate(SeekType type, MotionHandler seeker, MotionHandler seekee, out Vector2 pointOfInterception)        {            double seconds = 500.0 /*, highSeconds = 2.0, lowSeconds = 0.0 */;            IMotionData seekerMD = seeker.MotionDataGet,                seekeeMD = seekee.MotionDataGet;            seekerMD.ForcesGS = new List<Force>();            seekeeMD.ForcesGS = new List<Force>();            Double lowHighTime = 1000.0;            Double highLowTime = 0.0;            Vector2 temp1, temp2, temp3;            do            {                seekerMD = seeker.MotionDataGet;                seekeeMD = seekee.MotionDataGet;                // seekerMD.Forces = new List<Force>(seeker.motionData.Forces);                // seekeeMD.Forces = new List<Force>(seekee.motionData.Forces);                seekerMD.ForcesGS.Clear();                seekeeMD.ForcesGS.Clear();                // seekerMD.Forces.Add(new Force(seekeeMD.Position.Normalized, 100.0));                if (type == SeekType.MatchCourseAndSpeed)                {                    seekeeMD.PositionGS = seekeeMD.PositionGS - seekerMD.PositionGS;                    seekerMD.PositionGS = Vector2.Zero;                    seekeeMD.VelocityGS = seekeeMD.VelocityGS - seekerMD.VelocityGS;                    seekerMD.VelocityGS = Vector2.Zero;                    seekee.Simulate(seconds, ref seekeeMD);                    seekerMD.MoveTo(seekeeMD.PositionGS, 1.0);                    seeker.Simulate(seconds, ref seekerMD);                }                else if (type == SeekType.MissileAttackVector)                {                    temp1 = seekerMD.VelocityGS;                    seekeeMD.PositionGS = seekeeMD.PositionGS - seekerMD.PositionGS;                    seekerMD.PositionGS = Vector2.Zero;                    seekeeMD.VelocityGS = seekeeMD.VelocityGS - seekerMD.VelocityGS;                    seekerMD.VelocityGS = Vector2.Zero;                    temp2 = seekeeMD.VelocityGS;                    temp3 = temp1 + temp2;                    seekeeMD.VelocityGS *= temp3.Length;                    seekee.Simulate(seconds, ref seekeeMD);                    seekerMD.MoveTo(seekeeMD.PositionGS, 1.0);                                        seeker.Simulate(seconds, ref seekerMD);                }                                if ((seekerMD.PositionGS.Length / seekeeMD.PositionGS.Length) > 1.000)                // if (((seekerMD.Position + seekerMD.Velocity * seconds).Length / (seekeeMD.Position + seekeeMD.Velocity * seconds).Length) > 1.000)                {                    if (seconds < lowHighTime)                        lowHighTime = seconds;                }                else if ((seekerMD.PositionGS.Length / seekeeMD.PositionGS.Length) < 1.000)                // else if (((seekerMD.Position + seekerMD.Velocity * seconds).Length / (seekeeMD.Position + seekeeMD.Velocity * seconds).Length) < 1.000)                {                    if (seconds > highLowTime)                        highLowTime = seconds;                }                seconds = MathExtensions.MathExt.Lerp(highLowTime, lowHighTime, 0.5);            } while (Math.Abs((seekeeMD.PositionGS.Length / seekerMD.PositionGS.Length) - 1.0) > 0.0001);            // } while (Math.Abs(((seekerMD.Position + seekerMD.Velocity * seconds).Length / (seekeeMD.Position + seekeeMD.Velocity * seconds).Length) - 1.0) < 0.001);            pointOfInterception = seekeeMD.PositionGS + seeker.MotionDataGet.PositionGS;            return true;        }