I’m trying to calculate the compass rotation in my viewmodel, The orientation data is provided by FusedOrientationProviderClient
. Despite applying a low-pass filter to the azimuth value, the compass experiences drift when the device is moved quickly.
private val provider =
LocationServices.getFusedOrientationProviderClient(context)
fun requestOrientationUpdates(
samplingDelay: OrientationOutputDelay = OrientationOutputDelay.MEDIUM,
executor: ExecutorService = Executors.newSingleThreadExecutor(),
) = callbackFlow {
val listener = DeviceOrientationListener {
launch { send(it) }
}
val request = DeviceOrientationRequest.Builder(
samplingDelay.toDeviceOrientationRequestDelay()
).build()
provider.requestOrientationUpdates(
/* request */ request,
/* executor */ executor,
/* callback listener */ listener
)
awaitClose {
provider.removeOrientationUpdates(listener)
}
}
private fun calculateCompassRotation(
location: Location,
deviceOrientation: DeviceOrientation
): CompassState {
val azimuthInDegrees = deviceOrientation.headingDegrees
var bearTo = location.bearingTo(destLoc)
if (bearTo < 0) bearTo += 360
var direction: Float = bearTo - azimuthInDegrees
if (direction < 0) direction += 360
val isFacingDest = direction in 358.0..360.0 || direction in 0.0..2.0
// Low-pass filter
val alpha = 0.1f
val smoothedDirection = currentDegreeNeedle + alpha * (direction - currentDegreeNeedle)
currentDegreeNeedle = smoothedDirection
val smoothedAzimuth = currentDegree + alpha * (azimuthInDegrees - currentDegree)
currentDegree = -smoothedAzimuth
val needleRotation = RotationTarget(currentDegreeNeedle, smoothedDirection)
val compassRotation = RotationTarget(currentDegree, -smoothedAzimuth)
return CompassState(
isFacingDestination = isFacingDest,
needleRotation = needleRotation,
compassRotation = compassRotation
)
}
I’ve tried testing with OutputDelay
with both OutputDelay set to DEFAULT
and MEDIUM
.
Logs: https://pastebin.com/ivWjpTm2
After a fast movement, even if the user stops, the headingDegrees
value seems to fall in the direction it was moving in before.