Датчик угла наклона в WinRT
139Разработка под Windows 10 --- Датчик угла наклона
Класс датчика угла наклона Inclinometer — один из двух классов, объединяющих показания акселерометра и компаса с некоторым сглаживанием результата. Класс предоставляет информацию в форме углов тангажа (pitch), крена (roll) и отклонения (yaw) — термины позаимствованы в области динамики полета. У летящего самолета отклонение определяет направление, в котором обращен нос. Отклонение изменяется при повороте самолета влево или вправо. Тангаж определяет угол носа самолета относительно горизонтали. Он изменяется при подъеме или опускании носа с целью набора или потери высоты. Крен достигается наклоном корпуса влево или вправо.
Чтобы понять, какое отношение эти углы имеют к компьютеру, представьте, что вы летите на своем планшете, как на ковре-самолете. Вы сидите на экране лицом к верхнему краю (в основной ориентации планшета, конечно). В системе координат, приведенной ранее, отклонение определяет величину поворота по оси Z, тангаж — по оси X, а крен — по оси Y.
Программа YawPitchRoll также помогает наглядно представить эти углы. Файл XAML содержит элементы Rectangle, используемые для рисования линий, элементы Ellipse для рисования шариков, а также текстовые элементы:
<Page ...>
<Grid Background="#FFFFFFFF">
<!-- Тангаж -->
<Rectangle Width="3" Fill="Blue"
HorizontalAlignment="Center"
VerticalAlignment="Stretch" />
<Path Name="pitchPath"
Stroke="Blue">
<Path.Data>
<EllipseGeometry x:Name="pitchEllipse" RadiusX="20" RadiusY="20" />
</Path.Data>
</Path>
<!-- Крен -->
<Rectangle Height="3" Fill="Red"
HorizontalAlignment="Stretch"
VerticalAlignment="Center" />
<Path Name="rollPath" Stroke="Red" Fill="Red">
<Path.Data>
<EllipseGeometry x:Name="rollEllipse" RadiusX="20" RadiusY="20" />
</Path.Data>
</Path>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<!-- Тангаж -->
<TextBlock Text="PITCH" Foreground="Blue"
HorizontalAlignment="Right" Margin="0 0 24 0" />
<TextBlock Name="pitchValue" Grid.Column="1"
Foreground="Blue" HorizontalAlignment="Left" Margin="24 0 0 0" />
<!-- Крен -->
<TextBlock Text="ROLL" Grid.Row="1"
Foreground="Red" HorizontalAlignment="Left"
VerticalAlignment="Top" Margin="0 108 0 0">
<TextBlock.RenderTransform>
<RotateTransform Angle="-90" />
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock Name="rollValue"
Grid.Row="0"
Grid.Column="0"
Foreground="Red"
HorizontalAlignment="Left"
VerticalAlignment="Bottom">
<TextBlock.RenderTransform>
<RotateTransform Angle="-90" />
</TextBlock.RenderTransform>
</TextBlock>
<!-- Отклонение -->
<Grid Grid.Column="1" HorizontalAlignment="Stretch"
RenderTransformOrigin="0 1" VerticalAlignment="Bottom">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center">
<TextBlock Text="YAW = " Foreground="Green" />
<TextBlock Name="yawValue" Foreground="Green" />
</StackPanel>
<Rectangle Height="3" Fill="Green"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom" />
<Grid.RenderTransform>
<TransformGroup>
<RotateTransform Angle="-90" />
<RotateTransform x:Name="yawRotate" />
</TransformGroup>
</Grid.RenderTransform>
</Grid>
</Grid>
</Grid>
</Page>
Как мы видим из файла фонового кода, в области создания и использования экземпляров класс Inclinometer мало чем отличается от Accelerometer и Compass:
using System;
using Windows.Devices.Sensors;
using Windows.Foundation;
using Windows.Graphics.Display;
using Windows.UI.Core;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace WinRTTestApp
{
public sealed partial class MainPage : Page
{
Inclinometer inclinometer = Inclinometer.GetDefault();
public MainPage()
{
this.InitializeComponent();
DisplayProperties.AutoRotationPreferences =
DisplayProperties.NativeOrientation;
Loaded += OnMainPageLoaded;
}
private async void OnMainPageLoaded(object sender,
RoutedEventArgs e)
{
if (inclinometer == null)
{
await new MessageDialog("Датчик угла наклона не поддерживается").ShowAsync();
}
else
{
ShowYawPitchRoll(inclinometer.GetCurrentReading());
inclinometer.ReportInterval = inclinometer.MinimumReportInterval;
inclinometer.ReadingChanged += OnInclinometerReadingChanged;
}
}
private async void OnInclinometerReadingChanged(Inclinometer sender,
InclinometerReadingChangedEventArgs e)
{
await this.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal, () =>
{
ShowYawPitchRoll(e.Reading);
});
}
private void ShowYawPitchRoll(InclinometerReading inclinometerReading)
{
if (inclinometerReading == null)
return;
double yaw = inclinometerReading.YawDegrees;
double pitch = inclinometerReading.PitchDegrees;
double roll = inclinometerReading.RollDegrees;
yawValue.Text = yaw.ToString("F0") + "°";
pitchValue.Text = pitch.ToString("F0") + "°";
rollValue.Text = roll.ToString("F0") + "°";
yawRotate.Angle = yaw;
if (pitch <= 90 && pitch >= -90)
{
pitchPath.Fill = pitchPath.Stroke;
pitchEllipse.Center = new Point(this.ActualWidth / 2,
this.ActualHeight * (pitch + 90) / 180);
}
else
{
pitchPath.Fill = null;
if (pitch > 90)
pitchEllipse.Center = new Point(this.ActualWidth / 2,
this.ActualHeight * (270 - pitch) / 180);
else // pitch < -90
pitchEllipse.Center = new Point(this.ActualWidth / 2,
this.ActualHeight * (-90 - pitch) / 180);
}
rollEllipse.Center = new Point(this.ActualWidth * (roll + 90) / 180,
this.ActualHeight / 2);
}
}
}
Нет никакого «скрытого компаса», поставляющего информацию датчику угла наклона. Свойство YawDegrees так же ненадежно, как и показания компаса, хотя на самом деле они дополняют друг друга: сумма YawDegrees и показаний Compass всегда равна приблизительно 360. Когда планшет лежит экраном вверх на плоской поверхности, линия отклонения указывает на север (или в его окрестности), а шарики тангажа и крена находятся в центре. Если наклонить верхний край планшета вверх или вниз, PitchDegrees изменяется в диапазоне от 90° (планшет стоит вертикально) до -90° (планшет перевернут «вниз головой»). Значение RollDegrees изменяется в диапазоне от 90° до -90° при наклоне планшета вправо или влево. Вот как выглядит приложение, если приподнять левую и верхнюю стороны планшета:
Если устройство лежит экраном вниз, YawDegrees указывает на юг, a PitchDegrees принимает значения в диапазоне от 90° до 180°, и от -90° до -180°. В программе эти значения представлены красным шариком.
Если в вашей программе по экрану летает какой-нибудь объект, этих углов может быть достаточно. Однако может оказаться, что вам нужны более математически-ориентированные данные. Для этих целей и предназначен датчик ориентации в трехмерном пространстве, который мы обсудим в следующей статье.