Sign in to follow this  
Narf the Mouse

Interception estimation algorithm - Accelerate towards and 0/0 matching

Recommended Posts

Narf the Mouse    322
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.Forces.Add(new Force(seekeeMD.Position.Normalized, 100.0));

                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 this post


Link to post
Share on other sites
Narf the Mouse    322
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;
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this