xamarin / Essentials

Xamarin.Essentials is no longer supported. Migrate your apps to .NET MAUI, which includes Maui.Essentials.
https://aka.ms/xamarin-upgrade
Other
1.52k stars 506 forks source link

[Bug] SensorSpeed intervals differ between Android and iOS #1438

Open janusw opened 4 years ago

janusw commented 4 years ago

Description

Looking at https://github.com/xamarin/Essentials/blob/main/Xamarin.Essentials/Types/SensorSpeed.ios.tvos.watchos.cs, one can see the following SensorSpeed intervals for iOS:

(The source code does not give any hint as to where these numbers come from.)

On Android, in contrast, there are no hard-coded numbers, but instead one relies on Android.Hardware.SensorDelay. According to https://developer.android.com/guide/topics/sensors/sensors_overview, the Android intervals are defined like this:

Ideally the sensor intervals should be the same on all platforms, I guess. However, as one can see above, they differ considerably between Android and iOS (in particular the smaller intervals).

Basic Information

janusw commented 4 years ago

After doing some git archeology, I found that the iOS numbers were first introduced with the OrientationSensor implementation (#249). Btw, the OrientationSensor is also where I noticed the differences.

The OrientationSensor was initially implemented with commit 3432c0e65929a445acaa71f0b9bdf972a8d03ed6, which includes a revealing comment in OrientationSensor.ios.cs:

        // Timing intervales to match android sensor speeds in seconds
        // https://stackoverflow.com/questions/10044158/android-sensors

So, first of all I'm glad that there was the desire to match the Android sensor speeds :)

However, looking at https://stackoverflow.com/questions/10044158/android-sensors, the Xamarin iOS values apparently come from the top-rated answer, which only has approximations based on test results. Also it's from 2013.

The second answer also quotes the numbers from https://developer.android.com/guide/topics/sensors/sensors_overview, which I could even verify by measurement (for the fastest interval I actually get values around 5ms on my Zenfone 6 with Android 10).

So I assume the numbers in the Stackoverflow thread are simply wrong (either measured incorrectly, or outdated).

janusw commented 4 years ago

It seems that one should not use an actual zero for the sensor interval (at least not on UWP, where a zero is used to turn off the sensor, see #419).

janusw commented 4 years ago

UWP used even other values originally (neither agreeing with Android nor iOS), but after the values were unified in 1806eb9f7544f54f19ffc02e32cc110c8ba134bb, UWP uses the same values as iOS.

Tizen still uses yet another set of values, but some of them actually agree with Android already :)

janusw commented 3 years ago

The biggest problem here, apart from the sensor rates simply differing across platforms, is that the rates on iOS are systematically lower than on Android, and in some cases just loo low.

In particular the interval of 20ms for SensorSpeed.Fastest corresponds to an update rate of 50 Hz, which is even lower than the typical screen refresh rates of modern devices (often 60 Hz or even above).

janusw commented 3 years ago

While it's always possible to down-sample a high rate to something lower (e.g. via Reactive Observables), the opposite is impossible, of course.

Let's say we're aiming at a sensor rate of 60 Hz, matching a device's screen refresh rate (in order to achieve a visual appearance that's as smooth as possible, e.g. for an augmented-reality display that relies on OrientationSensor data) ...

By that argument, SensorSpeed.Fastest should really correspond to the highest rate possible. The 5 ms interval used in my patch (see above) is already a big improvement over the 20 ms that XE uses for iOS and UWP right now, and it would even be sufficient for the latest devices with a 120 Hz screen.

However, one should probably check whether it's possible to achieve even higher sampling rates on iOS (as a reminder: the 5 ms were the maximum I could achieve on an Android 10 device).

janusw commented 3 years ago

However, one should probably check whether it's possible to achieve even higher sampling rates on iOS (as a reminder: the 5 ms were the maximum I could achieve on an Android 10 device).

On iOS, the smallest interval I can measure is roughly 9 ms, which is about double of the value on Android (roughly 4.5 ms).

janusw commented 3 years ago

I verified that the interval with SensorSpeed.Fastest is 4 - 4.5 ms not only on Android 10, but also on also on an older device with Android 6.

Also I have extended the XE samples app to measure the interval of the OrientationSensor (see #1439).