传感器方向

加速计、陀螺仪、指南针测斜仪OrientationSensor 类的传感器数据由参考轴定义。 这些轴由设备的参考帧定义,并在用户旋转时随设备旋转。 如果你的应用支持自动旋转并重新定位设备以适应用户旋转设备,则必须在使用它之前调整传感器数据以供旋转。

重要的 API

显示方向与设备方向

若要了解传感器的参考轴,需要区分显示方向与设备方向。 显示方向是方向文本,图像显示在屏幕上,而设备方向是设备的物理定位。

注意

正 z 轴从设备屏幕向外扩展,如下图所示。 笔记本电脑的 Z 轴

在下图中,设备和显示方向都采用 Landscape(所示的传感器轴特定于横向方向)。

此图显示了采用 Landscape 的显示和设备方向。

横向显示和设备方向

第二张图显示了采用 LandscapeFlipped 的显示和设备方向。

LandscapeFlipped 中的显示和设备方向

最后一张图显示了采用 Landscape 的显示方向和采用 LandscapeFlipped 的设备方向。

设备方向为 LandscapeFlipped 时在横向中显示方向

可以通过使用 GetForCurrentView 方法和 CurrentOrientation 属性通过 DisplayInformation查询方向值。 然后,可以通过与 DisplayOrientations 枚举进行比较来创建逻辑。 请记住,对于支持的每个方向,必须支持将引用轴转换为该方向。

横向优先与纵向优先设备

制造商既生产横向优先设备,又生产纵向优先设备。 参考帧因横向优先设备(如台式机和笔记本电脑)和纵向优先设备(如手机和某些平板电脑)而异。 下表显示了横向优先设备和纵向优先设备的传感器轴。

方向 横向优先 纵向优先
横向 横向优先设备 横向方向的纵向优先设备
纵向 纵向优先的横向设备 纵向优先设备
LandscapeFlipped LandscapeFlipped 方向中的横向优先设备 LandscapeFlipped 方向中的纵向优先设备
PortraitFlipped 纵向优先的横向设备 PortraitFlipped 方向中的纵向优先设备

设备广播显示器和无外设设备

某些设备能够将显示器广播到另一台设备。 例如,可以拍摄平板电脑并将显示器广播到将采用横向方向的投影仪。 在这种情况下,请务必记住设备方向基于原始设备,而不是显示显示器的设备方向。 因此,加速计将报告平板电脑的数据。

此外,某些设备没有显示器。 使用这些设备时,这些设备的默认方向为纵向。

显示方向和指南针标题

指南针标题取决于参考轴,因此它随设备方向变化。 根据此表进行补偿(假定用户正朝北)。

显示方向 指南针标题的参考轴 朝北时 API 指南针方向 (横向优先) 朝北时的 API 指南针方向 (纵向优先) 指南针标题补偿 (横向优先) 指南针标题补偿 (纵向优先)
横向 Z- 0 270 方位 (标题 + 90) % 360
纵向 Y 90 0 (标题 + 270) % 360 方位
LandscapeFlipped Z 180 90 (标题 + 180) % 360 (标题 + 270) % 360
PortraitFlipped Y 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 Y Z
横向 X Y Z
纵向 Y -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 轴时的不同方向,因此我们需要反向旋转以重新获取用户的方向。 对于四元数数据,可以使用 Euler 的公式通过引用四元数定义旋转,还可以使用引用旋转矩阵。

欧拉的公式

若要获取所需的相对方向,请将引用对象与绝对对象相乘。 请注意,此数学不是通勤的。

将引用对象与绝对对象相乘

在前面的表达式中,绝对对象由传感器数据返回。

显示方向 反时针旋转绕 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]

另请参阅

集成动作和方向传感器