VibrationController.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. using System;
  2. using System.Threading.Tasks;
  3. using Sensors;
  4. using UnityEngine;
  5. namespace SicknessReduction.Haptic
  6. {
  7. public enum VibrationControllerMode
  8. {
  9. Continuous,
  10. AlternatingFixed,
  11. AlternatingCadenceBased
  12. }
  13. [RequireComponent(typeof(DynamicReductionSource))]
  14. public class VibrationController : EspController
  15. {
  16. private const string TOPIC_CYCLE = "Vibration/Control/Cycle";
  17. private const string TOPIC_CADENCE = "Vibration/Control/Cadence";
  18. private const int THRES_CADENCE_CHANGE = 4;
  19. public int cycle = 128; //vibro motor specs: 11000 ± 3,000rpm = 133.33 - 183.33 Hz
  20. public VibrationControllerMode mode;
  21. public int fixedCycleRpm;
  22. private bool initialCyclePublished;
  23. private int previousCadence = -1;
  24. private DynamicReductionSource reductionSource;
  25. private int currentCycle = 0;
  26. protected override void Start()
  27. {
  28. base.Start();
  29. reductionSource = GetComponent<DynamicReductionSource>();
  30. }
  31. protected override async void Update()
  32. {
  33. base.Update();
  34. // > 0 while cornering
  35. var correctedReductionValue = Mathf.Clamp(reductionSource.CurrentValue + reductionSource.Change, 0, 1);
  36. Debug.Log($"CorrectedReductionValue = {correctedReductionValue}");
  37. if (!DoUpdate || PreviousUpdateActive) return;
  38. if (correctedReductionValue > 0)
  39. {
  40. switch (mode)
  41. {
  42. case VibrationControllerMode.Continuous:
  43. await VibrateContinuous((int) (correctedReductionValue * cycle));
  44. break;
  45. case VibrationControllerMode.AlternatingFixed:
  46. await VibrateAlternatingFixed((int) (correctedReductionValue * cycle));
  47. break;
  48. case VibrationControllerMode.AlternatingCadenceBased:
  49. await VibrateAlternatingCadenceBased();
  50. break;
  51. default:
  52. throw new ArgumentOutOfRangeException();
  53. }
  54. }
  55. else
  56. {
  57. await StopVibrating();
  58. }
  59. PreviousUpdateActive = false;
  60. }
  61. private async Task StopVibrating()
  62. {
  63. Debug.Log("Stop Vibrating");
  64. await Broker.Publish(TOPIC_CYCLE, "0");
  65. currentCycle = 0;
  66. }
  67. private async Task VibrateAlternatingCadenceBased()
  68. {
  69. var cadence = BikeSensorData.Instance.PowermeterData?.InstantaneousCadence;
  70. if (!cadence.HasValue) return;
  71. var c = cadence.Value;
  72. PreviousUpdateActive = true; //flag to avoid concurrent updates
  73. //as soon as we have a cadence, we want the motors to vibrate
  74. if (!initialCyclePublished)
  75. {
  76. await Broker.Publish(TOPIC_CYCLE, $"{cycle}");
  77. initialCyclePublished = true;
  78. }
  79. //if the cadence changes to 0, we have to switch off vibration
  80. if (c == 0)
  81. {
  82. await Broker.Publish(TOPIC_CYCLE, "0");
  83. previousCadence = c;
  84. }
  85. //as soon as we have cadence again, we want to switch on vibration again, and then immediately set cadence again
  86. else if (previousCadence == 0)
  87. {
  88. await Broker.Publish(TOPIC_CYCLE, $"{cycle}");
  89. await PublishCadence(c);
  90. }
  91. //if we have never set cadence, or the change of cadence is high enough, we tell the ESP to change cadence
  92. else if (previousCadence < 0 || c - previousCadence > THRES_CADENCE_CHANGE)
  93. {
  94. await PublishCadence(c);
  95. }
  96. }
  97. private async Task VibrateAlternatingFixed(int cycleValue)
  98. {
  99. if (Math.Abs(cycleValue - currentCycle) > 0)
  100. {
  101. await Broker.Publish(TOPIC_CYCLE, $"{cycleValue}");
  102. await PublishCadence(fixedCycleRpm);
  103. }
  104. }
  105. private async Task VibrateContinuous(int cycleValue)
  106. {
  107. if (Math.Abs(cycleValue - currentCycle) > 0)
  108. {
  109. Debug.Log($"Sending Cycle {cycleValue}");
  110. await Broker.Publish(TOPIC_CYCLE, $"{cycleValue}");
  111. }
  112. }
  113. private async Task PublishCadence(int cadence)
  114. {
  115. Debug.Log($"Sending Cadence {cadence}");
  116. await Broker.Publish(TOPIC_CADENCE, $"{cadence}");
  117. previousCadence = cadence;
  118. }
  119. }
  120. }