< Summary

Class:OrthogonalEvasion
Assembly:bamlab.micromissiles
File(s):/github/workspace/Assets/Scripts/Evasion/OrthogonalEvasion.cs
Covered lines:27
Uncovered lines:8
Coverable lines:35
Total lines:78
Line coverage:77.1% (27 of 35)
Covered branches:0
Total branches:0
Covered methods:3
Total methods:3
Method coverage:100% (3 of 3)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
OrthogonalEvasion(...)0%110100%
ShouldEvade(...)0%11110100%
Evade(...)0%8.817066.67%

File(s)

/github/workspace/Assets/Scripts/Evasion/OrthogonalEvasion.cs

#LineLine coverage
 1using UnityEngine;
 2
 3// The agent will try to evade its pursuer by turning its velocity vector to be orthogonal to the
 4// pursuer's velocity vector.
 5//
 6// Turning orthogonal to the pursuer means that the pursuer needs to apply a normal acceleration to
 7// intercept the agent, incurring the maximum possible lift-induced drag.
 8public class OrthogonalEvasion : EvasionBase {
 219  public OrthogonalEvasion(IAgent agent) : base(agent) {}
 10
 11  // Determine whether to perform any evasive maneuvers.
 312  public override bool ShouldEvade(IAgent pursuer) {
 413    if (!(Agent.AgentConfig?.DynamicConfig?.FlightConfig?.EvasionConfig?.Enabled ?? false)) {
 114      return false;
 15    }
 16
 217    SensorOutput sensorOutput = Agent.Sensor.Sense(pursuer);
 218    float evasionRangeThreshold =
 19        Agent.AgentConfig.DynamicConfig.FlightConfig.EvasionConfig.RangeThreshold;
 220    return sensorOutput.Position.Range <= evasionRangeThreshold && sensorOutput.Velocity.Range < 0;
 321  }
 22
 23  // Calculate the acceleration input to evade the pursuer.
 424  public override Vector3 Evade(IAgent pursuer) {
 25    const float epsilon = 1e-6f;
 26    const float groundProximityThresholdFactor = 5f;
 27    const float groundAvoidanceUpFactor = 5f;
 28
 429    Vector3 agentPosition = Agent.Position;
 430    Vector3 agentVelocity = Agent.Velocity;
 431    Vector3 pursuerPosition = pursuer.Position;
 432    Vector3 pursuerVelocity = pursuer.Velocity;
 33
 34    // Evade the pursuer by turning the velocity to be orthogonal to the pursuer's velocity.
 435    Vector3 normalVelocity = Vector3.ProjectOnPlane(agentVelocity, pursuerVelocity);
 536    if (normalVelocity.sqrMagnitude < epsilon) {
 37      // If the agent's velocity is aligned with the pursuer's velocity, choose a random normal
 38      // direction in which to evade.
 139      normalVelocity = pursuer.Right;
 140    }
 41    // If the agent's velocity is aligned with the normal velocity, i.e., orthogonal to the
 42    // pursuer's velocity, then the normal acceleration should be zero as the agent should continue
 43    // in the same direction.
 444    Vector3 normalAccelerationDirection =
 45        Vector3.ProjectOnPlane(normalVelocity, agentVelocity).normalized;
 46
 47    // Turn away from the pursuer.
 448    Vector3 relativePosition = pursuerPosition - agentPosition;
 449    if (Vector3.Dot(relativePosition, normalAccelerationDirection) > 0) {
 050      normalAccelerationDirection *= -1;
 051    }
 52
 53    // Avoid evading straight down when near the ground.
 454    float altitude = agentPosition.y;
 455    float groundProximityThreshold = Mathf.Abs(agentVelocity.y) * groundProximityThresholdFactor;
 456    if (agentVelocity.y < 0 && altitude < groundProximityThreshold) {
 57      // Determine the evasion direction based on the angle to pursuer.
 058      float angle = Vector3.SignedAngle(Agent.Forward, relativePosition, Vector3.up);
 59
 60      // Choose the direction that leads away from the pursuer.
 061      Vector3 rightDirection = Agent.Right;
 062      Vector3 bestHorizontalDirection = angle > 0 ? -rightDirection : rightDirection;
 63
 64      // Blend between horizontal evasion and slight upward movement.
 065      float blendFactor = 1 - (altitude / groundProximityThreshold);
 066      normalAccelerationDirection =
 67          Vector3
 68              .Lerp(normalAccelerationDirection,
 69                    bestHorizontalDirection + Agent.Up * groundAvoidanceUpFactor, blendFactor)
 70              .normalized;
 071    }
 472    Vector3 normalAcceleration = normalAccelerationDirection * Agent.MaxNormalAcceleration();
 73
 74    // Apply the maximum forward acceleration.
 475    Vector3 forwardAcceleration = Agent.Forward * Agent.MaxForwardAcceleration();
 476    return normalAcceleration + forwardAcceleration;
 477  }
 78}