Xamarin Orientation Sensor Quaternion

大城市里の小女人 提交于 2019-12-11 18:06:39

问题


I'm trying to determine a 3d vector Vector3 representing my phones orientation without an angle. What I'm looking for is the vector that figuratively comes out of the back of the phone like a ray, basically a normal vector of the phone.

I know the quaternion gives me a transformation, but to what?

Furthermore, I found Quaternion.ToAxisAngle(), which transforms a quaternion to an axis and its respective roll angle. I thought, great, that's what I need, I can just ignore the angle.

When the phone lies on the table, I get the following axis:

axis = [0,0,-1]

And the angle basically represents the angle of the compass. In that particular situation, that's what I expected. But when the phone has a different arbitrary spatial position, the axis doesn't seem to be the phone's normal vector any more.

How can I calculate a normal vector to the phone's plane?


回答1:


"Everything is relative" 😎

So what you need to do is save a quaternion and use that as an origin (it is also call centre) and then you can localize any new quaternions to determine what orientation changes have occurred.

Calibration

A calibration can be performed by telling the user to hold the phone steady and then sampling and debouncing a stream of quaternion and averaging them over a period of time. But for this example. just place the device on a table, screen up, before starting the app, and grab the first sample (not great, but for a quickie it works).

Note: A System.Reactive observable works great for sampling and debouncing

Note: Store this quaternion as its inverse (Quaternion.Inverse) as that is one less calculation you have to perform on each sample.

Calc the difference on each sample:

You want to multiply the current sampled quaternion by the origin/centre (in inverse form).

Note: Remember multiplication is non-commutative with quaternions so order matters(!)

var currentQ = e.Reading.Orientation;
var q = Quaternion.Multiply(originQ, currentQ);

Convert your localized quaternion

So now you have a localized quaternion that you can convert to a Vector3 (transform it by a base vector (up, forward, down, ...) or obtain some Euler angles or ...

Example:

So using the Xamarin Essentials sample, this is how I would change the OrientationSensor_ReadingChanged event as a very quick example.

Note: The sampling event is called A LOT depending upon the device and SensorSpeed is really useless on controlling the output rate. If you are directly trying to update the screen with these samples (on a 1-to-1 basis), you could have serious problems (the Mono garbage collector can barely keep up with GC'ing the strings that are created when updating the UI (watch the application output, GC cycles are occurring constantly, even with SensorSpeed.UI set). I use Reactive Observables to smooth the samples and throttle the sensor output to reasonable update cycles (16ms or more) before updating the UI.

void OrientationSensor_ReadingChanged(object sender, OrientationSensorChangedEventArgs e)
{
    if (originQ == Quaternion.Identity) // auto-origin on first sample or when requested
    {
        originQ = Quaternion.Inverse(e.Reading.Orientation);
    }

    var q = Quaternion.Multiply(originQ, e.Reading.Orientation);

    GetEulerAngles(q, out yaw, out pitch, out roll); // assuming "right-hand" orientation

    SmoothAndThrottle(yaw, pitch, roll, () =>
    {
        Device.BeginInvokeOnMainThread(() =>
        {
            pitchLabel.Text = pitch.ToString();
            rollLabel.Text = roll.ToString();
            yawLabel.Text = yaw.ToString();

            // This will appear to keep the image aligned to the origin/centre.
            direction.RotateTo(90 * yaw, 1);
            direction.RotationX = 90 * pitch;
            direction.RotationY = -90 * roll;
        });
    });
}

Note: Just sub in your favorite quaternion to Euler angles routine (and write a smoothing and throttling routine if desired).

Output:



来源:https://stackoverflow.com/questions/54540095/xamarin-orientation-sensor-quaternion

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!