diff --git a/App v2/.idea/vcs.xml b/App v2/.idea/vcs.xml
new file mode 100644
index 0000000..6c0b863
--- /dev/null
+++ b/App v2/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/App v2/app/src/main/AndroidManifest.xml b/App v2/app/src/main/AndroidManifest.xml
index aa47874..d7b5282 100644
--- a/App v2/app/src/main/AndroidManifest.xml
+++ b/App v2/app/src/main/AndroidManifest.xml
@@ -18,6 +18,7 @@
+
diff --git a/App v2/app/src/main/java/com/erik/bleindoorpositioning/ble/BleScanner.kt b/App v2/app/src/main/java/com/erik/bleindoorpositioning/ble/BleScanner.kt
index b50b500..61c3bf6 100644
--- a/App v2/app/src/main/java/com/erik/bleindoorpositioning/ble/BleScanner.kt
+++ b/App v2/app/src/main/java/com/erik/bleindoorpositioning/ble/BleScanner.kt
@@ -14,15 +14,18 @@ import com.erik.bleindoorpositioning.model.PositionResult
import com.erik.bleindoorpositioning.model.ScannedBeacon
import com.erik.bleindoorpositioning.positioning.BeaconFilterManager
import com.erik.bleindoorpositioning.positioning.KalmanFilter
+import com.erik.bleindoorpositioning.positioning.MovingAverageFilter
import com.erik.bleindoorpositioning.positioning.PositionCalculator
+import com.erik.bleindoorpositioning.positioning.PositionKalmanFilter
import com.erik.bleindoorpositioning.positioning.PositionSmoother
+import com.erik.bleindoorpositioning.positioning.SensorFusionManager
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import java.util.concurrent.TimeUnit
-class BleScanner(context: Context, private val configRepository: ConfigRepository, private val coroutineScope: CoroutineScope) {
+class BleScanner(private val context: Context, private val configRepository: ConfigRepository, private val coroutineScope: CoroutineScope) {
companion object {
private const val TAG = "BleScanner"
@@ -52,18 +55,34 @@ class BleScanner(context: Context, private val configRepository: ConfigRepositor
private var retryAttempt = 0
// RSSI-Filterung
- private val filterManager = BeaconFilterManager {
- KalmanFilter(
- processNoise = 0.5, // TODO: Kalibrieren
- measurementNoise = 10.0 // TODO: Kalibrieren
- )
+ private val filterManager = BeaconFilterManager { // Filter für einzelne Beacon-RSSI-Werte
+ MovingAverageFilter(windowSize = 20) // 20 Messpunkte für stabile Mittelwertbildung
}
// Positionsberechnung (wird bei jedem Scan-Start neu initialisiert)
private var positionCalculator: PositionCalculator? = null
// Positions-Glättung
- private val positionSmoother = PositionSmoother(alpha = 0.15)
+ private val positionSmoother = PositionSmoother(alpha = 0.25) // Reaktiver, da EKF schon glättet
+
+ // Sensor-Fusion (EKF + PDR)
+ private val positionKalmanFilter = PositionKalmanFilter(processNoise = 0.5) // Standard: Balance zwischen PDR und BLE
+ private var isEkfInitialized = false
+ private var sensorFusionManager: SensorFusionManager? = null
+ private val lock = Any()
+
+ init {
+ sensorFusionManager = SensorFusionManager(context) { heading, stepLength ->
+ synchronized(lock) {
+ positionKalmanFilter.predict(heading, stepLength)
+ val fusedPos = positionKalmanFilter.getPosition()
+ val smoothed = positionSmoother.update(fusedPos)
+ _position.value?.let { prev ->
+ _position.value = prev.copy(position = smoothed)
+ }
+ }
+ }
+ }
// Öffentliche State Flows
private val _beacons = MutableStateFlow