Xamarin Датчик ориентации Quaternion - PullRequest
0 голосов
/ 05 февраля 2019

Я пытаюсь определить 3d вектор Vector3, представляющий ориентацию моих телефонов без угла.То, что я ищу, это вектор, который образно выходит из задней части телефона, как луч, в основном нормальный вектор телефона.

Я знаю, что кватернион дает мне преобразование, но во что?

Кроме того, я нашел Quaternion.ToAxisAngle(), который преобразует кватернион в ось и соответствующий ей угол крена.Я подумал, отлично, это то, что мне нужно, я могу просто игнорировать угол.

Когда телефон лежит на столе, я получаю следующую ось:

axis = [0,0,-1]

И угол в основномпредставляет угол компаса.В этой конкретной ситуации это то, что я ожидал.Но когда телефон имеет другое произвольное пространственное положение, ось больше не является вектором нормалей телефона.

Как рассчитать вектор нормали к плоскости телефона?

1 Ответ

0 голосов
/ 06 февраля 2019

«Все относительно» 100

Итак, вам нужно сохранить кватернион и использовать его в качестве источника (это также называется centre), а затем вы можете локализовать любые новые кватернионы, чтобы определитькакие изменения ориентации произошли.

Калибровка

Калибровку можно выполнить, попросив пользователя держать телефон устойчиво, а затем произвести выборку и отсеивание потока кватернионов и усреднить их за период времени.,Но для этого примера.Просто положите устройство на стол, откройте экран, прежде чем запускать приложение, и возьмите первый образец (не очень, но для быстрого запуска).

Примечание: Система.Реактивная наблюдаемая прекрасно подходит для выборки и дебасинга

Примечание: Сохраните этот кватернион как его обратное значение (Quaternion.Inverse), так как это на один расчет меньше, чем вы должны выполнить для каждой выборки.

Рассчитайте разницу для каждого образца:

Вы хотите умножить текущий кватернион выборки на начало координат / центр (в обратной форме).

Примечание: запомнитьумножение не является коммутативным с кватернионами, поэтому порядок имеет значение (!)

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

Преобразование вашего локализованного кватерниона

Так что теперь у вас есть локализованный кватернион, который вы можете преобразовать в Vector3 (преобразовать его с помощьюбазовый вектор (вверх, вперед, вниз, ...) или получить некоторые углы Эйлера или ...

Пример:

Так что, используя образец Xamarin Essentials, я бы так изменилOrientationSensor_ReadingChanged событие как vочень быстрый пример.

Примечание: Событие выборки называется LOT в зависимости от устройства, и SensorSpeed действительно бесполезен при управлении скоростью вывода.Если вы пытаетесь напрямую обновить экран с помощью этих примеров (в соотношении 1 к 1), у вас могут возникнуть серьезные проблемы (сборщик мусора Mono может едва поспевать за GC, сохраняя строки, которые создаются при обновлении пользовательского интерфейса).(смотрите выходные данные приложения, циклы GC происходят постоянно, даже с установленным SensorSpeed.UI.) Я использую Reactive Observables для сглаживания выборок и регулирования выходного сигнала датчика до приемлемых циклов обновления (16 мс или более) перед обновлением пользовательского интерфейса.

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;
        });
    });
}

Примечание. Просто добавьте в свой любимый кватернион подпрограмму углов Эйлера (и, при желании, напишите подпрограмму сглаживания и дросселирования).

Вывод:

enter image description here

...