From 0abf247074f510803e40d9314e58bd875d7d04cd Mon Sep 17 00:00:00 2001 From: teamclouday Date: Sun, 22 Aug 2021 17:00:38 -0400 Subject: [PATCH] improve stability and reduce delay --- Android/app/build.gradle | 4 +- .../example/androidsteering/Connection.java | 68 ++++++++------ .../com/example/androidsteering/Motion.java | 4 +- Windows/README.md | 2 +- Windows/SteeringWheel/Connection.cs | 90 +++++++++++++------ Windows/SteeringWheel/Controller.cs | 60 +++++++------ Windows/SteeringWheel/SteeringWheel.csproj | 2 +- 7 files changed, 144 insertions(+), 86 deletions(-) diff --git a/Android/app/build.gradle b/Android/app/build.gradle index 46e1a93..92d7690 100644 --- a/Android/app/build.gradle +++ b/Android/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "com.example.androidsteering" minSdkVersion 19 targetSdkVersion 29 - versionCode 4 - versionName "2.0.0" + versionCode 5 + versionName "2.1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { diff --git a/Android/app/src/main/java/com/example/androidsteering/Connection.java b/Android/app/src/main/java/com/example/androidsteering/Connection.java index 676a480..54f856d 100644 --- a/Android/app/src/main/java/com/example/androidsteering/Connection.java +++ b/Android/app/src/main/java/com/example/androidsteering/Connection.java @@ -43,59 +43,71 @@ static class MyBuffer private boolean updatePitch = true; private boolean updateRoll = true; - public synchronized void addData(float pitch, float roll) + public void addData(float pitch, float roll) { if(!running) return; - if(updatePitch) buff.add(new Motion.MyMove(false, 0, pitch)); - if(updateRoll) buff.add(new Motion.MyMove(false, 1, roll)); - int idx = 0; - while(buff.size() > MAX_SIZE && idx < buff.size()) + synchronized (buff) { - if(buff.get(idx).MotionButton) + if(updatePitch) buff.add(new Motion.MyMove(false, 0, pitch)); + if(updateRoll) buff.add(new Motion.MyMove(false, 1, roll)); + int idx = buff.size() - 1; + while(buff.size() > MAX_SIZE && idx >= 0) { - idx++; - continue; + if(buff.get(idx).MotionButton) + { + idx--; + continue; + } + buff.remove(idx); } - buff.remove(idx); } } - public synchronized void addData(int status, float val) + public void addData(int status, float val) { if(!running) return; - buff.add(new Motion.MyMove(false, status, val)); - int idx = 0; - while(buff.size() > MAX_SIZE && idx < buff.size()) + synchronized (buff) { - if(buff.get(idx).MotionButton) + buff.add(new Motion.MyMove(false, status, val)); + int idx = buff.size() - 1; + while(buff.size() > MAX_SIZE && idx >= 0) { - idx++; - continue; + if(buff.get(idx).MotionButton) + { + idx--; + continue; + } + buff.remove(idx); } - buff.remove(idx); } } - public synchronized void addData(MotionButton button) + public void addData(MotionButton button) { if(!running) return; - buff.add(new Motion.MyMove(true, button.getVal(), 0.0f)); - int idx = 0; - while(buff.size() > MAX_SIZE && idx < buff.size()) + synchronized (buff) { - if(buff.get(idx).MotionButton) + buff.add(new Motion.MyMove(true, button.getVal(), 0.0f)); + int idx = buff.size() - 1; + while(buff.size() > MAX_SIZE && idx >= 0) { - idx++; - continue; + if(buff.get(idx).MotionButton) + { + idx--; + continue; + } + buff.remove(idx); } - buff.remove(idx); } } - public synchronized Motion.MyMove getData() + public Motion.MyMove getData() { - if(buff.size() <= 0) return null; - return buff.remove(0); + synchronized (buff) + { + if(buff.size() <= 0) return null; + return buff.remove(0); + } } public synchronized void turnOn(){running = true;} diff --git a/Android/app/src/main/java/com/example/androidsteering/Motion.java b/Android/app/src/main/java/com/example/androidsteering/Motion.java index a0f5ed6..4ac05cf 100644 --- a/Android/app/src/main/java/com/example/androidsteering/Motion.java +++ b/Android/app/src/main/java/com/example/androidsteering/Motion.java @@ -76,8 +76,8 @@ public Motion(MainActivity activity, Connection.MyBuffer buffer) public void start() { // sample period is set to 10ms - sensorManager.registerListener(this, accSensor, SensorManager.SENSOR_DELAY_UI); - sensorManager.registerListener(this, magSensor, SensorManager.SENSOR_DELAY_UI); + sensorManager.registerListener(this, accSensor, SensorManager.SENSOR_DELAY_GAME); + sensorManager.registerListener(this, magSensor, SensorManager.SENSOR_DELAY_GAME); Log.d(mainActivity.getString(R.string.logTagMotion), "Sensor listener registered"); } diff --git a/Windows/README.md b/Windows/README.md index 422a390..314c5c3 100644 --- a/Windows/README.md +++ b/Windows/README.md @@ -25,7 +25,7 @@ Used to configure controller buttons and axis * Interpreted range is `(-80, 10)` Overflowing values are clamped * Steering (Pitch) - * Real range is `(-90, 90)`, with resting mode in range `(-2, 2)` + * Real range is `(-90, 90)`, with no resting mode * Interpreted range is `(-45, 45)` Overflowing values are clamped diff --git a/Windows/SteeringWheel/Connection.cs b/Windows/SteeringWheel/Connection.cs index 3060bc4..4671c55 100644 --- a/Windows/SteeringWheel/Connection.cs +++ b/Windows/SteeringWheel/Connection.cs @@ -24,21 +24,37 @@ public void AddData(bool v1, int v2, float v3) { lock(buffer) { - buffer.Add(new MotionData() + if(v1 || buffer.Count <= MAX_SIZE) { - IsButton = v1, - Status = v2, - Value = v3 - }); - int idx = 0; - while (buffer.Count > MAX_SIZE && idx < buffer.Count) + buffer.Add(new MotionData() + { + IsButton = v1, + Status = v2, + Value = v3 + }); + } + else { - if (buffer[idx].IsButton) + bool updated = false; + for (int idx = buffer.Count - 1; idx >= 0; idx--) { - idx++; - continue; + if (!buffer[idx].IsButton && buffer[idx].Status == v2) + { + buffer[idx].Value = buffer[idx].Value * 0.4f + v3 * 0.6f; // take weighted average + updated = true; + break; + } + } + // if not updated, insert regardless of oversize + if(!updated) + { + buffer.Add(new MotionData() + { + IsButton = v1, + Status = v2, + Value = v3 + }); } - buffer.RemoveAt(idx); } } } @@ -46,16 +62,27 @@ public void AddData(MotionData data) { lock(buffer) { - buffer.Add(data); - int idx = 0; - while (buffer.Count > MAX_SIZE && idx < buffer.Count) + if (data.IsButton || buffer.Count <= MAX_SIZE) { - if (buffer[idx].IsButton) + buffer.Add(data); + } + else + { + bool updated = false; + for (int idx = buffer.Count - 1; idx >= 0; idx--) + { + if (!buffer[idx].IsButton && buffer[idx].Status == data.Status) + { + buffer[idx].Value = buffer[idx].Value * 0.4f + data.Value * 0.6f; // take weighted average + updated = true; + break; + } + } + // if not updated, insert regardless of oversize + if (!updated) { - idx++; - continue; + buffer.Add(data); } - buffer.RemoveAt(idx); } } } @@ -105,10 +132,13 @@ class Connection private readonly int MAX_WAIT_TIME = 1500; private readonly int DATA_SEPARATOR = 10086; - private readonly int BUFFER_SIZE = 13 * 5; // 5 data packs each time + private readonly int PACK_SIZE = 13; + private readonly int NUM_PACKS = 4; // 4 packs a time private readonly int DEVICE_CHECK_EXPECTED = 123456; private readonly int DEVICE_CHECK_DATA = 654321; private bool isConnectionAllowed = false; + private byte[] lastPack = new byte[13]; + private int lastPackLength = 0; // bluetooth components private readonly Guid bthServerUUID = new Guid("a7bda841-7dbc-4179-9800-1a3eff463f1c"); @@ -260,12 +290,14 @@ private void ConnectBluetooth() while (isConnectionAllowed && bthClient != null) { // read data into a buffer - byte[] buffer = new byte[BUFFER_SIZE]; - int size = bthStream.Read(buffer, 0, BUFFER_SIZE); + byte[] buffer = new byte[PACK_SIZE * (NUM_PACKS + 1)]; + Array.Copy(lastPack, 0, buffer, 0, lastPackLength); // add last pack + int size = bthStream.Read(buffer, lastPackLength, PACK_SIZE * NUM_PACKS); if (size <= 0) break; + int totalSize = size + lastPackLength; // process data into data packs int idx = 0; - while (idx <= size - 13) + while (idx <= totalSize - PACK_SIZE) { // check for separator Array.Copy(buffer, idx, placeholder, 0, 4); @@ -288,6 +320,9 @@ private void ConnectBluetooth() // add to shared buffer sharedBuffer.AddData(data); } + // check for remaining pack, and store for next loop + Array.Copy(buffer, idx, lastPack, 0, totalSize - idx); + lastPackLength = totalSize - idx; Thread.Sleep(1); } } @@ -438,12 +473,14 @@ private void ConnectWifi() while (isConnectionAllowed && wifiClient != null) { // read data into a buffer - byte[] buffer = new byte[BUFFER_SIZE]; - int size = wifiStream.Read(buffer, 0, BUFFER_SIZE); + byte[] buffer = new byte[PACK_SIZE * (NUM_PACKS + 1)]; + Array.Copy(lastPack, 0, buffer, 0, lastPackLength); // add last pack + int size = wifiStream.Read(buffer, lastPackLength, PACK_SIZE * NUM_PACKS); if (size <= 0) break; + int totalSize = size + lastPackLength; // process data into data packs int idx = 0; - while (idx <= size - 13) + while (idx <= totalSize - PACK_SIZE) { // check for separator Array.Copy(buffer, idx, placeholder, 0, 4); @@ -466,6 +503,9 @@ private void ConnectWifi() // add to shared buffer sharedBuffer.AddData(data); } + // check for remaining pack, and store for next loop + Array.Copy(buffer, idx, lastPack, 0, totalSize - idx); + lastPackLength = totalSize - idx; Thread.Sleep(1); } } diff --git a/Windows/SteeringWheel/Controller.cs b/Windows/SteeringWheel/Controller.cs index b0faf9b..0fb2177 100644 --- a/Windows/SteeringWheel/Controller.cs +++ b/Windows/SteeringWheel/Controller.cs @@ -93,7 +93,7 @@ class Controller private long axisMax = 0; public bool vJoyInitialized { get; private set; } private const int triggerInterval = 100; - private const int updateInterval = 10; + private const int updateInterval = 5; public Controller(MainWindow window, SharedBuffer buffer) { @@ -277,33 +277,39 @@ private void ProcessAcceleration(float val) /// private void ProcessSteering(float val) { - if(-2.0f <= val && val <= 2.0f) + //if(-2.0f <= val && val <= 2.0f) + //{ + // // set to rest mode + // lock (joyReportLock) + // { + // joyReport.AxisX = (int)(axisMax / 2); + // } + //} + //else if(2.0f < val && val <= 90.0f) + //{ + // // turning left + // float step = FilterSmoothStep(val, 2.0f, CAP_Steering); + // float half = axisMax / 2.0f * step; + // lock (joyReportLock) + // { + // joyReport.AxisX = (int)(axisMax / 2.0f - half); + // } + //} + //else if(-90.0f <= val && val < -2.0f) + //{ + // // turning right + // float step = FilterSmoothStep(-val, 2.0f, CAP_Steering); + // float half = axisMax / 2.0f * step; + // lock (joyReportLock) + // { + // joyReport.AxisX = (int)(axisMax / 2.0f + half); + // } + //} + float step = FilterLinear(-val, -CAP_Steering, CAP_Steering); + val = axisMax * step; + lock(joyReportLock) { - // set to rest mode - lock (joyReportLock) - { - joyReport.AxisX = (int)(axisMax / 2); - } - } - else if(2.0f < val && val <= 90.0f) - { - // turning left - float step = FilterSmoothStep(val, 2.0f, CAP_Steering); - float half = axisMax / 2.0f * step; - lock (joyReportLock) - { - joyReport.AxisX = (int)(axisMax / 2.0f - half); - } - } - else if(-90.0f <= val && val < -2.0f) - { - // turning right - float step = FilterSmoothStep(-val, 2.0f, CAP_Steering); - float half = axisMax / 2.0f * step; - lock (joyReportLock) - { - joyReport.AxisX = (int)(axisMax / 2.0f + half); - } + joyReport.AxisX = (int)val; } } diff --git a/Windows/SteeringWheel/SteeringWheel.csproj b/Windows/SteeringWheel/SteeringWheel.csproj index a38dc13..47e0638 100644 --- a/Windows/SteeringWheel/SteeringWheel.csproj +++ b/Windows/SteeringWheel/SteeringWheel.csproj @@ -30,7 +30,7 @@ Teamclouday false 1 - 2.0.0.%2a + 2.1.0.%2a false true true