| | 1 | | using System.Collections; |
| | 2 | | using System.Collections.Generic; |
| | 3 | | using UnityEngine; |
| | 4 | |
|
| | 5 | | public abstract class Agent : MonoBehaviour { |
| | 6 | | // In the initialized phase, the agent is subject to no forces. |
| | 7 | | // In the ready phase, the agent is subject to gravity and drag with zero input acceleration. |
| | 8 | | public enum FlightPhase { INITIALIZED, READY, BOOST, MIDCOURSE, TERMINAL, TERMINATED } |
| | 9 | |
|
| | 10 | | [SerializeField] |
| 41 | 11 | | private FlightPhase _flightPhase = FlightPhase.INITIALIZED; |
| | 12 | |
|
| | 13 | | [SerializeField] |
| | 14 | | protected Vector3 _velocity; |
| | 15 | |
|
| | 16 | | [SerializeField] |
| | 17 | | protected Vector3 _acceleration; |
| | 18 | |
|
| | 19 | | [SerializeField] |
| | 20 | | protected Vector3 _dragAcceleration; |
| | 21 | |
|
| | 22 | | [SerializeField] |
| | 23 | | // Only for debugging (viewing in editor) |
| | 24 | | // Don't bother setting this it won't be used |
| | 25 | | protected float _speed; |
| | 26 | |
|
| | 27 | | [SerializeField] |
| 41 | 28 | | protected List<Agent> _interceptors = new List<Agent>(); |
| | 29 | | [SerializeField] |
| | 30 | | protected Agent _target; |
| | 31 | | [SerializeField] |
| | 32 | | protected Agent _targetModel; |
| 41 | 33 | | protected bool _isHit = false; |
| 41 | 34 | | protected bool _isMiss = false; |
| | 35 | |
|
| | 36 | | [SerializeField] |
| 41 | 37 | | protected double _timeSinceBoost = 0; |
| | 38 | | [SerializeField] |
| 41 | 39 | | protected double _timeInPhase = 0; |
| | 40 | |
|
| | 41 | | public StaticAgentConfig staticAgentConfig; |
| | 42 | | public DynamicAgentConfig dynamicAgentConfig; |
| | 43 | |
|
| | 44 | | // Define delegates |
| | 45 | | // MarkDestroyed event handler |
| | 46 | | public delegate void TerminatedEventHandler(Agent agent); |
| | 47 | | public event TerminatedEventHandler OnTerminated; |
| | 48 | |
|
| | 49 | | public delegate void InterceptHitEventHandler(Interceptor interceptor, Threat target); |
| | 50 | | public delegate void InterceptMissEventHandler(Interceptor interceptor, Threat target); |
| | 51 | | public delegate void ThreatHitEventHandler(Threat threat); |
| | 52 | | public delegate void ThreatMissEventHandler(Threat threat); |
| | 53 | |
|
| | 54 | | // Define events |
| | 55 | | public event InterceptHitEventHandler OnInterceptHit; |
| | 56 | | public event InterceptMissEventHandler OnInterceptMiss; |
| | 57 | | public event ThreatHitEventHandler OnThreatHit; |
| | 58 | | public event ThreatMissEventHandler OnThreatMiss; |
| | 59 | |
|
| | 60 | | private Vector3 _initialVelocity; |
| | 61 | |
|
| 15 | 62 | | public void SetFlightPhase(FlightPhase flightPhase) { |
| 15 | 63 | | _timeInPhase = 0; |
| 15 | 64 | | _flightPhase = flightPhase; |
| 15 | 65 | | if (flightPhase == FlightPhase.INITIALIZED || flightPhase == FlightPhase.TERMINATED) { |
| 0 | 66 | | GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll; |
| 15 | 67 | | } else { |
| 15 | 68 | | GetComponent<Rigidbody>().constraints = RigidbodyConstraints.None; |
| 15 | 69 | | } |
| 15 | 70 | | if (flightPhase == FlightPhase.BOOST) { |
| 0 | 71 | | SetVelocity(GetVelocity() + _initialVelocity); |
| 0 | 72 | | } |
| 15 | 73 | | } |
| | 74 | |
|
| 0 | 75 | | public FlightPhase GetFlightPhase() { |
| 0 | 76 | | return _flightPhase; |
| 0 | 77 | | } |
| | 78 | |
|
| 0 | 79 | | public bool HasLaunched() { |
| 0 | 80 | | return _flightPhase != FlightPhase.INITIALIZED; |
| 0 | 81 | | } |
| | 82 | |
|
| 0 | 83 | | public bool HasTerminated() { |
| 0 | 84 | | return _flightPhase == FlightPhase.TERMINATED; |
| 0 | 85 | | } |
| | 86 | |
|
| 15 | 87 | | public virtual void SetDynamicAgentConfig(DynamicAgentConfig config) { |
| 15 | 88 | | dynamicAgentConfig = config; |
| 15 | 89 | | } |
| | 90 | |
|
| 15 | 91 | | public virtual void SetStaticAgentConfig(StaticAgentConfig config) { |
| 15 | 92 | | staticAgentConfig = config; |
| 15 | 93 | | GetComponent<Rigidbody>().mass = staticAgentConfig.bodyConfig.mass; |
| 15 | 94 | | } |
| | 95 | |
|
| 0 | 96 | | public virtual bool IsAssignable() { |
| 0 | 97 | | return true; |
| 0 | 98 | | } |
| | 99 | |
|
| 0 | 100 | | public virtual void AssignTarget(Agent target) { |
| 0 | 101 | | _target = target; |
| 0 | 102 | | _target.AddInterceptor(this); |
| 0 | 103 | | _targetModel = SimManager.Instance.CreateDummyAgent(target.GetPosition(), target.GetVelocity()); |
| 0 | 104 | | } |
| | 105 | |
|
| 0 | 106 | | public Agent GetAssignedTarget() { |
| 0 | 107 | | return _target; |
| 0 | 108 | | } |
| | 109 | |
|
| 6 | 110 | | public bool HasAssignedTarget() { |
| 6 | 111 | | return _target != null; |
| 6 | 112 | | } |
| | 113 | |
|
| 0 | 114 | | public Agent GetTargetModel() { |
| 0 | 115 | | return _targetModel; |
| 0 | 116 | | } |
| | 117 | |
|
| 0 | 118 | | public void CheckTargetHit() { |
| 0 | 119 | | if (HasAssignedTarget() && _target.IsHit()) { |
| 0 | 120 | | UnassignTarget(); |
| 0 | 121 | | } |
| 0 | 122 | | } |
| | 123 | |
|
| 0 | 124 | | public virtual void UnassignTarget() { |
| 0 | 125 | | _target.RemoveInterceptor(this); |
| 0 | 126 | | _target = null; |
| 0 | 127 | | _targetModel = null; |
| 0 | 128 | | } |
| | 129 | |
|
| | 130 | | // Return whether the agent has hit or been hit. |
| 0 | 131 | | public bool IsHit() { |
| 0 | 132 | | return _isHit; |
| 0 | 133 | | } |
| | 134 | |
|
| 0 | 135 | | public void AddInterceptor(Agent interceptor) { |
| 0 | 136 | | _interceptors.Add(interceptor); |
| 0 | 137 | | } |
| | 138 | |
|
| 0 | 139 | | public void RemoveInterceptor(Agent interceptor) { |
| 0 | 140 | | _interceptors.Remove(interceptor); |
| 0 | 141 | | } |
| | 142 | |
|
| 0 | 143 | | public virtual void TerminateAgent() { |
| 0 | 144 | | if (_flightPhase != FlightPhase.TERMINATED) { |
| 0 | 145 | | OnTerminated?.Invoke(this); |
| 0 | 146 | | } |
| 0 | 147 | | _flightPhase = FlightPhase.TERMINATED; |
| 0 | 148 | | SetPosition(new Vector3(0, 0, 0)); |
| 0 | 149 | | gameObject.SetActive(false); |
| 0 | 150 | | } |
| | 151 | |
|
| | 152 | | // Mark the agent as having hit the target or been hit. |
| 0 | 153 | | public void HandleInterceptHit(Agent otherAgent) { |
| 0 | 154 | | _isHit = true; |
| 0 | 155 | | if (this is Interceptor interceptor && otherAgent is Threat threat) { |
| 0 | 156 | | OnInterceptHit?.Invoke(interceptor, threat); |
| 0 | 157 | | } else if (this is Threat threatAgent && otherAgent is Interceptor interceptorTarget) { |
| 0 | 158 | | OnInterceptHit?.Invoke(interceptorTarget, threatAgent); |
| 0 | 159 | | } |
| 0 | 160 | | TerminateAgent(); |
| 0 | 161 | | } |
| | 162 | |
|
| 0 | 163 | | public void HandleInterceptMiss() { |
| 0 | 164 | | if (_target != null) { |
| 0 | 165 | | if (this is Interceptor interceptor && _target is Threat threat) { |
| 0 | 166 | | OnInterceptMiss?.Invoke(interceptor, threat); |
| 0 | 167 | | } else if (this is Threat threatAgent && _target is Interceptor interceptorTarget) { |
| 0 | 168 | | OnInterceptMiss?.Invoke(interceptorTarget, threatAgent); |
| 0 | 169 | | } |
| 0 | 170 | | UnassignTarget(); |
| 0 | 171 | | } |
| 0 | 172 | | TerminateAgent(); |
| 0 | 173 | | } |
| | 174 | |
|
| | 175 | | // This happens if we, e.g., hit the carrier |
| 0 | 176 | | public void HandleThreatHit() { |
| 0 | 177 | | _isHit = true; |
| 0 | 178 | | if (this is Threat threat) { |
| 0 | 179 | | OnThreatHit?.Invoke(threat); |
| 0 | 180 | | } |
| 0 | 181 | | TerminateAgent(); |
| 0 | 182 | | } |
| | 183 | |
|
| | 184 | | // This happens if we, e.g., hit the floor |
| 0 | 185 | | public void HandleThreatMiss() { |
| 0 | 186 | | if (this is Threat threat) { |
| 0 | 187 | | OnThreatMiss?.Invoke(threat); |
| 0 | 188 | | } |
| 0 | 189 | | TerminateAgent(); |
| 0 | 190 | | } |
| | 191 | |
|
| 15 | 192 | | public void SetInitialVelocity(Vector3 velocity) { |
| 15 | 193 | | _initialVelocity = velocity; |
| 15 | 194 | | } |
| | 195 | |
|
| 14 | 196 | | public Vector3 GetPosition() { |
| 14 | 197 | | return transform.position; |
| 14 | 198 | | } |
| | 199 | |
|
| 4 | 200 | | public void SetPosition(Vector3 position) { |
| 4 | 201 | | transform.position = position; |
| 4 | 202 | | } |
| | 203 | |
|
| 8 | 204 | | public double GetSpeed() { |
| 8 | 205 | | return GetComponent<Rigidbody>().linearVelocity.magnitude; |
| 8 | 206 | | } |
| | 207 | |
|
| 34 | 208 | | public Vector3 GetVelocity() { |
| 34 | 209 | | return GetComponent<Rigidbody>().linearVelocity; |
| 34 | 210 | | } |
| | 211 | |
|
| 1 | 212 | | public void SetVelocity(Vector3 velocity) { |
| 1 | 213 | | GetComponent<Rigidbody>().linearVelocity = velocity; |
| 1 | 214 | | } |
| | 215 | |
|
| 3 | 216 | | public Vector3 GetAcceleration() { |
| 3 | 217 | | return _acceleration; |
| 3 | 218 | | } |
| | 219 | |
|
| 0 | 220 | | public void SetAcceleration(Vector3 acceleration) { |
| 0 | 221 | | _acceleration = acceleration; |
| 0 | 222 | | } |
| | 223 | |
|
| 3 | 224 | | public Transformation GetRelativeTransformation(Agent target) { |
| 3 | 225 | | Transformation transformation = new Transformation(); |
| | 226 | |
|
| | 227 | | // Get the relative position transformation. |
| 3 | 228 | | transformation.position = GetRelativePositionTransformation(target.GetPosition()); |
| | 229 | |
|
| | 230 | | // Get the relative velocity transformation. |
| 3 | 231 | | transformation.velocity = GetRelativeVelocityTransformation( |
| | 232 | | target.GetPosition() - GetPosition(), target.GetVelocity() - GetVelocity()); |
| | 233 | |
|
| | 234 | | // Get the relative acceleration transformation. |
| 3 | 235 | | transformation.acceleration = GetRelativeAccelerationTransformation(target); |
| 3 | 236 | | return transformation; |
| 3 | 237 | | } |
| | 238 | |
|
| 5 | 239 | | public Transformation GetRelativeTransformationToWaypoint(Vector3 waypoint) { |
| 5 | 240 | | Transformation transformation = new Transformation(); |
| | 241 | |
|
| | 242 | | // Get the relative position transformation. |
| 5 | 243 | | transformation.position = GetRelativePositionTransformation(waypoint); |
| | 244 | |
|
| | 245 | | // Get the relative velocity transformation. |
| 5 | 246 | | transformation.velocity = |
| | 247 | | GetRelativeVelocityTransformation(waypoint - GetPosition(), -GetVelocity()); |
| | 248 | |
|
| 5 | 249 | | return transformation; |
| 5 | 250 | | } |
| | 251 | |
|
| 8 | 252 | | private PositionTransformation GetRelativePositionTransformation(Vector3 relativePosition) { |
| 8 | 253 | | PositionTransformation positionTransformation = new PositionTransformation(); |
| | 254 | |
|
| | 255 | | // Set the relative position in Cartesian coordinates |
| 8 | 256 | | positionTransformation.cartesian = relativePosition; |
| | 257 | |
|
| | 258 | | // Calculate the distance (range) to the target |
| 8 | 259 | | positionTransformation.range = relativePosition.magnitude; |
| | 260 | |
|
| 8 | 261 | | Vector3 flatRelativePosition = Vector3.ProjectOnPlane(relativePosition, transform.up); |
| 8 | 262 | | Vector3 verticalRelativePosition = relativePosition - flatRelativePosition; |
| | 263 | |
|
| | 264 | | // Calculate elevation (vertical angle relative to forward) |
| 8 | 265 | | positionTransformation.elevation = |
| | 266 | | Mathf.Atan(verticalRelativePosition.magnitude / flatRelativePosition.magnitude); |
| | 267 | |
|
| | 268 | | // Calculate azimuth (horizontal angle relative to forward) |
| 9 | 269 | | if (flatRelativePosition.magnitude == 0) { |
| 1 | 270 | | positionTransformation.azimuth = 0; |
| 8 | 271 | | } else { |
| 7 | 272 | | positionTransformation.azimuth = |
| | 273 | | Vector3.SignedAngle(transform.forward, flatRelativePosition, transform.up) * Mathf.PI / |
| | 274 | | 180; |
| 7 | 275 | | } |
| | 276 | |
|
| 8 | 277 | | return positionTransformation; |
| 8 | 278 | | } |
| | 279 | |
|
| | 280 | | private VelocityTransformation GetRelativeVelocityTransformation(Vector3 relativePosition, |
| 8 | 281 | | Vector3 relativeVelocity) { |
| 8 | 282 | | VelocityTransformation velocityTransformation = new VelocityTransformation(); |
| | 283 | |
|
| | 284 | | // Set the relative velocity in Cartesian coordinates. |
| 8 | 285 | | velocityTransformation.cartesian = relativeVelocity; |
| | 286 | |
|
| | 287 | | // Calculate range rate (radial velocity). |
| 8 | 288 | | velocityTransformation.range = Vector3.Dot(relativeVelocity, relativePosition.normalized); |
| | 289 | |
|
| | 290 | | // Project relative velocity onto the sphere passing through the target. |
| 8 | 291 | | Vector3 tangentialVelocity = Vector3.ProjectOnPlane(relativeVelocity, relativePosition); |
| | 292 | |
|
| | 293 | | // The target azimuth vector is orthogonal to the relative position vector and |
| | 294 | | // points to the starboard of the target along the azimuth-elevation sphere. |
| 8 | 295 | | Vector3 targetAzimuth = Vector3.Cross(transform.up, relativePosition); |
| | 296 | | // The target elevation vector is orthogonal to the relative position vector |
| | 297 | | // and points upwards from the target along the azimuth-elevation sphere. |
| 8 | 298 | | Vector3 targetElevation = Vector3.Cross(relativePosition, transform.right); |
| | 299 | | // If the relative position vector is parallel to the yaw or pitch axis, the |
| | 300 | | // target azimuth vector or the target elevation vector will be undefined. |
| 9 | 301 | | if (targetAzimuth.magnitude == 0) { |
| 1 | 302 | | targetAzimuth = Vector3.Cross(targetElevation, relativePosition); |
| 10 | 303 | | } else if (targetElevation.magnitude == 0) { |
| 2 | 304 | | targetElevation = Vector3.Cross(relativePosition, targetAzimuth); |
| 2 | 305 | | } |
| | 306 | |
|
| | 307 | | // Project the relative velocity vector on the azimuth-elevation sphere onto |
| | 308 | | // the target azimuth vector. |
| 8 | 309 | | Vector3 tangentialVelocityOnAzimuth = Vector3.Project(tangentialVelocity, targetAzimuth); |
| | 310 | |
|
| | 311 | | // Calculate the time derivative of the azimuth to the target. |
| 8 | 312 | | velocityTransformation.azimuth = |
| | 313 | | tangentialVelocityOnAzimuth.magnitude / relativePosition.magnitude; |
| 13 | 314 | | if (Vector3.Dot(tangentialVelocityOnAzimuth, targetAzimuth) < 0) { |
| 5 | 315 | | velocityTransformation.azimuth *= -1; |
| 5 | 316 | | } |
| | 317 | |
|
| | 318 | | // Project the velocity vector on the azimuth-elevation sphere onto the target |
| | 319 | | // elevation vector. |
| 8 | 320 | | Vector3 tangentialVelocityOnElevation = Vector3.Project(tangentialVelocity, targetElevation); |
| | 321 | |
|
| | 322 | | // Calculate the time derivative of the elevation to the target. |
| 8 | 323 | | velocityTransformation.elevation = |
| | 324 | | tangentialVelocityOnElevation.magnitude / relativePosition.magnitude; |
| 9 | 325 | | if (Vector3.Dot(tangentialVelocityOnElevation, targetElevation) < 0) { |
| 1 | 326 | | velocityTransformation.elevation *= -1; |
| 1 | 327 | | } |
| | 328 | |
|
| 8 | 329 | | return velocityTransformation; |
| 8 | 330 | | } |
| | 331 | |
|
| 3 | 332 | | private AccelerationTransformation GetRelativeAccelerationTransformation(Agent agent) { |
| | 333 | | // Since the agent's acceleration is an input, the relative acceleration is just the agent's |
| | 334 | | // acceleration. |
| 3 | 335 | | AccelerationTransformation accelerationTransformation = new AccelerationTransformation(); |
| 3 | 336 | | accelerationTransformation.cartesian = agent.GetAcceleration(); |
| 3 | 337 | | return accelerationTransformation; |
| 3 | 338 | | } |
| | 339 | |
|
| 0 | 340 | | public double GetDynamicPressure() { |
| 0 | 341 | | var airDensity = Constants.CalculateAirDensityAtAltitude(transform.position.y); |
| 0 | 342 | | var flowSpeed = GetSpeed(); |
| 0 | 343 | | return 0.5 * airDensity * (flowSpeed * flowSpeed); |
| 0 | 344 | | } |
| | 345 | |
|
| | 346 | | protected abstract void UpdateReady(double deltaTime); |
| | 347 | | protected abstract void UpdateBoost(double deltaTime); |
| | 348 | | protected abstract void UpdateMidCourse(double deltaTime); |
| | 349 | |
|
| 0 | 350 | | protected virtual void Awake() {} |
| | 351 | |
|
| | 352 | | // Start is called before the first frame update |
| 38 | 353 | | protected virtual void Start() {} |
| | 354 | |
|
| | 355 | | // Update is called once per frame |
| 0 | 356 | | protected virtual void FixedUpdate() { |
| 0 | 357 | | _speed = (float)GetSpeed(); |
| 0 | 358 | | if (_flightPhase != FlightPhase.INITIALIZED && _flightPhase != FlightPhase.READY) { |
| 0 | 359 | | _timeSinceBoost += Time.fixedDeltaTime; |
| 0 | 360 | | } |
| 0 | 361 | | _timeInPhase += Time.fixedDeltaTime; |
| | 362 | |
|
| 0 | 363 | | var launch_time = dynamicAgentConfig.dynamic_config.launch_config.launch_time; |
| 0 | 364 | | var boost_time = staticAgentConfig.boostConfig.boostTime; |
| 0 | 365 | | double elapsedSimulationTime = SimManager.Instance.GetElapsedSimulationTime(); |
| | 366 | |
|
| 0 | 367 | | if (_flightPhase == FlightPhase.TERMINATED) { |
| 0 | 368 | | return; |
| | 369 | | } |
| | 370 | |
|
| 0 | 371 | | if (_flightPhase == FlightPhase.INITIALIZED || _flightPhase == FlightPhase.READY) { |
| 0 | 372 | | float launchTimeVariance = 0.5f; |
| 0 | 373 | | float launchTimeNoise = Random.Range(-launchTimeVariance, launchTimeVariance); |
| 0 | 374 | | launch_time += launchTimeNoise; |
| | 375 | |
|
| 0 | 376 | | if (elapsedSimulationTime >= launch_time) { |
| 0 | 377 | | SetFlightPhase(FlightPhase.BOOST); |
| 0 | 378 | | } |
| 0 | 379 | | } |
| 0 | 380 | | if (_timeSinceBoost > boost_time && _flightPhase == FlightPhase.BOOST) { |
| 0 | 381 | | SetFlightPhase(FlightPhase.MIDCOURSE); |
| 0 | 382 | | } |
| 0 | 383 | | AlignWithVelocity(); |
| 0 | 384 | | switch (_flightPhase) { |
| | 385 | | case FlightPhase.INITIALIZED: |
| 0 | 386 | | break; |
| | 387 | | case FlightPhase.READY: |
| 0 | 388 | | UpdateReady(Time.fixedDeltaTime); |
| 0 | 389 | | break; |
| | 390 | | case FlightPhase.BOOST: |
| 0 | 391 | | UpdateBoost(Time.fixedDeltaTime); |
| 0 | 392 | | break; |
| | 393 | | case FlightPhase.MIDCOURSE: |
| | 394 | | case FlightPhase.TERMINAL: |
| 0 | 395 | | UpdateMidCourse(Time.fixedDeltaTime); |
| 0 | 396 | | break; |
| | 397 | | case FlightPhase.TERMINATED: |
| 0 | 398 | | break; |
| | 399 | | } |
| | 400 | |
|
| 0 | 401 | | _velocity = GetVelocity(); |
| | 402 | | // Store the acceleration because it is set to zero after each simulation step |
| 0 | 403 | | _acceleration = |
| | 404 | | GetComponent<Rigidbody>().GetAccumulatedForce() / GetComponent<Rigidbody>().mass; |
| 0 | 405 | | } |
| | 406 | |
|
| 0 | 407 | | protected virtual void AlignWithVelocity() { |
| 0 | 408 | | Vector3 velocity = GetVelocity(); |
| 0 | 409 | | if (velocity.magnitude > 0.1f) // Only align if we have significant velocity |
| 0 | 410 | | { |
| | 411 | | // Create a rotation with forward along velocity and up along world up |
| 0 | 412 | | Quaternion targetRotation = Quaternion.LookRotation(velocity, Vector3.up); |
| | 413 | |
|
| | 414 | | // Smoothly rotate towards the target rotation |
| 0 | 415 | | transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, |
| | 416 | | 10000f * Time.fixedDeltaTime); |
| 0 | 417 | | } |
| 0 | 418 | | } |
| | 419 | |
|
| 0 | 420 | | protected Vector3 CalculateAcceleration(Vector3 accelerationInput) { |
| 0 | 421 | | Vector3 gravity = Physics.gravity; |
| 0 | 422 | | float airDrag = CalculateDrag(); |
| 0 | 423 | | float liftInducedDrag = CalculateLiftInducedDrag(accelerationInput + gravity); |
| 0 | 424 | | float dragAcceleration = -(airDrag + liftInducedDrag); |
| | 425 | |
|
| | 426 | | // Project the drag acceleration onto the forward direction |
| 0 | 427 | | Vector3 dragAccelerationAlongRoll = dragAcceleration * transform.forward; |
| 0 | 428 | | _dragAcceleration = dragAccelerationAlongRoll; |
| | 429 | |
|
| 0 | 430 | | return accelerationInput + gravity + dragAccelerationAlongRoll; |
| 0 | 431 | | } |
| | 432 | |
|
| 6 | 433 | | protected float CalculateMaxForwardAcceleration() { |
| 6 | 434 | | return staticAgentConfig.accelerationConfig.maxForwardAcceleration; |
| 6 | 435 | | } |
| | 436 | |
|
| 8 | 437 | | protected float CalculateMaxNormalAcceleration() { |
| 8 | 438 | | float maxReferenceNormalAcceleration = |
| | 439 | | (float)(staticAgentConfig.accelerationConfig.maxReferenceNormalAcceleration * |
| | 440 | | Constants.kGravity); |
| 8 | 441 | | float referenceSpeed = staticAgentConfig.accelerationConfig.referenceSpeed; |
| 8 | 442 | | return Mathf.Pow((float)GetSpeed() / referenceSpeed, 2) * maxReferenceNormalAcceleration; |
| 8 | 443 | | } |
| | 444 | |
|
| 0 | 445 | | private float CalculateDrag() { |
| 0 | 446 | | float dragCoefficient = staticAgentConfig.liftDragConfig.dragCoefficient; |
| 0 | 447 | | float crossSectionalArea = staticAgentConfig.bodyConfig.crossSectionalArea; |
| 0 | 448 | | float mass = staticAgentConfig.bodyConfig.mass; |
| 0 | 449 | | float dynamicPressure = (float)GetDynamicPressure(); |
| 0 | 450 | | float dragForce = dragCoefficient * dynamicPressure * crossSectionalArea; |
| 0 | 451 | | return dragForce / mass; |
| 0 | 452 | | } |
| | 453 | |
|
| 0 | 454 | | private float CalculateLiftInducedDrag(Vector3 accelerationInput) { |
| 0 | 455 | | float liftAcceleration = Vector3.ProjectOnPlane(accelerationInput, transform.up).magnitude; |
| 0 | 456 | | float liftDragRatio = staticAgentConfig.liftDragConfig.liftDragRatio; |
| 0 | 457 | | return Mathf.Abs(liftAcceleration / liftDragRatio); |
| 0 | 458 | | } |
| | 459 | | } |
| | 460 | |
|
| | 461 | | public class DummyAgent : Agent { |
| | 462 | | protected override void Start() { |
| | 463 | | base.Start(); |
| | 464 | | } |
| | 465 | |
|
| | 466 | | protected override void FixedUpdate() { |
| | 467 | | GetComponent<Rigidbody>().AddForce(_acceleration, ForceMode.Acceleration); |
| | 468 | | } |
| | 469 | |
|
| | 470 | | protected override void UpdateReady(double deltaTime) { |
| | 471 | | // Do nothing |
| | 472 | | } |
| | 473 | |
|
| | 474 | | protected override void UpdateBoost(double deltaTime) { |
| | 475 | | // Do nothing |
| | 476 | | } |
| | 477 | |
|
| | 478 | | protected override void UpdateMidCourse(double deltaTime) { |
| | 479 | | // Do nothing |
| | 480 | | } |
| | 481 | | } |