Fix moving average quaternion desync & smoothing (#1351)

This commit is contained in:
Butterscotch!
2025-03-16 08:04:10 -04:00
committed by GitHub
parent 5353101fff
commit eb23778bec

View File

@@ -29,8 +29,7 @@ class QuaternionMovingAverage(
private var latestQuaternion = IDENTITY
private var smoothingQuaternion = IDENTITY
private val fpsTimer = if (VRServer.instanceInitialized) VRServer.instance.fpsTimer else NanoTimer()
private var frameCounter = 0
private var lastAmt = 0f
private var timeSinceUpdate = 0f
init {
// amount should range from 0 to 1.
@@ -71,28 +70,15 @@ class QuaternionMovingAverage(
filteredQuaternion = filteredQuaternion.interpR(quatBuf, amt)
}
} else if (type == TrackerFilters.SMOOTHING) {
// Increase every update for linear interpolation
frameCounter++
// Make it framerate-independent
timeSinceUpdate += fpsTimer.timePerFrame
// Calculate the slerp factor based off the smoothFactor and smoothingCounter
var amt = smoothFactor * frameCounter
// Make it framerate-independent
amt *= fpsTimer.timePerFrame
// Be at least last amount to not rollback
amt = amt.coerceAtLeast(lastAmt)
// limit to 1 to not overshoot
amt = amt.coerceAtMost(1f)
lastAmt = amt
val amt = (smoothFactor * timeSinceUpdate).coerceAtMost(1f)
// Smooth towards the target rotation by the slerp factor
filteredQuaternion = smoothingQuaternion.interpR(latestQuaternion, amt)
} else {
// No filtering; just keep track of rotations (for going over 180 degrees)
filteredQuaternion = latestQuaternion.twinNearest(smoothingQuaternion)
}
filteringImpact = latestQuaternion.angleToR(filteredQuaternion)
@@ -108,21 +94,20 @@ class QuaternionMovingAverage(
// Gets and stores the rotation between the last 2 quaternions
rotBuffer?.add(latestQuaternion.inv().times(q))
} else if (type == TrackerFilters.SMOOTHING) {
frameCounter = 0
lastAmt = 0f
timeSinceUpdate = 0f
smoothingQuaternion = filteredQuaternion
} else {
smoothingQuaternion = filteredQuaternion
// No filtering; just keep track of rotations (for going over 180 degrees)
filteredQuaternion = q.twinNearest(filteredQuaternion)
}
latestQuaternion = q
}
@Synchronized
fun resetQuats(q: Quaternion) {
if (type == TrackerFilters.PREDICTION) {
rotBuffer?.clear()
latestQuaternion = q
}
rotBuffer?.clear()
latestQuaternion = q
filteredQuaternion = q
addQuaternion(q)
}