BicyclePhysics.cs 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. using UnityEngine;
  2. namespace Phscs
  3. {
  4. public class BicyclePhysics
  5. {
  6. private const float K_A = 0.5f; //wind resistance coefficient
  7. private const float A = 0.6f; //frontal area bike + rider; m2
  8. private const float D = 1.226f; //air density; kg/m3
  9. /// <summary>
  10. /// Returns a speed in m/s for a bike riding a gradient with the same power it would be ridden in the flat with the
  11. /// input speed.
  12. /// Using formula from http://www.sportsci.org/jour/9804/dps.html. Assuming v=s and neglecting rolling resistance
  13. /// The speed is calculated by solving k_aAs_1^3d = k_aAs_2^3d + giMs_2 for s_2
  14. /// </summary>
  15. /// <param name="speedFlat">Speed the bike would have in flat terrain</param>
  16. /// <param name="systemMass">Mass of bike + rider</param>
  17. /// <param name="gradient">gradient in vertical meters gained per meter travelled forward</param>
  18. /// <returns></returns>
  19. public static float SpeedAtGradientForSpeedAtFlat(float speedFlat, float systemMass, float gradient)
  20. {
  21. var g = -Physics.gravity.y;
  22. const float k = K_A * A * D;
  23. var b = g * gradient * systemMass;
  24. float result;
  25. if (gradient < -0.01f) // 1 percent
  26. {
  27. result = 2 * Mathf.Sqrt(-b / (3 * k)) *
  28. Mathf.Cos(
  29. Mathf.Acos(3 * Mathf.Sqrt(-3 * k / b) * k * speedFlat
  30. / (2 * b))
  31. / 3);
  32. }
  33. else
  34. {
  35. var sqrtTerm = Mathf.Sqrt(
  36. Mathf.Pow(b, 3f)
  37. /
  38. (27f * Mathf.Pow(k, 3f))
  39. +
  40. Mathf.Pow(speedFlat, 6f)
  41. /
  42. 4f
  43. );
  44. var secondTerm = Mathf.Pow(speedFlat, 3f) / 2f;
  45. result = Qbrt(sqrtTerm + secondTerm) + Qbrt(-sqrtTerm + secondTerm);
  46. }
  47. if (float.IsNaN(result))
  48. {
  49. Debug.LogWarning(
  50. $"BicyclePhysics: result is NaN for k = {k} and b = {b} (gradient = {gradient}, mass = {systemMass})");
  51. return speedFlat;
  52. }
  53. return result;
  54. }
  55. private static float Qbrt(float x)
  56. {
  57. return x < 0 ? -Mathf.Pow(-x, 1f / 3f) : Mathf.Pow(x, 1f / 3f);
  58. }
  59. }
  60. }