Modern Warfare Mod 3 brings World in Conflict from the Cold War into the Modern Age. It also ups the ante on realism and authenticity in every role – Infantry, Armor, Support and Air, while trying our best to keep everything relatively balanced for fun and interesting gameplay.

Report article RSS Feed WiC Modding Tutorial - Leading a moving target in Python

A frequently asked question is how to compensate your gun's aiming point based upon your target's movement (leading your target), so that your bullet will hit your target instead of ending up in a miss. We'll go over a number of target leading strategies using WiC's python ShooterBase() module to show you some of the methods we use.

Posted by blahdy on Jan 2nd, 2011
Intermediate Server Side Coding.

WiC Modding Tutorial - Leading a moving target in Python


This tutorial assumes you have some basic working knowledge of python language, basic understanding of modding in World in Conflict and some understanding of basic linear algebra (high school level).

Option 1: The simplest and the most inaccurate, but "good enough" way to lead your target.

The most basic way to lead a moving target is very simple. 

Our bullet is not a laser -- it takes time for it to reach the target.  So since it takes some amount of time to reach the target, we need to wait that much amount of time before firing. Calculating the amount of time our bullet will take to reach the target can be done by using basic physics law of t = d / v, where time = distance to travel / bullet speed or velocity.  The distance to travel is the length of the vector between you and the target.

Once you solve the time, you just need to apply this time against the target's velocity vector to get its predicted world-relative vector position after the amount of your specified time has elapsed.  Thankfully, ShooterBase() python module provides you a neat function called GetPredictedTargetPosition( aTimeToCalculate ).  You can use this function to plug in your calculated time value to receive the world-relative vector position of the target after your time has elapased.  That is where you want to aim your gun.

This leading method is used by all of WiC's standard Straight Shooter projectiles -- so every unit employing straight shooter in vanilla, unmodded WiC uses this method to lead.

Pros:
Very simple, fast and easy to understand.

Cons:
The problem with this method is that it does not take into account for the fact that the target is *moving*.  We are using the distance between our position and the target's position.  But this distance is changing every frame because the target is moving.  You will not be able to intercept any target that moves at moderate to fast speed with this method.

Examples in Use:
All vanilla WiC straight shooters use this method.  Most tanks and ground units in MW Mod also use this method. A good side effect of this simple method is that from an RTS game standpoint, it creates a sense of realism in that even with good fire control system, not every shot is going to make a hit against a moving target.  But against most slow targets, you will hit it ok as long as your bullet's speed is fast enough to contact the target's hitbox in time.


Option 2: Quadratic Equation Solving

This method is very commonly used by MW Mod.  The great benefit of this method is that it is relatively simple to implement and yet impressively accurate in most situations.

Quadratic equations are also commonly used in computing trajectories of projectiles in motion.  You'll also find it in use by several games when producing firing solutions for AI bots against moving character target or unit in the game.

Instead of digging into the math and boring you with details, let's just get straight to the code.  You can learn more about the math aspect by searching for Quadratic Equation on Google and Wikipedia.

The following is snippet of PredictorFCS python code used by MW Mod when generating quadratic fire solutions:

python code:
  def QuadraticFireSolution( self, aTargetPosition, aFiringPosition, aTargetSpeed, aBulletSpeed ):
    """ Primitive method to provide basic calculation of how much we need to lead a target.
      Uses quadratic equation to solve for smallest possible square root.
     
      Returns the amount of time in seconds we need to wait to hit our target.
     
      Returns -1 if there is no fire solution (i.e. target is moving away from us and
      our bullet is too slow to catch up).
    """

   
    targetVelocityVector = math.Vector3(0, 0, 0) * aTargetSpeed
    interceptVelocityVector = math.Vector3(0, 0, 0) * aBulletSpeed
   
    tDelta = aTargetPosition - aFiringPosition
   
    Vr = targetVelocityVector - interceptVelocityVector
    a = Vr.Dot( Vr ) - aBulletSpeed * aBulletSpeed
    b = 2 * Vr.Dot( tDelta )
    c = tDelta.Dot ( tDelta )
   
    deter = b * b - 4 * ( a * c )
   
    if deter < 0:
      PdFCS.com.exp.teamchat ( self.UnitMessageHeader, 2, "<#ff0>NO SOLUTION</> (Unable to generate quadratic fire solution.)")
      return -1
    else:
      ETN = 2 * ( c / pdmath.sqrt(deter) - b )
      return ETN

Remember the time of collision we had solved for in the above "simplest way to lead your target" method by dividing distance by bullet speed?  This function also calculates for that time and returns the value of time.  If the target cannot be hit, then you have no fire solution and the function will return -1 instead.  Simply plug in the number returned by the above function into WiC ShooterBase's GetPredictedTargetPosition( time ) to get world position on where you need to aim your gun to hit your target.

Pros:
The benefit of this method is that it is very accurate, even when the distance between you and the target is changing by every frame. It is also computationally very cheap so you can conduct this calculation on massive number of targets simultaneously at once to generate quick fire solutions for multiple targets.

Cons:

  • Only works accurately against intercepts forming a right triangle. Doesn't matter for slow targets, but matters a lot for anti-missile systems.

Examples:
Quadratic equation is commonly used in MW Mod on all major fire control applications as well as radar systems used to track enemy units. The reason behind its prevalent use in the mod is simply because it is computationally cheap and easy to implement for various applications, while providing acceptably accurate target leads.

  • The AEGIS-style air defense script running the Patriot radar-guided SAMs uses quadratic equation to rapidly generate firing solution against up to 100 air targets while running the "Track-While-Scan" (TWS) function. 

    The TWS function builds list of up to 100 targets and updates the list every 0.1 second with new predicted moving positions. Because of the TWS principle, the radar script needs to know where the target is predicted to move to, in order to figure out where to look next in the sky for its next radar sweep.  This makes sure that the radar constantly maintains tracking of its target.

    This also means that the target aircraft would not receive a radar lock or missile launch warning, simply because the radar unit is "sweeping" the sky in search mode, and using quadratic equation to figure out where to look in the sky again for the next search sweep, without significantly increasing the number of radar scans issued against the aircraft (which would trigger missile launch/SAM lock warnings).

  • Helicopter chainguns use quadratic equation when targeting moving units.  This makes the chaingun effective against maneuvering aircraft, notwithstanding inaccuracy that may result from gun's barrel at longer distances.
  • Apache Longbow radar script also uses quadratic equation to rapidly generate fire solutions on the fly against up to 128 moving ground targets. When several Apaches are joining in to rapidly fire off their Longbow Hellfires, the radar script keeps track of every Hellfire round and directs each to different target in the fire zone individually. 3 air players with 2 Apaches per player firing together in teamwork could destroy an entire batallion of enemy armor in less than 30 seconds. Talk about extreme firepower..
  • Quadratic equation is also used by SAM fire control radars to "illuminate" their targets when airborne missiles are about to strike them.
  • Also used in numerous AA guns to direct bullets onto moving target's flight path.

Option 3: Trigonometric Calculation

When you are targeting fast moving target that is traveling almost as fast as you are, such as ballistic missiles, you start to run into issue of resolution.  The data you receive and perceive about your target, such as target's moving velocity, direction, pitch, yaw, etc is changing rapidly every frame.  And the data-set you are using to predict target's movement point is already too late, especially when target has a very small cross section and hitbox, where even a smallest inaccuracy would result in a total miss.

This becomes a bit of challenge when you are trying to shoot a ballistic missile with another missile, with perfect one-shot accuracy.  It will be unacceptable for the intercepting missile to miss then fly around for 2nd try like a typical game homing shooter, because by then, ballistic missile will hit its mark.

To accurately intercept fast moving and maneuvering targets with a single sniper hit, we convert vectors into polar coordinates and solve for angles in a triangle using trigonometric law of sines.  We'll just get straight to the code:

python code:
    pdFCS_PI = 3.141592653589793238
    Length = toTarget.Length()
    TargetDirectionVector = pdFCS.guidance.MovingTargetIndicator(1) - targetPosition10
    TargetDirectionVector.NormalizeSafe()
    toTarget.NormalizeSafe()
   
    targetDirectionalHeading = math.PolarAnglesFromVector( TargetDirectionVector )
    targetHeading = math.PolarAnglesFromVector( toTarget )
    targetHeading2 = targetDirectionalHeading - targetHeading
   
    bY = pdFCS_PI - targetHeading2.X
    b = pdFCS_PI - targetHeading2.Y

    A_div_B = targetSpeed / interceptVelocity
   
    C = Length

    if A_div_B == 0:
      pdFCS.com.exception( "PAC-3 ERINT", "DIV_ZERO", None )
      check = 1
    else:
      check = 0
   
    sin_bY = pdmath.sin(bY)
    sin_b = pdmath.sin(b)
   

    sin_aY = A_div_B * sin_bY
    sin_a = A_div_B * sin_b
   
   
    # If sine of a is greater than 1 it means a triangle can't be constructed with given
    # angles that have sides with the given ratio.
    #
    if sin_a <= 1 and sin_aY <= 1:
      a = pdmath.asin(sin_a)
      aY = pdmath.asin(sin_aY)
     
      # Note: results below may create zero-divisions, be sure to put fabs check
      # above 0.0001.  sine of small angles approaching zero means triangle is
      # practically flat anyway.
      # -blahdy
      #
      # c = pdFCS_PI - a - b
      # sin_c = pdmath.sin(c)
      # B = C * ( sin_b / sin_c )
     
      if check == 0:
        targetHeading.X += aY
        targetHeading.Y += a
    else:
      pdFCS.com.exp.teamchat( "PAC-3 ERINT", 2, "<#f30>ABORT CHECK SINE LAW</> (Unable to validate firing solution.) </>" )
      return False

           
The position of target, the predicted point of interception and our current position all make up to form up a triangle. The law of sines can be used to compute the polar angles required to point ourselves to intercept the moving target. The sides of triangle are made up of speed of our missile and speed of our target.  They are not actual lengths, but that doesn't matter -- what matters is the ratio of the sides.  This technique is basically a triangulation.

The above code returns the polar angles required for us to make our shot against the target, but unfortunately, this actually does not work in practice.  As our missile projectile is flying to intercept the target, the target is also flying as fast as we are.  This creates a situation where the angles of the aforementioned triangle are changing very rapidly every frame -- especially when our missile and the target are aiming to collide head-on.  The angle closure rate is too high.

To mitigate the high angle closing rate, we would need to implement some form of feedback loop to predict the rate of angle closure and simulate interception ahead of time.  A rather simpler method we ended up trying is to use the fact that two objects are on a collision course when their direct line of sight (LOS) does not change direction. We measure the rate at which LOS angle is changing every frame (LOS rate) and verify whether we are sufficiently aiming our missile velocity vector proportional to the LOS rate, and in the same direction. This in effect is a form of Proportional Navigation.

The third option we use to further mitigate high angle closures against high speed targets is to spawn and maneuver the interceptor so that it is perpendicularly oriented toward the target, usually on top of it due to ballistic trajectory of SAM.  By hitting the target from perpendicular axis, the angle closure rate is substantially reduced, compared to a high speed head-on collision.

Pros:

  • Similar in conceptual idea to military-grade fire directors, except in real-life they are 1000 times more complicated and take into account for wind, gravity, etc, all of which are ignored in our game.
  • Ideal for hit-to-kill interception of a high speed target, great for ballistic missile defense.

Cons:

  • Most complex out of all three methods to implement.
  • High rate of closure significantly affects accuracy, thus mitigation methods need to be provided.

Examples:
PAC-3 missiles in the mod use trigonometric firing solution combined with proportional navigation to make their kills during end-game shots (terminal guidance).

You can see the trigonometric law of sines and proportional navigation pricinples in action in the video below.  Notice how the intercepts look like they are forming up a triangle.


Post comment Comments
Fxor
Fxor Jan 3 2011, 3:28am says:

*brain explodes*

+2 votes     reply to comment
aloha2436
aloha2436 Jan 3 2011, 6:34am says:

AND THEY SAID HIGH SCHOOL MATH WOULD NEVER AMOUNT TO ANYTHING

+9 votes     reply to comment
Starkiller2356
Starkiller2356 Jan 3 2011, 9:37am says:

WOW that is crazy!

+1 vote     reply to comment
P3ACE753
P3ACE753 Jan 3 2011, 2:55pm says:

EPIC MOD IS EPIC !

+1 vote     reply to comment
Post a Comment
click to sign in

You are not logged in, your comment will be anonymous unless you join the community today (totally free - or sign in with your social account on the right) which we encourage all contributors to do.

2000 characters limit; HTML formatting and smileys are not supported - text only

Track this mod Profile
Icon
World in Conflict Icon
Platform
Windows
Contact
Send Message
Official Page
Wicmwmod.com
Release Date
Released Dec 22, 2011
Mod Watch
Track this mod
Tutorial
Browse
Tutorials
Report Abuse
Report article
Related Mods
WIC: Modern Warfare Mod 4 (World in Conflict)
WIC: Modern Warfare Mod 4 World in Conflict - Single & Multiplayer Real Time Strategy
Related Games
World in Conflict
World in Conflict Single & Multiplayer Real Time Tactics
Related Groups
WIC : Modern Warfare Mod Team
WIC : Modern Warfare Mod Team Developer with 22 members