123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- using System;
- using System.Threading.Tasks;
- using Sensors;
- using UnityEngine;
- namespace SicknessReduction.Haptic
- {
- public enum VibrationControllerMode
- {
- Continuous,
- AlternatingFixed,
- AlternatingCadenceBased
- }
- [RequireComponent(typeof(DynamicReductionSource))]
- public class VibrationController : EspController
- {
- private const string TOPIC_CYCLE = "Vibration/Control/Cycle";
- private const string TOPIC_CADENCE = "Vibration/Control/Cadence";
- private const int THRES_CADENCE_CHANGE = 4;
- public int minCycle = 100;
- public int maxCycle = 178; //vibro motor specs: 11000 ± 3,000rpm = 133.33 - 183.33 Hz
- public float reductionValueThreshold = 0.05f;
- public VibrationControllerMode mode;
- public int fixedCycleRpm;
- private bool initialCyclePublished;
- private int previousCadence = -1;
- private DynamicReductionSource reductionSource;
- private int currentCycle = 0;
- protected override void Start()
- {
- base.Start();
- reductionSource = GetComponent<DynamicReductionSource>();
- }
- protected override async void Update()
- {
- base.Update();
- // > 0 while cornering
- var reductionValue = reductionSource.CurrentValue;
- var cycleValue = reductionValue < reductionValueThreshold
- ? 0
- : (int) Mathf.Lerp(minCycle, maxCycle, reductionValue);
- if (!DoUpdate || PreviousUpdateActive) return;
- if (reductionValue > 0)
- {
- switch (mode)
- {
- case VibrationControllerMode.Continuous:
- await VibrateContinuous(cycleValue);
- break;
- case VibrationControllerMode.AlternatingFixed:
- await VibrateAlternatingFixed(cycleValue);
- break;
- case VibrationControllerMode.AlternatingCadenceBased:
- await VibrateAlternatingCadenceBased();
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
- }
- else if (currentCycle != 0)
- {
- await StopVibrating();
- }
- PreviousUpdateActive = false;
- }
- private async Task StopVibrating()
- {
- Debug.Log("Stop Vibrating");
- await Broker.Publish(TOPIC_CYCLE, "0");
- currentCycle = 0;
- }
- private async Task VibrateAlternatingCadenceBased()
- {
- var cadence = BikeSensorData.Instance.PowermeterData?.InstantaneousCadence;
- if (!cadence.HasValue) return;
- var c = cadence.Value;
- PreviousUpdateActive = true; //flag to avoid concurrent updates
- //as soon as we have a cadence, we want the motors to vibrate
- if (!initialCyclePublished)
- {
- await Broker.Publish(TOPIC_CYCLE, $"{maxCycle}");
- initialCyclePublished = true;
- }
- //if the cadence changes to 0, we have to switch off vibration
- if (c == 0)
- {
- await Broker.Publish(TOPIC_CYCLE, "0");
- previousCadence = c;
- }
- //as soon as we have cadence again, we want to switch on vibration again, and then immediately set cadence again
- else if (previousCadence == 0)
- {
- await Broker.Publish(TOPIC_CYCLE, $"{maxCycle}");
- await PublishCadence(c);
- }
- //if we have never set cadence, or the change of cadence is high enough, we tell the ESP to change cadence
- else if (previousCadence < 0 || c - previousCadence > THRES_CADENCE_CHANGE)
- {
- await PublishCadence(c);
- }
- }
- private async Task VibrateAlternatingFixed(int cycleValue)
- {
- if (Math.Abs(cycleValue - currentCycle) > 0)
- {
- await Broker.Publish(TOPIC_CYCLE, $"{cycleValue}");
- await PublishCadence(fixedCycleRpm);
- }
- }
- private async Task VibrateContinuous(int cycleValue)
- {
- if (Math.Abs(cycleValue - currentCycle) > 0)
- {
- Debug.Log($"Sending Cycle {cycleValue}");
- await Broker.Publish(TOPIC_CYCLE, $"{cycleValue}");
- }
- }
- private async Task PublishCadence(int cadence)
- {
- Debug.Log($"Sending Cadence {cadence}");
- await Broker.Publish(TOPIC_CADENCE, $"{cadence}");
- previousCadence = cadence;
- }
- }
- }
|