RIM-116 & Phalanx
Fire control
At Mach 2 a missile needs several seconds for a few kilometres, and a mortar shell travels over a kilometre in that time. Without a lead solution the mount never hits anything that moves.
The intercept equation
Solve |Z + V*t - S| = v*t for t. Rearranged that is a quadratic
t²(V·V - v²) + 2t(D·V) + D·D = 0 with D = Z - S. Of the
roots, the smallest positive one counts – the larger describes a meeting after the target has already
passed the mount.
bool MyAD_Intercept(vector shooter, vector target, vector targetVel, float speed, out float time)
{
vector d = target - shooter;
float a = vector.Dot(targetVel, targetVel) - speed * speed;
float b = 2.0 * vector.Dot(d, targetVel);
float c = vector.Dot(d, d);
// target exactly as fast as the missile: the equation is linear
if (Math.AbsFloat(a) < 0.001)
{
if (Math.AbsFloat(b) < 0.001)
return false;
time = -c / b;
return time > 0;
}
float disc = b * b - 4.0 * a * c;
if (disc < 0)
return false; // faster and opening: not catchable
float root = Math.Sqrt(disc);
float t1 = (-b + root) / (2.0 * a);
float t2 = (-b - root) / (2.0 * a);
// smallest positive root
time = -1;
if (t1 > 0 && t2 > 0)
time = Math.Min(t1, t2);
else if (t1 > 0)
time = t1;
else if (t2 > 0)
time = t2;
return time > 0;
}
Aircraft: straight line. Shells: iterate with gravity.
A helicopter hardly changes course within a few seconds and the missile corrects itself in the endgame, so a straight-line extrapolation is enough. A mortar shell falls tens of metres in a few seconds, so the straight line aims where it would have been. The ballistic version alternates between “point from time” and “time from point” until both agree – three passes are plenty.
Accuracy is a probability with a name
The levels are not decoration: the value is the hit probability and goes unchanged into the scatter of the aim point. Picking a level means picking a percentage – the names only make that concrete.
| Level (example) | Hit probability |
|---|---|
JOHN_WICK | very high |
RAMBO | high |
LUCKY_LUKE | medium – a sensible default |
JACK_SPARROW | low |
STEVIE_WONDER | very low |
enum MyAD_EAccuracy
{
JOHN_WICK = 0, // 90 %
RAMBO, // 75 %
LUCKY_LUKE, // 65 % - default
JACK_SPARROW, // 45 %
STEVIE_WONDER // 30 %
}
Let the same level drive how easily the seeker is fooled by a flare, so a bad mount is bad consistently rather than bad in one place and sharp in another.