< Summary

Class:IterativeLaunchPlanner
Assembly:bamlab.micromissiles
File(s):/github/workspace/Assets/Scripts/Algorithms/Planning/IterativeLaunchPlanner.cs
Covered lines:29
Uncovered lines:0
Coverable lines:29
Total lines:84
Line coverage:100% (29 of 29)
Covered branches:0
Total branches:0
Covered methods:2
Total methods:2
Method coverage:100% (2 of 2)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
IterativeLaunchPlanner(...)0%110100%
Plan()0%660100%

File(s)

/github/workspace/Assets/Scripts/Algorithms/Planning/IterativeLaunchPlanner.cs

#LineLine coverage
 1using UnityEngine;
 2
 3// The iterative launch planner class is a launch planner that performs an iterative process to
 4// determine the intercept point. The algorithm continuously performs the following 2-step iterative
 5// process:
 6//  1. Time-to-intercept estimation: The algorithm determines the time it takes the interceptor to
 7//  reach the target at the predicted intercept position, which is initialized to the target's
 8//  current position.
 9//  2. Intercept position estimation: The algorithm predicts the target position at the estimated
 10//  time-to-intercept.
 11public class IterativeLaunchPlanner : LaunchPlannerBase {
 12  // Maximum number of iterations before declaring failure. In certain cases, the predictor and
 13  // planner do not converge, so we need to limit the number of iterations.
 14  private const int _maxNumIterations = 10;
 15
 16  // Convergence threshold in meters for the difference vector magnitude. Convergence is declared
 17  // when the intercept position has not changed by more than this threshold between iterations.
 18  private const float _convergenceThreshold = 10f;
 19
 20  // Maximum intercept position threshold in meters to declare convergence. This threshold is used
 21  // as a final sanity check to ensure that the predicted target position and intercept position do
 22  // not differ by more than this threshold. This threshold should be set depending on the
 23  // granularity of the possible intercept positions.
 24  private const float _interceptPositionThreshold = 1000f;
 25
 26  public IterativeLaunchPlanner(ILaunchAnglePlanner launchAnglePlanner, IPredictor predictor)
 1827      : base(launchAnglePlanner, predictor) {}
 28
 29  // Plan the launch by finding the convergence point between the launch angle planner and the
 30  // predictor.
 631  public override LaunchPlan Plan() {
 632    PredictorState initialState = Predictor.Predict(time: 0f);
 633    Vector3 targetPosition = initialState.Position;
 34
 635    LaunchAngleOutput launchAngleOutput = new LaunchAngleOutput();
 636    Vector3 interceptPosition = new Vector3();
 3337    for (int i = 0; i < _maxNumIterations; ++i) {
 38      // Estimate the time-to-intercept.
 1139      launchAngleOutput = LaunchAnglePlanner.Plan(targetPosition);
 1140      float timeToIntercept = launchAngleOutput.TimeToPosition;
 41
 42      // Estimate the target position.
 1143      PredictorState predictedState = Predictor.Predict(timeToIntercept);
 1144      targetPosition = predictedState.Position;
 45
 46      // Check whether the intercept direction has changed, in which case the algorithm has
 47      // converged.
 1148      Vector3 newInterceptPosition = LaunchAnglePlanner.InterceptPosition(targetPosition);
 1649      if ((interceptPosition - newInterceptPosition).magnitude < _convergenceThreshold) {
 550        interceptPosition = newInterceptPosition;
 551        break;
 52      }
 653      interceptPosition = newInterceptPosition;
 54
 55      // Check that the target is moving towards the intercept position. Otherwise, the interceptor
 56      // should wait to be launched.
 657      Vector3 targetToInterceptPosition = interceptPosition - initialState.Position;
 658      Vector3 targetToPredictedPosition = targetPosition - initialState.Position;
 759      if (Vector3.Dot(targetToInterceptPosition, targetToPredictedPosition) < 0) {
 160        return LaunchPlan.NoLaunch();
 61      }
 562    }
 63
 64    // Check that the interceptor is moving towards the target. If the target is moving too fast,
 65    // the interceptor might be launched backwards because the intercept position and the predicted
 66    // position are behind the asset. In this case, the interceptor should wait to be launched.
 567    Vector3 interceptorToInterceptPosition = interceptPosition - LaunchAnglePlanner.Agent.Position;
 568    Vector3 targetToPredictedTargetPosition = targetPosition - initialState.Position;
 669    if (Vector3.Dot(interceptorToInterceptPosition, targetToPredictedTargetPosition) > 0) {
 170      return LaunchPlan.NoLaunch();
 71    }
 72
 73    // Check that the intercept position and the predicted position are within some threshold
 74    // distance of each other.
 775    if (Vector3.Distance(interceptPosition, targetPosition) < _interceptPositionThreshold) {
 376      return new LaunchPlan {
 77        ShouldLaunch = true,
 78        LaunchAngle = launchAngleOutput.LaunchAngle,
 79        InterceptPosition = targetPosition,
 80      };
 81    }
 182    return LaunchPlan.NoLaunch();
 683  }
 84}