"Все относительно" ????
Итак, что вам нужно сделать, это сохранить кватернион и использовать его в качестве источника (он также называется centre
), а затем вы можете локализовать любые новые кватернионы, чтобы определить, какие изменения ориентации произошли.
Калибровка
Калибровку можно выполнить, попросив пользователя держать телефон неподвижно, а затем произвести выборку и устранение дребезга потока кватернионов и усреднить их за определенный период времени. Но для этого примера. просто поместите устройство на стол, экран вверх, прежде чем запускать приложение, и возьмите первый образец (не очень хорошо, но на скорую руку это работает).
Примечание. Наблюдаемый объект System.Reactive отлично подходит для выборки и устранения дребезга.
Примечание. Сохраните этот кватернион как его инверсию (Quaternion.Inverse
), так как это на одно вычисление меньше, которое вам придется выполнять для каждого образца.
Рассчитайте разницу для каждого образца:
Вы хотите умножить текущий выбранный кватернион на начало/центр (в обратной форме).
Примечание. Помните, что умножение не является коммутативным с кватернионами, поэтому порядок имеет значение(!)
var currentQ = e.Reading.Orientation;
var q = Quaternion.Multiply(originQ, currentQ);
Преобразуйте свой локализованный кватернион
Итак, теперь у вас есть локализованный кватернион, который вы можете преобразовать в Vector3 (преобразовать его по базовому вектору (вверх, вперед, вниз,...) или получить некоторые углы Эйлера или...
Пример:
Итак, используя пример Xamarin Essentials, я бы изменил событие OrientationSensor_ReadingChanged
в качестве очень быстрого примера.
Примечание. Событие выборки называется A 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;
});
});
}
Примечание. Просто подключите свою любимую процедуру кватерниона к углам Эйлера (и при желании напишите процедуру сглаживания и дросселирования).
Выход:
person
SushiHangover
schedule
06.02.2019