電子コンパスを利用して端末の方角を取得する


WindowsPhone7.5から新たに電子コンパス情報を取得するためのAPIが追加されました。
本エントリでは、電子コンパスの情報から端末の方角を取得する方法を紹介します。

参照とusingの追加

電子コンパスを利用するために使うクラスはMicrosoft.Devices.Sensors.Compassクラスです。
Compassクラスは、標準の環境では参照が足りずusingを追加することができませんのでプロジェクト→参照の追加よりMicrosoft.Devices.Sensorsを追加しましょう。
参照の追加後、以下のusingを追加します。

using Microsoft.Devices.Sensors;

電子コンパスの存在チェック

電子コンパスはセンサーであり、将来的にはすべてのWindowsPhone端末に載ることがなくなるかもしれません。
そのため、電子コンパスが使用可能であるかのチェックを行う必要があります。

サンプルでは、MainPageのコンストラクタ内で電子コンパスの使用可否をチェックしています。
使用可否のチェックには、CompassクラスのIsSupportedプロパティを使用します。
プロパティがfalseを返す場合、その端末は電子コンパスをサポートしていません。
以下に該当部分のソースコードを引用します。
電子コンパスが利用できない場合には、電子コンパスの情報を取得開始するためのボタンをdisable状態に変更しています。

        public MainPage()
        {
            InitializeComponent();
            // コンパスセンサーの利用可能チェック
            if (!Microsoft.Devices.Sensors.Compass.IsSupported)
            {
                textBlock1.Text = "this device does not support compass-senssor";
                // コンパスデータ取得ボタンをdisableに
                button1.IsEnabled = false;
            }
        }

5行目でコンパスの使用可否チェックを行っています。
使用が出来なかった場合には、9行目で取得ボタンをdisable状態にしています。

電子コンパスの設定

電子コンパスを使用するための準備を行います。
電子コンパスのデータ取得開始には、CompassクラスのStartメソッドを利用しますが、Startメソッドの呼び出し前に「コンパス情報の更新間隔」と「コンパス情報の変動時に呼び出されるコールバックメソッド」の設定が必要です。

コンパス情報の更新間隔の設定にはTimeBetweenUpdatesプロパティを、
コールバックの登録にはCurrentValueChangedプロパティを使用し設定します。
また、Startメソッドを呼び出した後は更新間隔に設定した間隔で常時コンパス情報を取得することになります。
必要に応じてStopメソッドを呼び出し、取得停止を行うようにしましょう。

以下に該当部分のソースコードを引用します。
サンプルでは、該当部分はボタン押下時のコールバックメソッド内に記載しています。
また、画面遷移時(Pageから離れる時)に呼び出されるOnNavigateFromメソッド内でStopメソッドを呼び出しています。

        private void button1_Click(object sender, RoutedEventArgs e)
        {

            // コンパスセンサーの設定
            compass = new Compass();
            compass.TimeBetweenUpdates = TimeSpan.FromMilliseconds(100);
            compass.CurrentValueChanged += compass_ValueChanged;

            // コンパスセンサーのデータ取得開始
            compass.Start();

        }

       protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
        {
            // コンパスのデータ取得停止
            if (compass != null)
            {
                compass.Stop();
            }
        }

6行目で更新間隔を100msecに設定し、7行目でコールバックメソッドを設定しています。
compass_ValueChangedメソッドについては後述します。
10行目でStartメソッドを呼び出し、コンパス情報の取得を開始しています。

情報の取得

Startメソッドをコールし、コンパス情報の取得が開始されると、登録したコールバックメソッドが随時呼び出されます。

CurrentValueChangedプロパティに設定するコールバックメソッドのSensorReadingEventArgs型の引数から、電子コンパスの情報を取得できます。

取得できる情報は「地図上での北を基準にした角度(TrueHeading)」と「地磁気上の北を基準にした角度(MagneticHeading)」の二種類を取得できます。
サンプルではMagneticHeadingの情報のみを取得していますが、必要に応じて読み替えてください。

以下に該当部分のソースコードを引用します。
MagneticHeadingプロパティはDouble型の数であり、北を基準とした角度を示しています。
そのためサンプルでは、8方位を45度ずつに分配して各方位を算出しています。

       // コンパスの値が変かわったら呼びを出されるイベントハンドラ
        private void compass_ValueChanged(object sender, SensorReadingEventArgs e)
        {
            Dispatcher.BeginInvoke(delegate()
            {
                var v = e.SensorReading.MagneticHeading;
                string direction = "方角";

                if ((0                 {
                    direction = "北";
                }
                else if (22.5                 {
                    direction = "北東";
                }
                else if ((90 - 22.5)                 {
                    direction = "東";
                }
                else if ((135 - 22.5)                 {
                    direction = "南東";
                }
                else if ((180 - 22.5)                 {
                    direction = "南";
                }
                else if ((225 - 22.5)                 {
                    direction = "南西";
                }
                else if ((270 - 22.5)                 {
                    direction = "西";
                }

                else if ((315 - 22.5)                 {
                    direction = "北西";
                }

                textBlock1.Text = direction + "  {" + e.SensorReading.MagneticHeading + "}";

            });
        }

6行目でMagneticHeadingプロパティの情報を取得し、9行目以降で方位の算出を行っています。