I am trying to use the OrientationSensor as of Xamarin Essentials version 1.3.1 on Android and iOS.
On Android I see essentially the expected behavior, as documented at https://docs.microsoft.com/en-us/xamarin/essentials/orientation-sensor, namely: Pointing the device in a particular direction gives me a particular quaternion, irrespective of the orientation in which the sensor was started. When stopping the sensor and restarting it without changing orientation, the quaternion I get is (roughly) the same as before the restart.
On iOS this is different. There the quaternions I obtain depend on the device orientation in which the sensor was started: When starting the sensor while the phone lies flat on the table, the initial quaternion is always (0,0,0,1), no matter in which direction the device is pointing. If I stop and restart the sensor, the quaternion always goes back to (0,0,0,1).
However, when the sensor is started while the device is out of the table plane, the initial quaternion is not (0,0,0,1). The inclination angle seems to be reflected in the initial quaternion, but the azimutal angle is not.
This means that the orientation quaternion obtained on iOS is somehow relative to the initial orientation, while on Android it is 'absolute' (in the sense that it describes the rotation of the phone coordinate system into the earth coordinate system, as explained in the documentation).
The observed quaternion should be (0, 0, 0.707, 0.707), or at least close to it.
The observed quaternion is (0, 0, 0, 1). Seen on an iPhone 8 with iOS 13.2.
This could somehow have to do with CMAttitudeReferenceFrame. I don't know what the default is. I have very limited experience with the Android sensors.
This could somehow have to do with CMAttitudeReferenceFrame. I don't know what the default is.
Thanks for the hint. I think you are absolutely right. CMAttitudeReferenceFrameXArbitraryZVertical corresponds exactly to the behavior I'm seeing. Also it appear to be the default value, as a simple test shows:
CMMotionManager moma = new CMMotionManager();
Console.WriteLine("AttitudeReferenceFrame: " + moma.AttitudeReferenceFrame);
The Xamarin OrientationSensor should use CMAttitudeReferenceFrameXTrueNorthZVertical (or at least CMAttitudeReferenceFrameXMagneticNorthZVertical) in order to comply with its own documentation (and to be consistent with Android).
Ok, it is pretty straightforward to use a different reference frame for the OrientationSensor (see
20a8f90), but the actual problem is that one can only make the X axis point north, while the documentation (and Android) want the Y axis to point north.
So, the good news is that we can make iOS use a fixed reference frame, but the bad news is that it's still inconsistent with Android (and the documentation) :unamused:
Ok, it is pretty straightforward to use a different reference frame for the OrientationSensor (see
20a8f90), but the actual problem is that one can only make the X axis point north, while the documentation (and Android) want the Y axis to point north.
Since it's not possible to pick the required reference frame directly, one has to fix up the obtained quaternions manually via a rotation by 90 degrees around the z axis. This is done in the commit
61230c2, which resolves the issue from my point of view. I have already submitted a pull request for it (#988).
Most helpful comment
Since it's not possible to pick the required reference frame directly, one has to fix up the obtained quaternions manually via a rotation by 90 degrees around the z axis. This is done in the commit
61230c2, which resolves the issue from my point of view. I have already submitted a pull request for it (#988).