方法: Windows Phone の加速度センサーからデータを取得する

2012/02/09

ここでは、加速度計のデータを数値とグラフィックで表示する加速度計アプリケーションの作成について説明します。

加速度センサーによって特定の時点でデバイスに加えられた力が測定されます。これらの力はユーザーがデバイスを動かしている方向を特定するのに使用できます。加速度値は、X、Y、および Z 軸の加速度成分 (重力単位) を表す 3 次元ベクトルとして表されます。加速度の方向はデバイスに対するもので、デバイスが水平なテーブル上で上向きになっている場合は Z 軸方向に -1g が加わり、デバイスがテーブル面に対して垂直になっている場合は Y 軸方向に -1g が加わります。

加速度センサーは、重力と、電話の動きによって生じるすべての力を検出します。複合モーション API (Motion クラスを使用してアクセス) は、複数のデバイスのセンサーを使用してデバイスの加速度から重力ベクトルを分離し、デバイスの現在の姿勢 (ヨー、ピッチ、およびロール) を決定します。

次の手順では、加速度計アプリケーションの作成方法ついて説明します。

加速度計アプリケーションを作成するには

  1. Visual Studio で、新しい Windows Phone アプリケーション プロジェクトを作成します。このテンプレートは、Silverlight for Windows Phone カテゴリにあります。

  2. このアプリケーションは、センサー API および XNA Framework を含むアセンブリを参照する必要があります。これは、加速度データが XNA Framework の Vector3 オブジェクトの形式で渡されるためです。[プロジェクト] メニューの [参照の追加] をクリックし、[Microsoft.Devices.Sensors] と [Microsoft.Xna.Framework] を選択し、[OK] をクリックします。

  3. MainPage.xaml ファイルで、"ContentPanel" というの名前の Grid 要素に次の XAML コードを配置します。このコードでは、2 つのボタンを作成します。1 つは加速度計からのデータ取得を開始するボタン、もう 1 つはそれを停止するボタンです。また、数値の読み取り値を表示するのに使用する 3 つの TextBlock 要素と、読み取りデータをグラフィカルに表現するのに使用する 3 つの Line 要素も作成されます。最後に、このコードは、アプリケーションの現在の状態を表示するのに使用されるステータス TextBlock 要素を追加します。

    <Button Content="Start" Height="72" HorizontalAlignment="Left" Margin="20,10,0,0" Name="startButton" VerticalAlignment="Top" Width="160" Click="startButton_Click" />
    <Button Content="Stop" Height="72" HorizontalAlignment="Right" Margin="0,10,20,0" Name="stopButton" VerticalAlignment="Top" Width="160" Click="stopButton_Click"/>
    <TextBlock Height="30" HorizontalAlignment="Left"  Margin="20,100,0,0" Name="xTextBlock" Text="X: 1.0" VerticalAlignment="Top" Foreground="Red" FontSize="28" FontWeight="Bold"/>
    <TextBlock Height="30" HorizontalAlignment="Center"  Margin="0,100,0,0" Name="yTextBlock" Text="Y: 1.0" VerticalAlignment="Top" Foreground="Green" FontSize="28" FontWeight="Bold"/>
    <TextBlock Height="30" HorizontalAlignment="Right"  Margin="0,100,20,0" Name="zTextBlock" Text="Z: 1.0" VerticalAlignment="Top"  Foreground="Blue" FontSize="28" FontWeight="Bold"/>
    <Line x:Name="xLine" X1="240" Y1="350" X2="340" Y2="350" Stroke="Red" StrokeThickness="4"></Line>
    <Line x:Name="yLine" X1="240" Y1="350" X2="240" Y2="270" Stroke="Green" StrokeThickness="4"></Line>
    <Line x:Name="zLine" X1="240" Y1="350" X2="190" Y2="400" Stroke="Blue" StrokeThickness="4"></Line>
    <TextBlock Height="30" HorizontalAlignment="Center" Margin="6,571,6,0" Name="statusTextBlock" Text="TextBlock" VerticalAlignment="Top" Width="444" />
    
    
    
  4. MainPage.xaml.cs 分離コード ページを開き、センサーと XNA Framework 名前空間の using ディレクティブを、ページの先頭にある他の using ディレクティブに追加します。

    using Microsoft.Devices.Sensors;
    using Microsoft.Xna.Framework;
    
    
  5. MainPage クラス定義の先頭で、Accelerometer 型の変数を宣言します。

    public partial class MainPage : PhoneApplicationPage
    {
      Accelerometer accelerometer;
    
    
  6. ページ コンストラクターで、アプリケーションが実行されているデバイスが加速度計センサーを備えているかどうかを調べます。すべてのデバイスがすべてのセンサーをサポートしているわけではないため、センサーを使用する前に必ず確認する必要があります。既存のページのコンストラクターを次のコードに置き換えます。

    // Constructor
    public MainPage()
    {
      InitializeComponent();
    
      if (!Accelerometer.IsSupported)
      {
        // The device on which the application is running does not support
        // the accelerometer sensor. Alert the user and disable the
        // Start and Stop buttons.
        statusTextBlock.Text = "device does not support accelerometer";
        startButton.IsEnabled = false;
        stopButton.IsEnabled = false;
      }
    }
    
    
  7. [Start (開始)] ボタンのクリック イベントのハンドラーを追加します。上記の XAML コードの追加方法によっては、Visual Studio でこのハンドラーが既に追加されている可能性があります。その場合は、ハンドラー内のコードを削除します。ハンドラーが自動的に追加されていない場合は、MainPage クラス定義に次の空の関数をコピーして貼り付けます。

    private void startButton_Click(object sender, RoutedEventArgs e)
    {
                
    }
    
    
    
  8. [Start (開始)] ボタンのクリック ハンドラーの中で、初期化されるまでは null であるはずの加速度計オブジェクトが null であるかどうかを調べます。加速度計が null の場合は、コンストラクターを使用して初期化します。次に、TimeBetweenUpdates プロパティを設定することにより、加速度計からデータを受け取る速さを設定します。既定値は 2 ミリ秒です。次に、CurrentValueChanged イベントのハンドラーを設定します。空の [Start (開始)] ボタンのクリック ハンドラー内に次のコードを貼り付けます。

      if (accelerometer == null)
      {
       // Instantiate the Accelerometer.
        accelerometer = new Accelerometer();
        accelerometer.TimeBetweenUpdates = TimeSpan.FromMilliseconds(20);
        accelerometer.CurrentValueChanged+=new EventHandler<SensorReadingEventArgs<AccelerometerReading>>(accelerometer_CurrentValueChanged);
      }
    
    
  9. ここで、Start()()()() メソッドを使用して加速度計を起動します。Start の呼び出しは失敗する可能性があるため、この呼出は try ブロックに入れる必要があります。加速度計を起動できなかった場合は、catch ブロックでそのことをユーザーに警告できます。前のコード セクションの後の [Start (開始)] ボタンのクリック ハンドラーに次のコードを貼り付けます。

      try
      {
        statusTextBlock.Text = "starting accelerometer.";
        accelerometer.Start();
      }
      catch (InvalidOperationException ex)
      {
        statusTextBlock.Text = "unable to start accelerometer.";
      }
    
    
  10. 次に、CurrentValueChanged イベント ハンドラーを実装します。このメソッドは、TimeBetweenUpdates に指定した頻度で、新しい加速度データに基づいてシステムから呼び出されます。ハンドラーは、加速度データを含む AccelerometerReading オブジェクトを受け取ります。このハンドラーは、UI へのアクセスのないバックグラウンド スレッドで呼び出されます。したがって、このイベント ハンドラーは、UI スレッドで指定したコードを呼び出す Dispatcher.Invoke メソッドを使用します。Dispatcher.Invoke を使用して、次の手順で定義する UpdateUI が呼び出され、AccelerometerReading オブジェクトが渡されます。

    void accelerometer_CurrentValueChanged(object sender, SensorReadingEventArgs<AccelerometerReading> e)
    {
      // Call UpdateUI on the UI thread and pass the AccelerometerReading.
      Dispatcher.BeginInvoke(() => UpdateUI(e.SensorReading));
    }
    
    
  11. 加速度データをユーザーに対して表示する UpdateUI メソッドを実装します。このメソッドは、データが受信中であることを示すため、最初にステータス TextBlock を更新します。次に、3 つの TextBlock オブジェクトが更新されて、センサーのそれぞれの軸について加速度が数値で示されます。最後に、加速度をグラフィカルに表すために Line オブジェクトが更新されます。

    private void UpdateUI(AccelerometerReading accelerometerReading)
    {
      statusTextBlock.Text = "getting data";
    
      Vector3 acceleration = accelerometerReading.Acceleration;
    
      // Show the numeric values.
      xTextBlock.Text = "X: " + acceleration.X.ToString("0.00");
      yTextBlock.Text = "Y: " + acceleration.Y.ToString("0.00");
      zTextBlock.Text = "Z: " + acceleration.Z.ToString("0.00");
    
      // Show the values graphically.
      xLine.X2 = xLine.X1 + acceleration.X * 200;
      yLine.Y2 = yLine.Y1 - acceleration.Y * 200;
      zLine.X2 = zLine.X1 - acceleration.Z * 100;
      zLine.Y2 = zLine.Y1 + acceleration.Z * 100;
    }
    
    
  12. 最後のステップでは、ユーザーが加速度計からのデータ取得を停止できる [Stop (停止)] ボタンのクリック ハンドラーを実装します。ここでも、エディターによってこのハンドラーが自動的に追加されている場合は、内容を次のように置き換えます。

    private void stopButton_Click(object sender, RoutedEventArgs e)
    {
      if (accelerometer != null)
      {
        // Stop the accelerometer.
        accelerometer.Stop();
        statusTextBlock.Text = "accelerometer stopped.";
      }
    }
    
    

実際の Windows Phone デバイスが手元にある場合は、アプリケーションをビルドして、デバイスに展開し、デバイスを動かして加速度データの変化を観察するだけです。Windows Phone Emulator を使用している場合は、加速度計エミュレーター ツールでアプリケーションをテストする必要があります。

加速度計エミュレーターを使用するには

  1. Visual Studio の標準ツールバーで、[Windows Phone プロジェクトの対象の選択] から [Windows Phone エミュレーター] を選択します。

  2. F5 キーを押すか、または [デバッグ] メニューの [デバッグ開始] をクリックします。

  3. エミュレーターが起動して加速度アプリケーションが読み込まれるのを待ちます。

  4. エミュレーターのツールバーで、2 つの矢印が右側を指しているアイコンの [その他のツール] をクリックします。

  5. [その他のツール] ウィンドウで、[加速度計] タブをクリックします。

  6. エミュレーターのメイン ウィンドウ内で、作成した加速度アプリケーションの [Start (開始)] をクリックします。

  7. [その他のツール] ウィンドウを囲むピンクの点を動かして仮想電話の向きを変更し、エミュレーターのメイン ウィンドウでデータの変化を観察します。

表示: