Опубликован: 01.11.2011 | Уровень: специалист | Доступ: платный
Практическая работа 17:

Работа с акселерометром (Silverlight)

Аннотация: Устройства Windows Phone 7 имеют аппаратное устройство, измеряющее силу, пропорциональную ускорению. Для работы с акселерометром используется библиотека Microsoft.Devices.Sensors. Для считывания показаний прибора нужно создать экземпляр класса Accelerometer, задать обработчик события ReadingChanging и вызвать метод Start. В данной работе мы создадим обработчик событий, использующий разные свойства класса Accelerometer.

Дополнительные материалы к занятию можно скачать здесь.

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

Устройства, совместимые с Windows Phone, имеют акселерометр, измеряющий силу, пропорциональную ускорению. Если телефон неподвижен, то акселерометр регистрирует силу притяжения, т.е. позволяет определить положение телефона относительно земли.

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

Выходные данные акселерометра удобно представить в виде трехмерного вектора. Вектор ускорения может быть обозначен так: (х, у, z). В XNA есть тип трехмерный вектор, в Silverlight нет.

Тогда как три координаты (х, у, z) точно определяют точку в пространстве, вектор (х,у, z) обозначает направление и величину. Очевидно, что точка и вектор взаимосвязаны. Направление вектора (х, у, z) - это луч из точки (0, 0, 0) в точку (х, у, z). Но вектор это направление этого отрезка.

Модуль вектора (x,y, z)определяется по теореме Пифагора:

\text{Модуль }=\sqrt{x^2+y^2+z^2}

При работе с акселерометром оси трехмерной системы координат направляют следующим образом: положительное направление оси Y проходит вдоль максимального размера телефона снизу (где располагаются кнопки) вверх, положительное направление оси X - слева направо. Ось Z направлена перпендикулярно телефону, прямо на пользователя (Чарльз Петзолд, 2010).

Когда телефон неподвижен, вектор акселерометра указывает на землю. Модуль равен 1, т.е. \lg^{10}, что соответствует силе притяжения на поверхности земли. Когда телефон расположен вертикально, вектор ускорения - (0, -1, 0), т.е. направлен прямо вниз.

Если повернуть телефон на 90° против часовой стрелки (так называемое левостороннее альбомное расположение), то вектор ускорения станет равным (-1, 0, 0), при повороте телефона "вверх ногами" - вектор станет (0, 1, 0), еще один поворот на 90° против часовой стрелки обеспечивает правостороннее альбомное расположение и вектор ускорения равный (1, 0, 0). Положите телефон на стол экраном вверх, и вектор ускорения будет (0, 0, -1). (Эмулятор Windows Phone 7 всегда возвращает это значение) (Чарльз Петзолд, 2010).

Далее, мы разработаем приложение, моделирующее работу акселерометра. Желающих ознакомиться с подробностями работы программы мы отсылаем к [25](Петзольд, 2010).

Создаем новое приложение Practice_17 Silverlight Windows Phone 7.

Добавляем ссылку на библиотеку Microsoft.Device.Sensors.


MainPage.xaml:

<phone:PhoneApplicationPage 
    x:Class="Practice_17.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">

    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="Silverlight" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="Акселерометр" Margin="9,-7,0,0" 
Style="{StaticResource PhoneTextTitle1Style}" FontSize="64" />
        </StackPanel>

        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <TextBlock Name="txtblk" HorizontalAlignment="Center" VerticalAlignment="Center" />
        </Grid>
    </Grid>
 
</phone:PhoneApplicationPage>
    

В файле кода MainPage.xaml.cs вводим следующую программу:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Devices.Sensors;

namespace Practice_17
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        public MainPage()
        {
            InitializeComponent();
            InitializeComponent();
            Accelerometer acc = new Accelerometer();
            acc.ReadingChanged += OnAccelerometerReadingChanged;

            try
            {
                acc.Start();
            }
            catch (Exception exc)
            {
                txtblk.Text = exc.Message;
            }
        }

        delegate void SetTextBlockTextDelegate(TextBlock txtblk, string text);

        void SetTextBlockText(TextBlock txtblk, string text)
        {
            txtblk.Text = text;
        }

        void OnAccelerometerReadingChanged(object sender, AccelerometerReadingEventArgs args)
        {
            string str = String.Format("X = {0:F2}\n" +
            "Y = {1:F2}\n" +
            "Z = {2:F2}\n\n" +
            "Magnitude = {3:F2}\n\n" +
            "{4}",
            args.X, args.Y, args.Z,
            Math.Sqrt(args.X * args.X + args.Y * args.Y +
            args.Z * args.Z),
            args.Timestamp);

            if (txtblk.CheckAccess())
            {
                txtblk.Text = str;
            }
            else
            {
                txtblk.Dispatcher.BeginInvoke(delegate()
                {
                    txtblk.Text = str;
                });
            }
        }
    }

}
    
Листинг .

Получаем результат:

Как уже говорилось выше, при работе с эмулятором Windows Phone 7 предполагается, что телефон лежит на столе, поэтому мы получаем значения вектора ускорения (0, 0, -1).

Игорь Белов
Игорь Белов
Россия, г. Ейск
Александр Гринёв
Александр Гринёв
Украина, Днепропетрвск, Шаг