Browse Source

Refactoring + BikeSensorController

wwdmbvbb 3 years ago
parent
commit
08a4b0449b
35 changed files with 467 additions and 233 deletions
  1. 1 0
      .idea/.idea.VR Cycling/.idea/indexLayout.xml
  2. 4 4
      Assembly-CSharp-Editor.csproj
  3. 14 12
      Assembly-CSharp.csproj
  4. 1 8
      Assets/Scripts/BicyleController/BicycleController.cs
  5. 75 0
      Assets/Scripts/BicyleController/SensorBikeController.cs
  6. 3 0
      Assets/Scripts/BicyleController/SensorBikeController.cs.meta
  7. 3 0
      Assets/Scripts/Display.meta
  8. 21 15
      Assets/Scripts/Display/BikeDataDisplay.cs
  9. 0 0
      Assets/Scripts/Display/BikeDataDisplay.cs.meta
  10. 64 0
      Assets/Scripts/Display/DebugDisplay.cs
  11. 3 0
      Assets/Scripts/Display/DebugDisplay.cs.meta
  12. 0 28
      Assets/Scripts/HrDisplay.cs
  13. 0 3
      Assets/Scripts/HrDisplay.cs.meta
  14. 0 44
      Assets/Scripts/Polar/PolarListener.cs
  15. 0 3
      Assets/Scripts/Polar/PolarListener.cs.meta
  16. 3 0
      Assets/Scripts/Sensors.meta
  17. 0 0
      Assets/Scripts/Sensors/ANT+.meta
  18. 18 21
      Assets/Scripts/Sensors/ANT+/HrReceiver.cs
  19. 0 0
      Assets/Scripts/Sensors/ANT+/HrReceiver.cs.meta
  20. 26 36
      Assets/Scripts/Sensors/ANT+/PowerMeterReceiver.cs
  21. 0 0
      Assets/Scripts/Sensors/ANT+/PowerMeterReceiver.cs.meta
  22. 49 44
      Assets/Scripts/Sensors/ANT+/SpeedSensorReceiver.cs
  23. 0 0
      Assets/Scripts/Sensors/ANT+/SpeedSensorReceiver.cs.meta
  24. 95 0
      Assets/Scripts/Sensors/BikeSensorData.cs
  25. 3 0
      Assets/Scripts/Sensors/BikeSensorData.cs.meta
  26. 0 0
      Assets/Scripts/Sensors/Polar.meta
  27. 9 12
      Assets/Scripts/Sensors/Polar/PolarAccData.cs
  28. 0 0
      Assets/Scripts/Sensors/Polar/PolarAccData.cs.meta
  29. 61 0
      Assets/Scripts/Sensors/Polar/PolarReceiver.cs
  30. 11 0
      Assets/Scripts/Sensors/Polar/PolarReceiver.cs.meta
  31. 1 1
      Assets/Scripts/Sensors/Polar/UdpConnection.cs
  32. 0 0
      Assets/Scripts/Sensors/Polar/UdpConnection.cs.meta
  33. 2 2
      ProjectSettings/ProjectVersion.txt
  34. BIN
      obj/Debug/Assembly-CSharp.csprojAssemblyReference.cache
  35. BIN
      obj/Debug/SteamVR_Windows_EditorHelper.csprojAssemblyReference.cache

+ 1 - 0
.idea/.idea.VR Cycling/.idea/indexLayout.xml

@@ -31,6 +31,7 @@
       <Path>Integrations</Path>
       <Path>Library</Path>
       <Path>Logs</Path>
+      <Path>Temp</Path>
       <Path>obj</Path>
     </explicitExcludes>
   </component>

+ 4 - 4
Assembly-CSharp-Editor.csproj

@@ -698,6 +698,10 @@
       <Project>{2FA35993-2A22-653F-771D-EE2364CA1FAB}</Project>
       <Name>Assembly-CSharp</Name>
     </ProjectReference>
+    <ProjectReference Include="SteamVR_Actions.csproj">
+      <Project>{67161614-2DB4-7745-C3F6-F9DD455AD582}</Project>
+      <Name>SteamVR_Actions</Name>
+    </ProjectReference>
     <ProjectReference Include="SteamVR_Input_Editor.csproj">
       <Project>{1140961C-B987-84EB-8395-EA3F31446727}</Project>
       <Name>SteamVR_Input_Editor</Name>
@@ -714,10 +718,6 @@
       <Project>{CDC4B8D5-119D-91FE-D16D-283F6632AFF5}</Project>
       <Name>SteamVR_Windows_EditorHelper</Name>
     </ProjectReference>
-    <ProjectReference Include="SteamVR_Actions.csproj">
-      <Project>{67161614-2DB4-7745-C3F6-F9DD455AD582}</Project>
-      <Name>SteamVR_Actions</Name>
-    </ProjectReference>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+ 14 - 12
Assembly-CSharp.csproj

@@ -251,21 +251,23 @@
      <Compile Include="Assets\AdvancedAnt\Scripts\SpeedCadenceDisplay.cs" />
      <Compile Include="Assets\AdvancedAnt\Scripts\SpeedDisplay.cs" />
      <Compile Include="Assets\IpAddressDisplay.cs" />
-     <Compile Include="Assets\Scripts\ANT+\HrReceiver.cs" />
-     <Compile Include="Assets\Scripts\ANT+\PowerMeterReceiver.cs" />
-     <Compile Include="Assets\Scripts\ANT+\SpeedSensorReceiver.cs" />
-     <Compile Include="Assets\Scripts\BicyleController\AntSetup.cs" />
      <Compile Include="Assets\Scripts\BicyleController\BicycleController - Copy.cs" />
      <Compile Include="Assets\Scripts\BicyleController\BicycleController.cs" />
      <Compile Include="Assets\Scripts\BicyleController\KeyboardBikeController.cs" />
+     <Compile Include="Assets\Scripts\BicyleController\SensorBikeController.cs" />
      <Compile Include="Assets\Scripts\BicyleController\WheelConfig.cs" />
-     <Compile Include="Assets\Scripts\HrDisplay.cs" />
-     <Compile Include="Assets\Scripts\Polar\PolarAccData.cs" />
-     <Compile Include="Assets\Scripts\Polar\PolarListener.cs" />
-     <Compile Include="Assets\Scripts\Polar\UdpConnection.cs" />
+     <Compile Include="Assets\Scripts\Display\BikeDataDisplay.cs" />
+     <Compile Include="Assets\Scripts\Display\DebugDisplay.cs" />
      <Compile Include="Assets\Scripts\ResetPlayerPosition\AttachBikeToHead.cs" />
      <Compile Include="Assets\Scripts\ResetPlayerPosition\ResetPositionViaTransforms.cs" />
      <Compile Include="Assets\Scripts\ResetPlayerPosition\ResetPositionViaValveSDk.cs" />
+     <Compile Include="Assets\Scripts\Sensors\ANT+\HrReceiver.cs" />
+     <Compile Include="Assets\Scripts\Sensors\ANT+\PowerMeterReceiver.cs" />
+     <Compile Include="Assets\Scripts\Sensors\ANT+\SpeedSensorReceiver.cs" />
+     <Compile Include="Assets\Scripts\Sensors\BikeSensorData.cs" />
+     <Compile Include="Assets\Scripts\Sensors\Polar\PolarAccData.cs" />
+     <Compile Include="Assets\Scripts\Sensors\Polar\PolarReceiver.cs" />
+     <Compile Include="Assets\Scripts\Sensors\Polar\UdpConnection.cs" />
      <Compile Include="Assets\Scripts\SimpleCameraController.cs" />
      <Compile Include="Assets\Scripts\WCTest\SimpleBikeController.cs" />
      <Compile Include="Assets\Scripts\WCTest\SphereBikeController.cs" />
@@ -905,6 +907,10 @@
  </Reference>
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="SteamVR_Actions.csproj">
+      <Project>{67161614-2DB4-7745-C3F6-F9DD455AD582}</Project>
+      <Name>SteamVR_Actions</Name>
+    </ProjectReference>
     <ProjectReference Include="SteamVR_Input_Editor.csproj">
       <Project>{1140961C-B987-84EB-8395-EA3F31446727}</Project>
       <Name>SteamVR_Input_Editor</Name>
@@ -921,10 +927,6 @@
       <Project>{CDC4B8D5-119D-91FE-D16D-283F6632AFF5}</Project>
       <Name>SteamVR_Windows_EditorHelper</Name>
     </ProjectReference>
-    <ProjectReference Include="SteamVR_Actions.csproj">
-      <Project>{67161614-2DB4-7745-C3F6-F9DD455AD582}</Project>
-      <Name>SteamVR_Actions</Name>
-    </ProjectReference>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+ 1 - 8
Assets/Scripts/BicyleController/BicycleController.cs

@@ -46,14 +46,7 @@ public class BicycleController : MonoBehaviour
 
     private float calculatedWheelSpeed;
     private float initialWheelColliderY;
-
-
-    private void OnGUI()
-    {
-        GUI.TextField(new Rect(300, 10, 700, 40),
-            $"Motor Torque = {CurrentMotorTorque}; Brake Torque = {CurrentBrakeTorque}; Leaning Angle = {CurrentLeaningAngle}; Steering Angle = {CurrentSteerAngle}");
-
-    }
+    
 
     // Start is called before the first frame update
     void Start()

+ 75 - 0
Assets/Scripts/BicyleController/SensorBikeController.cs

@@ -0,0 +1,75 @@
+using System;
+using UnityEngine;
+using UnityEngine.Serialization;
+
+
+public class SensorBikeController : MonoBehaviour
+{
+    public float maxSpeed = 40f;
+    public float maxMotorTorque = 1000;
+    public float leaningAngleMultiplier = 0.1f;
+
+    public SpeedSensorConfig speedSensorConfig;
+    public PolarSensorConfig polarSensorConfig;
+
+    private BicycleController bicycleController;
+    private BikeSensorData sensorData;
+
+    private void Start()
+    {
+        bicycleController = GetComponent<BicycleController>();
+        sensorData = BikeSensorData.Instance;
+        sensorData.StartListening(polarSensorConfig: polarSensorConfig, speedSensorConfig: speedSensorConfig);
+    }
+
+    private void Update()
+    {
+        var speedData = sensorData.SpeedData;
+        var polarData = sensorData.PolarData;
+
+        if (speedData != null)
+        {
+            SetSpeed(speedData.Value);
+        }
+
+        if (polarData != null)
+        {
+            SetLeaningAngle(polarData.Value);
+        }
+    }
+
+    private void OnDestroy()
+    {
+        sensorData.Dispose();
+    }
+
+    private void SetLeaningAngle(PolarSensorData polarData)
+    {
+        bicycleController.CurrentLeaningAngle = polarData.Acc.x * leaningAngleMultiplier;
+    }
+
+    private void SetSpeed(SpeedSensorData speedData)
+    {
+        var currentSpeed = bicycleController.rigidBody.velocity.magnitude;
+        var speedDif = speedData.Speed - currentSpeed;
+        var ratio = speedDif / maxSpeed;
+        var torque = maxMotorTorque * ratio;
+        if (speedDif >= .1f) // 0.36 km/h
+        {
+            Debug.Log($"SpeedDif = {speedDif} -> applying Torque {torque} (Ratio: {ratio})");
+            bicycleController.CurrentBrakeTorque = 0;
+            bicycleController.CurrentMotorTorque = torque;
+        }
+        else if (speedDif <= -.1f)
+        {
+            Debug.Log($"SpeedDif = {speedDif} -> applying brake Torque {torque} (Ratio: {ratio})");
+            bicycleController.CurrentMotorTorque = 0;
+            bicycleController.CurrentBrakeTorque = -torque;
+        }
+        else
+        {
+            bicycleController.CurrentMotorTorque = 0;
+            bicycleController.CurrentBrakeTorque = 0;
+        }
+    }
+}

+ 3 - 0
Assets/Scripts/BicyleController/SensorBikeController.cs.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: f4cd757b8ab544dd8cf69b27aea0055d
+timeCreated: 1606374929

+ 3 - 0
Assets/Scripts/Display.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 73641783d21d4c85b64426dadb65abb2
+timeCreated: 1606381884

+ 21 - 15
Assets/Scripts/BicyleController/AntSetup.cs → Assets/Scripts/Display/BikeDataDisplay.cs

@@ -1,10 +1,9 @@
 using TMPro;
 using UnityEngine;
 
-public class AntSetup : MonoBehaviour
+public class BikeDataDisplay : MonoBehaviour
 {
-    [Header("Speed")] public int speedSensorId = 0;
-    public float wheelCircumference = 2.096f;
+    [Header("Speed")] 
     public TextMeshProUGUI speedDisplay;
     
     [Header("Powermeter")] 
@@ -13,28 +12,30 @@ public class AntSetup : MonoBehaviour
     public TextMeshProUGUI cadenceDisplay;
     public TextMeshProUGUI torqueDisplay;
 
-    private SpeedSensorReceiver speedSensorReceiver;
-    private PowerMeterReceiver powerMeterReceiver;
+    [Header("Heart Rate")] public int hrAntId = 0;
+    public TextMeshProUGUI heartRateDisplay;
+    
 
     private bool speedDisplayAvailable;
     private bool powerDisplayAvailable;
     private bool cadenceDisplayAvailable;
     private bool torqueDisplayAvailable;
+    private bool heartRateDisplayAvailable;
 
-    private BicycleController bicycleController;
+    private BikeSensorData sensorData;
 
     // Start is called before the first frame update
     void Start()
     {
-        bicycleController = GetComponent<BicycleController>();
+        sensorData = BikeSensorData.Instance;
+        //powermeter and ANT hr only for displaying for now TODO: move to controller if used for controlling
+        sensorData.StartListening(powermeterId: powerMeterId, hrAntId: hrAntId);
+
         speedDisplayAvailable = speedDisplay != null;
         powerDisplayAvailable = powerDisplay != null;
         torqueDisplayAvailable = torqueDisplay != null;
         cadenceDisplayAvailable = cadenceDisplay != null;
-        speedSensorReceiver = new SpeedSensorReceiver(speedSensorId, wheelCircumference);
-        powerMeterReceiver = new PowerMeterReceiver(powerMeterId);
-        speedSensorReceiver.StartScan();
-        powerMeterReceiver.StartScan();
+        heartRateDisplayAvailable = heartRateDisplay != null;
     }
 
     // Update is called once per frame
@@ -45,22 +46,27 @@ public class AntSetup : MonoBehaviour
         //bicycleController.SetTorque(powerMeterReceiver?.CrankTorque ?? 0); //TODO crank to wheel torque;
         if (speedDisplayAvailable)
         {
-            speedDisplay.text = $"{(speedSensorReceiver?.SpeedKmh ?? 0f):n2} km/h";
+            speedDisplay.text = $"{(sensorData.SpeedData?.SpeedKmh ?? 0f):n2} km/h";
         }
 
         if (powerDisplayAvailable)
         {
-            powerDisplay.text = $"{(powerMeterReceiver?.InstantaneousPower ?? 0f):0} W";
+            powerDisplay.text = $"{(sensorData.PowermeterData?.InstantaneousPower ?? 0f):0} W";
         }
 
         if (cadenceDisplayAvailable)
         {
-            cadenceDisplay.text = $"{(powerMeterReceiver?.InstantaneousCadence ?? 0f):0} rpm";
+            cadenceDisplay.text = $"{(sensorData.PowermeterData?.InstantaneousCadence ?? 0f):0} rpm";
         }
 
         if (torqueDisplayAvailable)
         {
-            torqueDisplay.text = $"{(powerMeterReceiver?.CrankTorque ?? 0f):F2} Nm";
+            torqueDisplay.text = $"{(sensorData.PowermeterData?.CrankTorque ?? 0f):F2} Nm";
+        }
+
+        if (heartRateDisplayAvailable)
+        {
+            heartRateDisplay.text = $"{(sensorData.HrData?.HeartRate ?? 0):0} bpm";
         }
     }
 }

+ 0 - 0
Assets/Scripts/BicyleController/AntSetup.cs.meta → Assets/Scripts/Display/BikeDataDisplay.cs.meta


+ 64 - 0
Assets/Scripts/Display/DebugDisplay.cs

@@ -0,0 +1,64 @@
+using System;
+using System.Net;
+using System.Text;
+using UnityEngine;
+
+
+public class DebugDisplay : MonoBehaviour
+{
+    public BicycleController bicycleController;
+    private BikeSensorData sensorData = BikeSensorData.Instance;
+
+    private string ip;
+    private string text;
+
+
+    private void Start()
+    {
+        ip = GetIp();
+    }
+
+    private void Update()
+    {
+        var sb = new StringBuilder();
+        sb.Append(
+            $"MotorTorque: {bicycleController.CurrentMotorTorque}; BrakeTorque: {bicycleController.CurrentBrakeTorque}, Steer: {bicycleController.CurrentSteerAngle}; Lean: {bicycleController.CurrentLeaningAngle}\n");
+        sb.Append("-----Sensors------\n");
+        sb.Append(
+            $"Speed: {(sensorData.SpeedData?.Speed ?? 0f):n4} m/s; Polar Acc ({(sensorData.PolarData?.Acc.x ?? 0f):n4}; {(sensorData.PolarData?.Acc.y ?? 0f):n4}; {(sensorData.PolarData?.Acc.z ?? 0f):n4}) ");
+        sb.Append("\n\n");
+        sb.Append($"IP: {ip}\n");
+        sb.Append("----BicycleController-----\n");
+        sb.Append($"Actual Speed {(bicycleController.rigidBody.velocity.magnitude * 3.6):n2} km/h");
+        text = sb.ToString();
+    }
+
+    private void OnGUI()
+    {
+        var padding = 10;
+        var width = 360;
+        var height = 120;
+        var x = Screen.width - width - padding;
+        var y = Screen.height - height - padding;
+
+        GUI.TextField(new Rect(x, y, width, height), text);
+    }
+
+    private String GetIp()
+    {
+        string usedIp = null;
+
+        foreach (var ip in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
+        {
+            if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
+            {
+                if (usedIp == null || ip.ToString().StartsWith("192.168.1."))
+                {
+                    usedIp = ip.ToString();
+                }
+            }
+        }
+
+        return usedIp;
+    }
+}

+ 3 - 0
Assets/Scripts/Display/DebugDisplay.cs.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 5bf6ef59c1034b1f8b9c5c713fb4c1b1
+timeCreated: 1606381894

+ 0 - 28
Assets/Scripts/HrDisplay.cs

@@ -1,28 +0,0 @@
-using System;
-using TMPro;
-using UnityEngine;
-
-
-public class HrDisplay : MonoBehaviour{
-    public int hrSensorId;
-    public TextMeshProUGUI heartRateDisplay;
-
-    private HrReceiver hrReceiver;
-
-    private bool heartRateDisplayAvailable;
-
-    private void Start()
-    {
-        hrReceiver = new HrReceiver(hrSensorId);
-        hrReceiver.StartScan();
-        heartRateDisplayAvailable = heartRateDisplay != null;
-    }
-
-    private void Update()
-    {
-        if (heartRateDisplayAvailable)
-        {
-            heartRateDisplay.text = $"{(hrReceiver?.HeartRate ?? 0):0} bpm";
-        }
-    }
-}

+ 0 - 3
Assets/Scripts/HrDisplay.cs.meta

@@ -1,3 +0,0 @@
-fileFormatVersion: 2
-guid: 3e7a4eba0218476ea327535b923bf640
-timeCreated: 1605819437

+ 0 - 44
Assets/Scripts/Polar/PolarListener.cs

@@ -1,44 +0,0 @@
-using System;
-using UnityEngine;
-
-
-public class PolarListener : MonoBehaviour
-{
-    private UdpConnection connection;
-    public int port = 9099;
-    public String ipAddress = "0.0.0.0";
-    private float rotation = 0f;
-    public float divisionValue = 60f;
-
-    private BicycleController bicycleController;
-    private void Start()
-    {
-        bicycleController = GetComponent<BicycleController>();
-        connection = new UdpConnection(ipAddress, port, OnAccData);
-        connection.Listen();
-    }
-
-    private void OnGUI()
-    {
-        GUI.TextField(new Rect(10,10, 100, 20), $"{rotation}");
-    }
-
-    private void OnAccData(AccData data)
-    {
-        //Debug.Log(data.Timestamp);
-        rotation = data.Values[0].y / divisionValue;
-        Debug.Log($"Rotate {data.Values[0].y} degrees");
-        //bicycleController.SetSteeringAngle(-rotation);
-        //transform.RotateAround(transform.position, Vector3.forward, data.Values[0].y);
-    }
-
-    /*private void Update()
-    {
-        transform.rotation = Quaternion.Euler(0,90,rotation);
-    }*/
-
-    private void OnDestroy()
-    {
-        connection.StopListening();
-    }
-}

+ 0 - 3
Assets/Scripts/Polar/PolarListener.cs.meta

@@ -1,3 +0,0 @@
-fileFormatVersion: 2
-guid: 7047fa022a2846339e78755e09e91fda
-timeCreated: 1605819762

+ 3 - 0
Assets/Scripts/Sensors.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 45b7bad8be4f433b973364720122048b
+timeCreated: 1606375162

+ 0 - 0
Assets/Scripts/ANT+.meta → Assets/Scripts/Sensors/ANT+.meta


+ 18 - 21
Assets/Scripts/ANT+/HrReceiver.cs → Assets/Scripts/Sensors/ANT+/HrReceiver.cs

@@ -3,38 +3,35 @@ using System.Collections.Generic;
 using ANT_Managed_Library;
 using System;
 
-public class HrReceiver
+public struct HRSensorData
 {
-    private int deviceID = 0; //set this to connect to a specific device ID
-    private bool connected = false; //will be set to true once connected
-    private List<AntDevice> scanResult;
-
-    private float heartRate; // the computed HR count  in BPM
+    public float HeartRate;
+}
 
+public class HrReceiver
+{
     private AntChannel backgroundScanChannel;
     private AntChannel deviceChannel;
+    private HRSensorData sensorData;
 
-    public int DeviceID => deviceID;
-
-    public bool Connected => connected;
-
-    public List<AntDevice> ScanResult => scanResult;
-
-    public float HeartRate => heartRate;
+    public int DeviceID { get; } = 0;
+    public bool Connected { get; private set; } = false;
+    public List<AntDevice> ScanResult { get; private set; }
+    public HRSensorData SensorData => sensorData;
 
 
     public HrReceiver()
     {
     }
 
-    public HrReceiver(int deviceID) => this.deviceID = deviceID;
+    public HrReceiver(int deviceID) => this.DeviceID = deviceID;
 
     //Start a background Scan to find the device
     public void StartScan()
     {
         Debug.Log("Looking for ANT + HeartRate sensor");
         AntManager.Instance.Init();
-        scanResult = new List<AntDevice>();
+        ScanResult = new List<AntDevice>();
         backgroundScanChannel = AntManager.Instance.OpenBackgroundScanChannel(0);
         backgroundScanChannel.onReceiveData += ReceivedBackgroundScanData;
     }
@@ -49,7 +46,7 @@ public class HrReceiver
             {
                 int deviceNumber = (data[10]) | data[11] << 8;
                 byte transType = data[13];
-                foreach (AntDevice d in scanResult)
+                foreach (AntDevice d in ScanResult)
                 {
                     if (d.deviceNumber == deviceNumber && d.transType == transType) //device already found
                         return;
@@ -62,8 +59,8 @@ public class HrReceiver
                 foundDevice.period = 8070;
                 foundDevice.radiofreq = 57;
                 foundDevice.name = "heartrate(" + foundDevice.deviceNumber + ")";
-                scanResult.Add(foundDevice);
-                if (deviceNumber == deviceID)
+                ScanResult.Add(foundDevice);
+                if (deviceNumber == DeviceID)
                 {
                     Debug.Log($"Desired HR Sensor with id {deviceNumber} found!");
                     ConnectToDevice(foundDevice);
@@ -85,7 +82,7 @@ public class HrReceiver
         deviceChannel = AntManager.Instance.OpenChannel(ANT_ReferenceLibrary.ChannelType.BASE_Slave_Receive_0x00,
             channelID, (ushort) device.deviceNumber, device.deviceType, device.transType, (byte) device.radiofreq,
             (ushort) device.period, false);
-        connected = true;
+        Connected = true;
         deviceChannel.onReceiveData += Data;
         deviceChannel.onChannelResponse += ChannelResponse;
 
@@ -94,9 +91,9 @@ public class HrReceiver
 
 
     //Deal with the received Data
-    public void Data(Byte[] data)
+    private void Data(Byte[] data)
     {
-        heartRate = (data[7]);
+        sensorData.HeartRate = (data[7]);
     }
 
 

+ 0 - 0
Assets/Scripts/ANT+/HRReceiver.cs.meta → Assets/Scripts/Sensors/ANT+/HrReceiver.cs.meta


+ 26 - 36
Assets/Scripts/ANT+/PowerMeterReceiver.cs → Assets/Scripts/Sensors/ANT+/PowerMeterReceiver.cs

@@ -13,47 +13,39 @@ other channel periods that may be present
 in the vicinity. During this overlap, channel
 collisions may occur as the radio can only
 service channel at a time. 
+*/
 
-    */
-public class PowerMeterReceiver
+public struct PowermeterSensorData
 {
-    private int deviceID = 0; //set this to connect to a specific device ID
-    private bool connected = false; //will be set to true once connected
-    private List<AntDevice> scanResult;
-
-    private int instantaneousPower; // the instantaneous power in watt
-    private int instantaneousCadence; // crank cadence in RPM if available ( 255 indicates invalid)
-    private float crankTorque;
+    public int InstantaneousPower; // the instantaneous power in watt
+    public int InstantaneousCadence; // crank cadence in RPM if available ( 255 indicates invalid)
+    public float CrankTorque;
+}
 
+public class PowerMeterReceiver
+{
     private AntChannel backgroundScanChannel;
     private AntChannel deviceChannel;
-
-    public int DeviceID => deviceID;
-
-    public bool Connected => connected;
-
-    public List<AntDevice> ScanResult => scanResult;
-
-    public int InstantaneousPower => instantaneousPower;
-
-    public int InstantaneousCadence => instantaneousCadence;
-
-    public float CrankTorque => crankTorque;
-
     private byte[] pageToSend;
+    private PowermeterSensorData sensorData;
+
+    public int DeviceID { get; } = 0;
+    public bool Connected { get; private set; } = false;
+    public List<AntDevice> ScanResult { get; private set; }
+    public PowermeterSensorData SensorData => sensorData;
 
     public PowerMeterReceiver()
     {
     }
 
-    public PowerMeterReceiver(int deviceID) => this.deviceID = deviceID;
+    public PowerMeterReceiver(int deviceID) => DeviceID = deviceID;
 
     public void StartScan()
     {
         Debug.Log("Looking for ANT + power meter sensor");
 
         AntManager.Instance.Init();
-        scanResult = new List<AntDevice>();
+        ScanResult = new List<AntDevice>();
         backgroundScanChannel = AntManager.Instance.OpenBackgroundScanChannel(0);
         backgroundScanChannel.onReceiveData += ReceivedBackgroundScanData;
     }
@@ -69,7 +61,7 @@ public class PowerMeterReceiver
             {
                 int deviceNumber = (data[10]) | data[11] << 8;
                 byte transType = data[13];
-                foreach (AntDevice d in scanResult)
+                foreach (AntDevice d in ScanResult)
                 {
                     if (d.deviceNumber == deviceNumber && d.transType == transType) //device already found
                         return;
@@ -82,8 +74,8 @@ public class PowerMeterReceiver
                 foundDevice.period = 8182;
                 foundDevice.radiofreq = 57;
                 foundDevice.name = "Powermeter(" + foundDevice.deviceNumber + ")";
-                scanResult.Add(foundDevice);
-                if (deviceNumber == deviceID)
+                ScanResult.Add(foundDevice);
+                if (deviceNumber == DeviceID)
                 {
                     Debug.Log($"Desired Power Sensor with id {deviceNumber} found!");
                     ConnectToDevice(foundDevice);
@@ -105,7 +97,7 @@ public class PowerMeterReceiver
         deviceChannel = AntManager.Instance.OpenChannel(ANT_ReferenceLibrary.ChannelType.BASE_Slave_Receive_0x00,
             channelID, (ushort) device.deviceNumber, device.deviceType, device.transType, (byte) device.radiofreq,
             (ushort) device.period, false);
-        connected = true;
+        Connected = true;
         deviceChannel.onReceiveData += Data;
         deviceChannel.onChannelResponse += ChannelResponse;
 
@@ -133,13 +125,13 @@ public class PowerMeterReceiver
 
             if (sameEventCounter[0x10] > 3)
             {
-                instantaneousPower = 0;
-                instantaneousCadence = 0;
+                sensorData.InstantaneousPower = 0;
+                sensorData.InstantaneousCadence = 0;
             }
             else
             {
-                instantaneousPower = data[6] | data[7] << 8;
-                instantaneousCadence = data[3];
+                sensorData.InstantaneousPower = data[6] | data[7] << 8;
+                sensorData.InstantaneousCadence = data[3];
             }
         }
 
@@ -155,7 +147,7 @@ public class PowerMeterReceiver
 
             if (sameEventCounter[0x12] > 3)
             {
-                crankTorque = 0;
+                sensorData.CrankTorque = 0;
             }
             else
             {
@@ -163,10 +155,8 @@ public class PowerMeterReceiver
                 float divisor = (32 * (updateEventCount[0x12] - previousTorqueEventCount));
                 if (divisor > 0)
                 {
-                    crankTorque =  (accumulatedTorque - previousAccumulatedTorqueValue) / divisor;
+                    sensorData.CrankTorque = (accumulatedTorque - previousAccumulatedTorqueValue) / divisor;
                 }
-                
-                Debug.Log($"instantaneousCrankTorque = {crankTorque}");
                 previousAccumulatedTorqueValue = accumulatedTorque;
                 previousTorqueEventCount = updateEventCount[0x12];
             }

+ 0 - 0
Assets/Scripts/ANT+/PowerMeterReceiver.cs.meta → Assets/Scripts/Sensors/ANT+/PowerMeterReceiver.cs.meta


+ 49 - 44
Assets/Scripts/ANT+/SpeedSensorReceiver.cs → Assets/Scripts/Sensors/ANT+/SpeedSensorReceiver.cs

@@ -3,56 +3,61 @@ using System.Collections;
 using System.Collections.Generic;
 using ANT_Managed_Library;
 using System;
+using UnityEngine.Serialization;
 
-public class SpeedSensorReceiver
+[System.Serializable]
+public struct SpeedSensorConfig
 {
-    private int deviceId = 0; //set this to connect to a specific device ID
-    private bool connected = false; //will be set to true once connected
-    private float wheelCircumference = 2.096f; //in meters, 700*23C, set this to your wheels size
-    private List<AntDevice> scanResult;
+    public int deviceId;
+    public float wheelCircumference;
 
-    private float speed; // The speed in m/s
-    private float distance; //the distance in meters
+    public SpeedSensorConfig(int deviceId = 0, float wheelCircumference = 2.096f)
+    {
+        this.deviceId = deviceId;
+        this.wheelCircumference = wheelCircumference;
+    }
+}
 
+public struct SpeedSensorData
+{
+    public float Speed;
+    public float SpeedKmh => Speed * 3.6f;
+    public float Distance;
+}
 
+public class SpeedSensorReceiver
+{
     private AntChannel backgroundScanChannel;
     private AntChannel deviceChannel;
 
-    private int stopRevCounter_speed = 0;
-    private int prev_measTime_speed = 0;
-    private int prev_revCount_speed = 0;
+    private int stopRevCounterSpeed = 0;
+    private int prevMeasTimeSpeed = 0;
+    private int prevRevCountSpeed = 0;
     private int revCountZero = 0;
+    private SpeedSensorData sensorData;
 
-    public int DeviceId => deviceId;
-
-    public bool Connected => connected;
-
-    public List<AntDevice> ScanResult => scanResult;
-
-    public float Speed => speed;
-
-    public float SpeedKmh => speed * 3.6f;
-
-    public float Distance => distance;
+    public SpeedSensorConfig Config { get; }
+    public bool Connected { get; private set; }
+    public List<AntDevice> ScanResult { get; private set; }
+    public SpeedSensorData SensorData => sensorData;
 
     public SpeedSensorReceiver()
     {
     }
 
-    public SpeedSensorReceiver(int deviceId) => this.deviceId = deviceId;
+    public SpeedSensorReceiver(SpeedSensorConfig config) => this.Config = config;
 
-    public SpeedSensorReceiver(int deviceId, float wheelCircumference)
-    {
-        this.deviceId = deviceId;
-        this.wheelCircumference = wheelCircumference;
-    }
+    public SpeedSensorReceiver(int deviceId) => Config = new SpeedSensorConfig(deviceId);
+
+    public SpeedSensorReceiver(int deviceId, float wheelCircumference) =>
+        Config = new SpeedSensorConfig(deviceId, wheelCircumference);
 
     //Start a background Scan to find the device
     public void StartScan()
     {
         Debug.Log("Looking for ANT + Speed sensor");
         AntManager.Instance.Init();
-        scanResult = new List<AntDevice>();
+        ScanResult = new List<AntDevice>();
         backgroundScanChannel = AntManager.Instance.OpenBackgroundScanChannel(0);
         backgroundScanChannel.onReceiveData += ReceivedBackgroundScanData;
     }
@@ -68,7 +73,7 @@ public class SpeedSensorReceiver
             {
                 int deviceNumber = (data[10]) | data[11] << 8;
                 byte transType = data[13];
-                foreach (AntDevice d in scanResult)
+                foreach (AntDevice d in ScanResult)
                 {
                     if (d.deviceNumber == deviceNumber && d.transType == transType) //device already found
                         return;
@@ -82,8 +87,8 @@ public class SpeedSensorReceiver
                 foundDevice.period = 8118;
                 foundDevice.radiofreq = 57;
                 foundDevice.name = "BikeSpeed(" + foundDevice.deviceNumber + ")";
-                scanResult.Add(foundDevice);
-                if (deviceNumber == deviceId)
+                ScanResult.Add(foundDevice);
+                if (deviceNumber == Config.deviceId)
                 {
                     Debug.Log($"Desired Speed Sensor with id {deviceNumber} found!");
                     ConnectToDevice(foundDevice);
@@ -105,7 +110,7 @@ public class SpeedSensorReceiver
         deviceChannel = AntManager.Instance.OpenChannel(ANT_ReferenceLibrary.ChannelType.BASE_Slave_Receive_0x00,
             channelID, (ushort) device.deviceNumber, device.deviceType, device.transType, (byte) device.radiofreq,
             (ushort) device.period, false);
-        connected = true;
+        Connected = true;
         deviceChannel.onReceiveData += Data;
         deviceChannel.onChannelResponse += ChannelResponse;
 
@@ -120,31 +125,31 @@ public class SpeedSensorReceiver
         int revCount_speed = (data[6]) | data[7] << 8;
 
 
-        if (prev_measTime_speed != 0 && measTime_speed != prev_measTime_speed && prev_measTime_speed < measTime_speed &&
-            prev_revCount_speed < revCount_speed)
+        if (prevMeasTimeSpeed != 0 && measTime_speed != prevMeasTimeSpeed && prevMeasTimeSpeed < measTime_speed &&
+            prevRevCountSpeed < revCount_speed)
         {
-            speed = (wheelCircumference * (revCount_speed - prev_revCount_speed) * 1024) /
-                    (measTime_speed - prev_measTime_speed);
-            stopRevCounter_speed = 0;
+            sensorData.Speed = (Config.wheelCircumference * (revCount_speed - prevRevCountSpeed) * 1024) /
+                               (measTime_speed - prevMeasTimeSpeed);
+            stopRevCounterSpeed = 0;
         }
         else
-            stopRevCounter_speed++;
+            stopRevCounterSpeed++;
 
-        if (stopRevCounter_speed >= 5)
+        if (stopRevCounterSpeed >= 5)
         {
-            stopRevCounter_speed = 5;
-            speed = 0;
+            stopRevCounterSpeed = 5;
+            sensorData.Speed = 0;
         }
 
 
-        prev_measTime_speed = measTime_speed;
-        prev_revCount_speed = revCount_speed;
+        prevMeasTimeSpeed = measTime_speed;
+        prevRevCountSpeed = revCount_speed;
 
         //DISTANCE
         if (revCountZero == 0)
             revCountZero = revCount_speed;
 
-        distance = wheelCircumference * (revCount_speed - revCountZero);
+        sensorData.Distance = Config.wheelCircumference * (revCount_speed - revCountZero);
     }
 
 

+ 0 - 0
Assets/Scripts/ANT+/SpeedSensorReceiver.cs.meta → Assets/Scripts/Sensors/ANT+/SpeedSensorReceiver.cs.meta


+ 95 - 0
Assets/Scripts/Sensors/BikeSensorData.cs

@@ -0,0 +1,95 @@
+using System;
+using System.Configuration;
+using System.Data;
+using JetBrains.Annotations;
+
+
+public sealed class BikeSensorData
+{
+    #region signleton
+
+    private static readonly Lazy<BikeSensorData>
+        lazy =
+            new Lazy<BikeSensorData>
+                (() => new BikeSensorData());
+
+    public static BikeSensorData Instance => lazy.Value;
+
+    #endregion
+
+    [CanBeNull] private PowerMeterReceiver powerMeterReceiver;
+    [CanBeNull] private SpeedSensorReceiver speedSensorReceiver;
+    [CanBeNull] private HrReceiver hrReceiver;
+    [CanBeNull] private PolarReceiver polarReceiver;
+
+    public SpeedSensorData? SpeedData => speedSensorReceiver?.SensorData;
+    public PowermeterSensorData? PowermeterData => powerMeterReceiver?.SensorData;
+    public HRSensorData? HrData => hrReceiver?.SensorData;
+    public PolarSensorData? PolarData => polarReceiver?.SensorData;
+
+    private BikeSensorData()
+    {
+    }
+
+    public void StartListening(SpeedSensorConfig? speedSensorConfig = null,
+        PolarSensorConfig? polarSensorConfig = null, int? powermeterId = null, int? hrAntId = null)
+    {
+
+        if(speedSensorReceiver != null)
+        {
+            throw new InvalidConstraintException(
+                "BikeSensorData: Already listening to Speed Sensor");
+        }
+        if(hrReceiver != null)
+        {
+            throw new InvalidConstraintException(
+                "BikeSensorData: Already listening to HR Sensor");
+        }
+
+        if (polarReceiver != null)
+        {
+            throw new InvalidConstraintException(
+                "BikeSensorData: Already listening to Polar Sensor");
+        }
+        if (powerMeterReceiver != null)
+        {
+            throw new InvalidConstraintException(
+                "BikeSensorData: Already listening to Power Sensor");
+        }
+        
+        if (speedSensorConfig != null)
+        {
+            speedSensorReceiver = new SpeedSensorReceiver(speedSensorConfig.Value);
+            speedSensorReceiver.StartScan();
+        }
+
+        if (hrAntId != null)
+        {
+            hrReceiver = new HrReceiver(hrAntId.Value);
+            hrReceiver.StartScan();
+        }
+
+        if (powermeterId != null)
+        {
+            powerMeterReceiver = new PowerMeterReceiver(powermeterId.Value);
+            powerMeterReceiver.StartScan();
+        }
+
+        if (polarSensorConfig != null)
+        {
+            polarReceiver = new PolarReceiver(polarSensorConfig.Value); //automatically starts listening
+        }
+        
+    }
+
+    public void Dispose()
+    {
+        polarReceiver?.Dispose();
+        //TODO: also dispose ANT sensors?
+
+        polarReceiver = null;
+        speedSensorReceiver = null;
+        powerMeterReceiver = null;
+        hrReceiver = null;
+    }
+}

+ 3 - 0
Assets/Scripts/Sensors/BikeSensorData.cs.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 92dac27707204a8eb372f4f4d16716a5
+timeCreated: 1606375208

+ 0 - 0
Assets/Scripts/Polar.meta → Assets/Scripts/Sensors/Polar.meta


+ 9 - 12
Assets/Scripts/Polar/PolarAccData.cs → Assets/Scripts/Sensors/Polar/PolarAccData.cs

@@ -1,25 +1,22 @@
-using System.Collections;
+using System;
+using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
 using UnityEngine;
 using Valve.VR.InteractionSystem;
 
-public class AccData
+public struct AccData
 {
-    private long timestamp;
-    private List<Vector3> values;
-
-    public long Timestamp => timestamp;
-
-    public List<Vector3> Values => values;
+    public long Timestamp { get; }
+    public List<Vector3> Values { get; }
 
     AccData(long timestamp, List<Vector3> values)
     {
-        this.timestamp = timestamp;
-        this.values = values;
+        this.Timestamp = timestamp;
+        this.Values = values;
     }
 
-    public static AccData fromString(string s)
+    public static AccData FromString(string s)
     {
         var data = s.Split(';');
         if (data.Length == 2)
@@ -30,6 +27,6 @@ public class AccData
             return new AccData(t, floats.Select(a => new Vector3(a[0], a[1], a[2])).ToList());
         }
 
-        return null;
+        throw new FormatException("AccData String has wrong format");
     }
 }

+ 0 - 0
Assets/Scripts/Polar/PolarAccData.cs.meta → Assets/Scripts/Sensors/Polar/PolarAccData.cs.meta


+ 61 - 0
Assets/Scripts/Sensors/Polar/PolarReceiver.cs

@@ -0,0 +1,61 @@
+using System;
+using UnityEngine;
+using UnityEngine.Serialization;
+
+[System.Serializable]
+public struct PolarSensorConfig
+{
+    public int port;
+    public String ipAddress;
+
+    public PolarSensorConfig(int port = 9099, string ipAddress = "0.0.0.0")
+    {
+        this.port = port;
+        this.ipAddress = ipAddress;
+    }
+}
+
+public struct PolarSensorData
+{
+    public Vector3 Acc;
+    public float EcgValue;
+}
+
+public class PolarReceiver
+{
+    private UdpConnection connection;
+    private PolarSensorData sensorData;
+
+    public PolarSensorConfig SensorConfig { get; private set; }
+    public PolarSensorData SensorData => sensorData;
+
+
+    public PolarReceiver()
+    {
+    }
+
+    public PolarReceiver(PolarSensorConfig config, bool autoStart = true)
+    {
+        SensorConfig = config;
+        if (autoStart) StartListening();
+    }
+
+    public void StartListening()
+    {
+        connection = new UdpConnection(SensorConfig.ipAddress, SensorConfig.port, OnAccData);
+        connection.Listen();
+    }
+
+    public void Dispose()
+    {
+        connection.StopListening();
+    }
+
+    private void OnAccData(AccData data)
+    {
+        //Debug.Log(data.Timestamp);
+        sensorData.Acc = data.Values[0]; //TODO: what about rest of array?
+    }
+
+    //TODO: OnEcgData
+}

+ 11 - 0
Assets/Scripts/Sensors/Polar/PolarReceiver.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8266fb7f0f71f4746875d145fd84cb26
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 1 - 1
Assets/Scripts/Polar/UdpConnection.cs → Assets/Scripts/Sensors/Polar/UdpConnection.cs

@@ -37,7 +37,7 @@ public class UdpConnection
                 var name = data[0];
                 if (name.Equals("ACC"))
                 {
-                    onAccData(AccData.fromString(data[1]));
+                    onAccData(AccData.FromString(data[1]));
                 }else if (name.Equals("ECG"))
                 {
                     //TODO

+ 0 - 0
Assets/Scripts/Polar/UdpConnection.cs.meta → Assets/Scripts/Sensors/Polar/UdpConnection.cs.meta


+ 2 - 2
ProjectSettings/ProjectVersion.txt

@@ -1,2 +1,2 @@
-m_EditorVersion: 2019.3.1f1
-m_EditorVersionWithRevision: 2019.3.1f1 (89d6087839c2)
+m_EditorVersion: 2019.4.15f1
+m_EditorVersionWithRevision: 2019.4.15f1 (fbf367ac14e9)

BIN
obj/Debug/Assembly-CSharp.csprojAssemblyReference.cache


BIN
obj/Debug/SteamVR_Windows_EditorHelper.csprojAssemblyReference.cache