Положение датчиков в пространстве

Данные датчиков из классов Accelerometer, Gyrometer, Compass, Inclinometer и OrientationSensor определяются по их опорным осям. Эти оси определяются опорным кадром устройства и поворачиваются вместе с устройством, когда пользователь поворачивает последнее. Если ваше приложение поддерживает автоматический поворот и автоматически меняет ориентацию, когда пользователь поворачивает устройство, необходимо скорректировать данные датчиков для поворота до начала его использования.

Важные API

Ориентация дисплея и ориентация устройства

Чтобы получить представление об опорных осях для датчиков, необходимо понимать разницу между ориентацией дисплея и ориентацией устройства. Ориентация дисплея — это направление, в котором на экране отображаются текст и изображения, а ориентация устройства — это его физическое положение.

Примечание

Положительная ось Z выходит за пределы экрана устройства, как показано на следующем рисунке. Ось Z для ноутбука

На следующих схемах ориентация устройства и дисплея находятся в альбомной ориентации (показанные ося датчика относятся к альбомной ориентации).

На этой схеме показана ориентация экрана и устройства в альбомной ориентации.

Альбомная ориентация дисплея и устройства

На следующей схеме показана ориентация дисплея и устройства в альбомной диаграмме LandscapeFlipped.

Альбомная (перевернутая) ориентация дисплея и устройства

На последней схеме показана ориентация отображения в альбомной ориентации, а ориентация устройства — LandscapeFlipped.

Дисплей в альбомной ориентации, а устройство — в альбомной (перевернутой)

Можно запросить значения ориентации при помощи класса DisplayInformation, используя метод GetForCurrentView со свойством CurrentOrientation. Затем можно создать логику путем сравнения с перечислением DisplayOrientations. Следует помнить, что для каждой поддерживаемой ориентации необходимо предусмотреть преобразование опорных осей.

Устройства с преимущественно альбомной и преимущественно книжной ориентацией

Изготовители создают устройства как с преимущественно альбомной, так и с преимущественно книжной ориентацией. Опорный кадр различается в зависимости от преимущественной ориентации устройств: альбомной, как у настольных компьютеров и ноутбуков, или книжной, как у телефонов и некоторых планшетов. В следующей таблице представлены оси датчиков для устройств обоих видов.

Ориентация Преимущественно альбомная Преимущественно книжная
Альбомная Устройства с преимущественно альбомной ориентацией в альбомной ориентации Устройства с преимущественно книжной ориентацией в альбомной ориентации
Книжная Устройства с преимущественно альбомной ориентацией в книжной ориентации Устройства с преимущественно книжной ориентацией в книжной ориентации
LandscapeFlipped Устройства с преимущественно альбомной ориентацией в альбомной (перевернутой) ориентации Устройства с преимущественно книжной ориентацией в альбомной (перевернутой) ориентации
PortraitFlipped Устройства с преимущественно альбомной ориентацией в книжной (перевернутой) ориентации Устройства с преимущественно книжной ориентацией в книжной (перевернутой) ориентации

Устройства, транслирующие изображение, и устройства без монитора

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

Кроме того, некоторые устройства не имеют дисплея. Для этих устройств ориентация по умолчанию — книжная.

Ориентация экрана и направление по компасу

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

Ориентация экрана Опорная ось для направления по компасу Направление по компасу, когда пользователь стоит лицом к северу, согласно API (преимущественно альбомная) Направление по компасу, когда пользователь стоит лицом к северу, согласно API (преимущественно книжная) Компенсация отклонения компаса (преимущественно альбомная) Компенсация отклонения компаса (преимущественно книжная)
Альбомная -Z 0 270 Направление (Направление + 90) % 360
Книжная Да 90 0 (Направление + 270) % 360 Направление
LandscapeFlipped Z 180 90 (Направление + 180) % 360 (Направление + 270) % 360
PortraitFlipped Да 270 180 (Направление + 90) % 360 (Направление + 180) % 360

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

private void ReadingChanged(object sender, CompassReadingChangedEventArgs e)
{
    double heading = e.Reading.HeadingMagneticNorth;
    double displayOffset;

    // Calculate the compass heading offset based on
    // the current display orientation.
    DisplayInformation displayInfo = DisplayInformation.GetForCurrentView();

    switch (displayInfo.CurrentOrientation)
    {
        case DisplayOrientations.Landscape:
            displayOffset = 0;
            break;
        case DisplayOrientations.Portrait:
            displayOffset = 270;
            break;
        case DisplayOrientations.LandscapeFlipped:
            displayOffset = 180;
            break;
        case DisplayOrientations.PortraitFlipped:
            displayOffset = 90;
            break;
     }

    double displayCompensatedHeading = (heading + displayOffset) % 360;

    // Update the UI...
}

Ориентация экрана с использованием акселерометра и гирометра

В следующей таблице приведено преобразование данных акселерометра и гирометра для ориентации экрана.

Опорные оси X Да Z
Альбомная X Да Z
Книжная Да -X Z
LandscapeFlipped -X -y Z
PortraitFlipped -y X Z

В следующем примере кода эти преобразования применяются к гирометру.

private void ReadingChanged(object sender, GyrometerReadingChangedEventArgs e)
{
    double x_Axis;
    double y_Axis;
    double z_Axis;

    GyrometerReading reading = e.Reading;  

    // Calculate the gyrometer axes based on
    // the current display orientation.
    DisplayInformation displayInfo = DisplayInformation.GetForCurrentView();
    switch (displayInfo.CurrentOrientation)
    {
        case DisplayOrientations.Landscape:
            x_Axis = reading.AngularVelocityX;
            y_Axis = reading.AngularVelocityY;
            z_Axis = reading.AngularVelocityZ;
            break;
        case DisplayOrientations.Portrait:
            x_Axis = reading.AngularVelocityY;
            y_Axis = -1 * reading.AngularVelocityX;
            z_Axis = reading.AngularVelocityZ;
            break;
        case DisplayOrientations.LandscapeFlipped:
            x_Axis = -1 * reading.AngularVelocityX;
            y_Axis = -1 * reading.AngularVelocityY;
            z_Axis = reading.AngularVelocityZ;
            break;
        case DisplayOrientations.PortraitFlipped:
            x_Axis = -1 * reading.AngularVelocityY;
            y_Axis = reading.AngularVelocityX;
            z_Axis = reading.AngularVelocityZ;
            break;
     }

    // Update the UI...
}

Ориентация экрана и ориентация устройства

Данные OrientationSensor необходимо изменять по-другому. Эти различные ориентации можно рассматривать как повороты против часовой стрелки по оси Z, поэтому нам нужно обратить вспять поворот, чтобы вернуть ориентацию пользователя. Для данных кватерниона можно использовать формулу Эйлера, чтобы определить поворот с опорным кватернионом. Можно также использовать опорную матрицу вращения.

Формула Эйлера

Чтобы получить желаемую относительную ориентацию, умножьте опорный объект на абсолютный объект. Обратите внимание, что эта формула не обладает свойством коммутативности.

Умножение опорного объекта на абсолютный объект

В предыдущем выражении абсолютный объект возвращается данными датчика.

Ориентация экрана Поворот против часовой стрелки вокруг оси Z Опорный кватернион (поворот в противоположном направлении) Опорная матрица вращения (поворот в противоположном направлении)
Альбомная 0 1 + 0i + 0j + 0k [1 0 0
0 1 0
0 0 1]
Книжная 90 cos(-45⁰) + (i + j + k)*sin(-45⁰) [0 1 0
-1 0 0
0 0 1]
LandscapeFlipped 180 0 - i - j - k [1 0 0
0 1 0
0 0 1]
PortraitFlipped 270 cos(-135⁰) + (i + j + k)*sin(-135⁰) [0 -1 0
1 0 0
0 0 1]

См. также раздел

Интеграция датчиков движения и ориентации