AirControl  1.3.0
Open Source, Modular, and Extensible Flight Simulator For Deep Learning Research
AC_Airplane_Characteristics.cs
1 using System.Collections;
2 using System.Collections.Generic;
3 using UnityEngine;
4 using Commons;
5 
6 namespace AirControl
7 {
11  public class AC_Airplane_Characteristics : MonoBehaviour
12  {
13  #region Varaibles
14  [Header("Characteristics Properties")]
15  private float maxMPH;
16  private float rbLerpSpeed;
17 
18 
19  [Header("Lift Properties")]
20  private float maxLiftPower;
21  public AnimationCurve liftCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
22  private float flapLiftPower;
23 
24 
25  [Header("Drag Properties")]
26  private float dragFactor;
27  private float flapDragFactor;
28 
29 
30  [Header("Control Properties")]
31  private float pitchSpeed;
32  private float rollSpeed;
33  private float yawSpeed;
34  public AnimationCurve controlSurfaceEfficiency = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
35 
36  public float forwardSpeed;
37  public float ForwardSpeed
38  {
39  get{return forwardSpeed;}
40  }
41 
42  private float mph;
43  public float MPH
44  {
45  get{return mph;}
46  }
47 
48  private AC_BaseAirplane_Input input;
49  private Rigidbody rb;
50  private float startDrag;
51  private float startAngularDrag;
52 
53  private float maxMPS;
54  private float normalizeMPH;
55 
56  private float angleOfAttack;
57  private float pitchAngle;
58  private float rollAngle;
59 
60  private float csEfficiencyValue;
61  #endregion
62 
63  #region Constants
64  const float mpsToMph = 2.23694f;
65  #endregion
66 
67  #region BuiltIn Methods
68  void Start(){
69  maxMPH = (float)CommonFunctions.airplanePreset[CommonFunctions.ActiveAirplane+"/maxMPH"];
70  rbLerpSpeed = (float)CommonFunctions.airplanePreset[CommonFunctions.ActiveAirplane+"/rbLerpSpeed"];
71 
72  maxLiftPower = (float)CommonFunctions.airplanePreset[CommonFunctions.ActiveAirplane+"/maxLiftPower"] ;
73  flapLiftPower = (float)CommonFunctions.airplanePreset[CommonFunctions.ActiveAirplane+"/flapLiftPower"];
74 
75  dragFactor = (float)CommonFunctions.airplanePreset[CommonFunctions.ActiveAirplane+"/dragFactor"];
76  flapDragFactor = (float)CommonFunctions.airplanePreset[CommonFunctions.ActiveAirplane+"/flapDragFactor"];
77 
78  pitchSpeed = (float)CommonFunctions.airplanePreset[CommonFunctions.ActiveAirplane+"/pitchSpeed"];
79  rollSpeed = (float)CommonFunctions.airplanePreset[CommonFunctions.ActiveAirplane+"/rollSpeed"];
80  yawSpeed = (float)CommonFunctions.airplanePreset[CommonFunctions.ActiveAirplane+"/yawSpeed"];
81  }
82  #endregion
83 
84  #region Custom Methods
85  public void InitCharacteristics(Rigidbody curRB, AC_BaseAirplane_Input curInput)
91  {
92  //Basic Initialization
93  input = curInput;
94  rb = curRB;
95  startDrag = rb.drag;
96  startAngularDrag = rb.angularDrag;
97 
98  //Find the max Meters Per Second
99  maxMPS = maxMPH / mpsToMph;
100  }
101 
105  public void UpdateCharacteristics()
106  {
107  if(rb)
108  {
109  //Process the Flight Physics
110  CalculateForwardSpeed();
111  CalculateLift();
112  CalculateDrag();
113 
114  //Process Control
115  HandleControlSurfaceEfficiency();
116  HandleYaw();
117  HandlePitch();
118  HandleRoll();
119  HandleBanking();
120 
121  //Handle Rigidbody
122  HandleRigidbodyTransform();
123  }
124  }
128  void CalculateForwardSpeed()
129  {
130  //Transform the Rigidbody velocity vector from world space to local space
131  Vector3 localVelocity = transform.InverseTransformDirection(rb.velocity);
132  forwardSpeed = Mathf.Max(0f, localVelocity.z);
133  // forwardSpeed = Mathf.Clamp(forwardSpeed, 0f, maxMPS);
134 
135  //find the Miles Per Hour from Meters Per Second
136  mph = forwardSpeed * mpsToMph;
137  // mph = Mathf.Clamp(mph, 0f, maxMPH);
138  normalizeMPH = Mathf.InverseLerp(0f, maxMPH, mph);
139  }
140 
141 
145  void CalculateLift()
146  {
147  //Get the angle of Attack
148  angleOfAttack = Vector3.Dot(rb.velocity.normalized, transform.forward);
149  angleOfAttack *= angleOfAttack;
150 
151  //Create the Lift Direction
152  Vector3 liftDir = transform.up;
153  float liftPower = liftCurve.Evaluate(normalizeMPH) * maxLiftPower;
154 
155  // //Add Flap Lift
156  // float finalLiftPower = flapLiftPower * input.NormalizedFlaps;
157 
158  //Apply the final Lift Force to the Rigidbody
159  Vector3 finalLiftForce = liftDir * (liftPower) * angleOfAttack;
160  rb.AddForce(finalLiftForce);
161  }
162 
166  void CalculateDrag()
167  {
168  //Speed Drag
169  float speedDrag = forwardSpeed * dragFactor;
170 
171  //Flap Drag
172  float flapDrag = input.Flaps * flapDragFactor;
173 
174  //add it all together!
175  float finalDrag = startDrag + speedDrag + flapDrag;
176 
177  rb.drag = finalDrag;
178  rb.angularDrag = startAngularDrag * forwardSpeed;
179  }
180 
184  void HandleRigidbodyTransform()
185  {
186  if(rb.velocity.magnitude > 1f)
187  {
188  Vector3 updatedVelocity = Vector3.Lerp(rb.velocity, transform.forward * forwardSpeed, forwardSpeed * angleOfAttack * Time.deltaTime * rbLerpSpeed);
189  rb.velocity = updatedVelocity;
190 
191 
192  Quaternion updatedRotation = Quaternion.Slerp(rb.rotation, Quaternion.LookRotation(rb.velocity, transform.up), Time.deltaTime * rbLerpSpeed);
193  rb.MoveRotation(updatedRotation);
194  }
195  }
196 
200  void HandleControlSurfaceEfficiency()
201  {
202  csEfficiencyValue = controlSurfaceEfficiency.Evaluate(normalizeMPH);
203  }
204 
208  void HandlePitch()
209  {
210  Vector3 flatForward = transform.forward;
211  flatForward.y = 0f;
212  flatForward = flatForward.normalized;
213  pitchAngle = Vector3.Angle(transform.forward, flatForward);
214  // Debug.Log(pitchAngle);
215 
216  Vector3 pitchTorque = input.Pitch * pitchSpeed * transform.right * csEfficiencyValue;
217  rb.AddTorque(pitchTorque);
218  }
219 
223  void HandleRoll()
224  {
225  Vector3 flatRight = transform.right;
226  flatRight.y = 0f;
227  flatRight = flatRight.normalized;
228  rollAngle = Vector3.SignedAngle(transform.right, flatRight, transform.forward);
229  // Debug.Log(rollAngle);
230 
231  Vector3 rollTorque = -input.Roll * rollSpeed * transform.forward * csEfficiencyValue;
232  rb.AddTorque(rollTorque);
233  }
234 
238  void HandleYaw()
239  {
240  Vector3 yawTorque = input.Yaw * yawSpeed * transform.up * csEfficiencyValue;
241  rb.AddTorque(yawTorque);
242  }
243 
247  void HandleBanking()
248  {
249  float bankSide = Mathf.InverseLerp(-90f, 90f, rollAngle);
250  float bankAmount = Mathf.Lerp(-1f, 1f, bankSide);
251  Vector3 bankTorque = bankAmount * rollSpeed * transform.up;
252  rb.AddTorque(bankTorque);
253  }
254 
255  // /// <summary>
256  // /// Get the local forward speed in Meters per second and convert it to Miles Per Hour
257  // /// </summary>
258  // void CalculateForwardSpeed()
259  // {
260  // //Transform the Rigidbody velocity vector from world space to local space
261  // Vector3 localVelocity = transform.InverseTransformDirection(rb.velocity);
262  // forwardSpeed = Mathf.Max(0f, localVelocity.z);
263  // // forwardSpeed = Mathf.Clamp(forwardSpeed, 0f, maxMPS);
264 
265  // //find the Miles Per Hour from Meters Per Second
266  // mph = forwardSpeed * mpsToMph;
267  // // mph = Mathf.Clamp(mph, 0f, maxMPH);
268  // normalizeMPH = Mathf.InverseLerp(0f, maxMPH, mph);
269  // }
270 
271 
272  // /// <summary>
273  // /// Build a lift force strong enough to lift he plane off the ground
274  // /// </summary>
275  // void CalculateLift()
276  // {
277  // //Get the angle of Attack
278  // angleOfAttack = Vector3.Dot(rb.velocity.normalized, transform.forward);
279  // angleOfAttack *= angleOfAttack;
280 
281  // //Create the Lift Direction
282  // Vector3 liftDir = transform.up;
283  // float liftPower = liftCurve.Evaluate(normalizeMPH) * maxLiftPower;
284 
285  // //Add Flap Lift
286  // float finalLiftPower = flapLiftPower * input.NormalizedFlaps;
287  // //Apply the final Lift Force to the Rigidbody
288  // Vector3 finalLiftForce = liftDir * ((liftPower * angleOfAttack) + finalLiftPower);
289  // rb.AddForce(finalLiftForce);
290  // }
291 
292  // /// <summary>
293  // /// Get a Drag force to keep the plane relatively stable in the air
294  // /// </summary>
295  // void CalculateDrag()
296  // {
297  // //Speed Drag
298  // float speedDrag = forwardSpeed * dragFactor;
299 
300  // //Flap Drag
301  // float flapDrag = input.Flaps * flapDragFactor;
302 
303  // //add it all together!
304  // float finalDrag = startDrag + speedDrag + (flapDrag*input.NormalizedFlaps);
305 
306  // rb.drag = finalDrag;
307  // rb.angularDrag = startAngularDrag * forwardSpeed;
308  // }
309 
310  // /// <summary>
311  // /// Control Airplane stabilization
312  // /// </summary>
313  // void HandleRigidbodyTransform()
314  // {
315  // if(rb.velocity.magnitude > 1f)
316  // {
317  // Vector3 updatedVelocity = Vector3.Lerp(rb.velocity, transform.forward * forwardSpeed, forwardSpeed * angleOfAttack * Time.deltaTime * rbLerpSpeed);
318  // rb.velocity = updatedVelocity;
319 
320 
321  // Quaternion updatedRotation = Quaternion.Slerp(rb.rotation, Quaternion.LookRotation(rb.velocity, transform.up), Time.deltaTime * rbLerpSpeed);
322  // rb.MoveRotation(updatedRotation);
323  // }
324  // }
325 
326  // /// <summary>
327  // /// Control surface effciency mapping
328  // /// </summary>
329  // void HandleControlSurfaceEfficiency()
330  // {
331  // csEfficiencyValue = controlSurfaceEfficiency.Evaluate(normalizeMPH);
332  // }
333 
334  // /// <summary>
335  // /// Handle Airplane Pitch
336  // /// </summary>
337  // void HandlePitch()
338  // {
339  // Vector3 flatForward = transform.forward;
340  // flatForward.y = 0f;
341  // flatForward = flatForward.normalized;
342  // pitchAngle = Vector3.Angle(transform.forward, flatForward);
343  // // Debug.Log(pitchAngle);
344 
345  // Vector3 pitchTorque = input.Pitch * pitchSpeed * transform.right * csEfficiencyValue;
346  // Debug.Log(pitchTorque);
347  // }
348 
349  // /// <summary>
350  // /// Handle Airplane Roll
351  // /// </summary>
352  // void HandleRoll()
353  // {
354  // Vector3 flatRight = transform.right;
355  // flatRight.y = 0f;
356  // flatRight = flatRight.normalized;
357  // rollAngle = Vector3.SignedAngle(transform.right, flatRight, transform.forward);
358  // // Debug.Log(rollAngle);
359 
360  // Vector3 rollTorque = -input.Roll * rollSpeed * transform.forward * csEfficiencyValue;
361  // rb.AddTorque(rollTorque);
362  // }
363 
364  // /// <summary>
365  // /// Handle Airplane Yaw
366  // /// </summary>
367  // void HandleYaw()
368  // {
369  // Vector3 yawTorque = input.Yaw * yawSpeed * transform.up * csEfficiencyValue;
370  // rb.AddTorque(yawTorque);
371  // }
372 
373  // /// <summary>
374  // /// Handle Airplane Braking
375  // /// </summary>
376  // void HandleBanking()
377  // {
378  // float bankSide = Mathf.InverseLerp(-90f, 90f, rollAngle);
379  // float bankAmount = Mathf.Lerp(-1f, 1f, bankSide);
380  // Vector3 bankTorque = bankAmount * rollSpeed * transform.up;
381  // rb.AddTorque(bankTorque);
382  // }
383  #endregion
384  }
385 }
AirControl.AC_BaseAirplane_Input
Base class to listen for keyboard Inputs
Definition: AC_BaseAirplane_Input.cs:12
AirControl.AC_Airplane_Characteristics.InitCharacteristics
void InitCharacteristics(Rigidbody curRB, AC_BaseAirplane_Input curInput)
Initialize Airplane Charatceristics
Definition: AC_Airplane_Characteristics.cs:90
AirControl.AC_Airplane_Characteristics.UpdateCharacteristics
void UpdateCharacteristics()
Update all the Flight Characteristics methods
Definition: AC_Airplane_Characteristics.cs:105
AirControl
Definition: AirplaneSelector.cs:8
Commons
Definition: AirplaneProperties.cs:14
AirControl.AC_Airplane_Characteristics
Main class defines the Airplane Characteristics
Definition: AC_Airplane_Characteristics.cs:11