Windows 10 の新しいセンサー機能

※本ブログは Building Apps for Windows "New sensor features in Windows 10”の抄訳です。

Windows 10 では、複数の新しいセンサー機能と革新技術を導入し、変更が施されています。前回のブログ投稿では、アクティビティセンサー、歩数計、気圧計、近接センサーなど、新しいコンテキスト センシング (英語) 機能について説明しました。この投稿では、Windows 10 に追加された 3 つのセンサー機能「センサーのバッチ処理」、「ReadingTransform」、「カスタムセンサー」について概説します。

センサーのバッチ処理

「睡眠モニター アプリの開発に着手したが、電力の消費量が気になる」という場合に有効なソリューションを紹介します。Windows 10 では、加速度計用のセンサーのバッチ処理機能を導入しました。センサーのバッチ処理とは、個々のセンサー サンプルを連続配信するのではなく、センサー ハードウェアにバッファーして一括配信するというバッチ処理機能を実現するセンサーのことです。センサーのバッチ処理を使うと、アプリケーションプロセッサは常時起動してデータを受信するたびにサンプルを処理する必要がなく、センサー サンプルをまとめて受信できるため起動頻度が減り、電力消費を抑えることができます。

連続配信とバッチ処理配信のそれぞれで、データがどのように収集されて配信されるかを下図に示します。

 

1_sensorBatch

バッチ処理対応になったことで、加速度計には 2 つのプロパティが追加されています。

  1. MaxBatchSize (英語): センサーがキャッシュできる最大イベント数です。この数に達すると、イベントは強制的に送信されます。このプロパティの値が 0 の場合、センサーはバッチ処理をサポートしません。バッチ処理の FIFO は複数のセンサーで共有されることがあるため、実際のサイズはこの数値よりも小さくなる可能性があります。
  2. ReportLatency (英語) : 待機時間を調整することで、センサーがバッチ処理を行う頻度をアプリケーションが制御できるようにします。任意のアプリケーションでこのプロパティが設定されると、センサーは指定された間隔でデータを送信します。ReportInterval プロパティを設定すると、指定した待機時間中に累積されるデータ量を制御できます。このプロパティは、アプリケーションでも、バッチ処理をサポートするセンサーでも設定を省略できます。

重要なポイントは、次のとおりです。

  • バッチ処理は、ワークフローのほとんどがバックグラウンドで処理され、フォアグラウンドまたは画面上での操作が限られている場合にお勧めです。
  • ReportLatency プロパティの最大値は MaxBatchsize に ReportInterval をかけた値です。それよりも大きな値を指定すると、データの喪失を防ぐため、最大のレポート待機時間が使用されます。
  • MaxBatchsize の値が 0 の場合、センサーはバッチ処理をサポートしません。
  • 複数のアプリケーションがそれぞれ異なる待機時間を設定する可能性がありますが、その場合は最短の待機期間が使用されます。

API パターンを以下に示します。

 // アプリの目的に適していて、センサーがサポートする、レポート間隔とレポート待機時間を選択します。
// この値は、後でセンサーをアクティブにするために使用します。
uint32 minReportInterval = accelerometer->MinimumReportInterval;
desiredReportInterval = minReportInterval > 16 ? minReportInterval : 16;
 
// 加速度計がバッチ処理をサポートしない場合、MaxBatchSize は 0 になります。
uint32 maxSupportedLatency = desiredReportInterval * accelerometer->MaxBatchSize;
desiredReportLatency = maxSupportedLatency < 10000 ? maxSupportedLatency : 10000;
 
// レポート間隔を確立します。
accelerometer->ReportInterval = desiredReportInterval;
 
// レポート待機時間を確立します。加速度計がバッチ処理をサポートしない場合は、操作なしになります。
accelerometer->ReportLatency = desiredReportLatency;

バッチ処理用に導入された新しいプロパティの説明を含む、加速度計の詳細な API リファレンスについては、こちらをご覧ください。また、UWP SDK サンプルは、こちら (英語) をご覧ください。

ReadingTransform プロパティ

目的の画面の向きにアプリを合わせようとして苦労したことはありませんか。Windows 10 UWP API を使用すると、コードを 1 行変更するだけで、簡単に画面の向きにアプリを合わせられるようになりました。

ここでは、そのことについてもう少し詳しく、背景を併せて説明します。Windows デスクトップと Windows Phone では、センサーの座標系の定義が異なります。このため、センサーデータの座標を画面の向きに合わせるには、大量のコードを記述する必要がありました。

ほとんどのセンサー (加速度計、ジャイロスコープ、磁力計など) のデータは、X、Y、Z 軸の測定値で構成されています。これは、センサーがシステムにどのように組み込まれているかによって決まります。

横長の向きが基本のデバイスでは、X 軸をデバイスの長辺に合わせ、Y 軸を短辺に合わせて、センサーを組み込んでいます。Z 軸は画面に対して垂直です。

2_landscapeFamily

一方、縦長の向きが基本のデバイスでは、X 軸をデバイスの短辺に合わせ、Y 軸を長辺に合わせて、センサーを組み込んでいます。Z 軸が画面に対して垂直であることは変わりません。

3_portaitFamily

その結果、画面の向きに合わせてセンサー データを変換しなければならなくなくなるため、アプリを複数のデバイスで実行するには複雑な処理が必要でした。Windows 10 では、センサー データを合わせる画面の向きを指定できる ReadingTransform という新しいプロパティを導入しました。

その結果、次の作業が簡単に行えるようになりました。

  • UWP アプリを指定した画面の向きに合わせ、デスクトップ、電話、Xbox、HoloLens、SurfaceHub、IoT を含むすべての Windows 10 デバイスで実行可能にする。
  • 既存のデスクトップまたは Windows Phone アプリを、複数のデバイス ファミリで実行できる UWP アプリに変換する。

以下は、これを実現するために必要な C++ のサンプルのコード変更です。このコードでは、加速度計を例にしています。

 void Scenario4_OrientationChanged::OnOrientationChanged(Windows::Graphics::Display::DisplayInformation ^sender, Platform::Object ^args)
{
    if (nullptr != accelerometer)
    {
        accelerometer->ReadingTransform = sender->CurrentOrientation;
    }
}

詳細については、ここ (英語) をクリックして Github で完全なサンプルをご覧ください。

重要なポイントは、次のとおりです。

  • Accelerometer のほか、GyroscopeMagnetometerCompassOrientationInclinometerSimpleOrientation も ReadingTransform プロパティをサポートします。
  • アプリは、想定している向きに合わせて値を初期化する必要があります。横長の向きのデバイスを想定したアプリを開発している場合は、初期値を Landscape に設定します。
  • アプリは OrientationChanged コールバックに登録し、画面やモニターの向きが変更されたら通知を受け取るように必要もあります。

カスタム センサー

Windows 10 から、ハードウェア メーカーがファースト クラス表現を持たない新しい種類のセンサー (大気質センサー、温度センサー、心拍数センサーなど) を追加できるようになりました。カスタム センサーのジェネリック API を利用することで、ハードウェア メーカーは任意の種類のセンサーを公開でき、Microsoft の OS リリース サイクルに合わせることなくセンサーをリリースできます。カスタム センサー用に Win32 センサー API を使用しているパートナーは、ハードウェアの変更もローレベル HID を使った複雑な処理も必要なく、Windows ストア アプリを開発できるようになりました。

重要なポイントは、次のとおりです。

  • カスタム センサー用の新しい名前空間 Windows.Devices.Sensors.Custom が追加されました。
  • 他のセンサー クラス (Accelerometer、Gyroscope、Magnetometer など) と同様にモデリングされた新しいクラス CustomSensor、CustomSensorReadingChangeEventArgs、CustomSensorReading が定義されました。
  • CustomSensorReading クラスには、キーと値の組のリスト プロパティがあります。このプロパティには、センサーのドライバーから UWP アプリに送信されたカスタム データが保持されます (キーは PROPERTYKEY を表す文字列で、値は整数/ブール値/浮動小数点値/倍精度浮動小数点値のいずれかです)。
  • CustomSensor クラスは、他のネイティブ センサー クラスと同じイベント メカニズムを再利用しています。
  • CustomSensor クラスも、他のネイティブ センサー クラスと同じ共通プロパティ (DeviceId、ReportInterval) を再利用しています。

API パターンを以下に示します。

 // 次の ID はベンダーが定義し、カスタム センサーの種類ごとに一意です。各カスタム センサー ドライバーは、一意の ID を 1 つ定義します。
//
// 下の ID は SDK に含まれているカスタム センサー ドライバー サンプルで定義されています。これは、カスタム センサーの CO2 エミュレーション サンプル ドライバーの ID です。
Guid GUIDCustomSensorDeviceVendorDefinedTypeID = new Guid("4025a865-638c-43aa-a688-98580961eeae");
 
// プロパティ キーは、カスタム センサー ドライバーが公開する DataField プロパティごとにベンダーが定義します。プロパティ キーは
// カスタム センサー ドライバーごとに定義し、カスタム センサーの種類ごとに一意です。
//
// 次の例は、WDK に含まれている CO2 エミュレーション カスタム センサーのドライバー サンプルで定義されている CO2 レベルを表すプロパティ キーです。
// この例では 1 つのキーしか定義していませんが、他のドライバーではプロパティ キー インデックスを増やして、複数のキーを定義している場合があります。
const String CO2LevelKey = "{74879888-a3cc-45c6-9ea9-058838256433} 1";
 
// メイン ページに戻るポインターです。NotifyUser() など MainPage でメソッドを呼び出す必要がある場合に必要になります。
 
MainPage rootPage = MainPage.Current;
 
private CustomSensor customSensor;
private uint desiredReportInterval;
private DeviceWatcher watcher;
 
public Scenario1_DataEvents()
{
    String customSensorSelector = "";
 
    this.InitializeComponent();
 
    customSensorSelector = CustomSensor.GetDeviceSelector(GUIDCustomSensorDeviceVendorDefinedTypeID);
    watcher = DeviceInformation.CreateWatcher(customSensorSelector);
    watcher.Added += OnCustomSensorAdded;
    watcher.Start();
 
    /// Invoked when the device watcher finds a matching custom sensor device
    /// </summary>
    /// <param name="watcher">device watcher</param>
    /// <param name="customSensorDevice">device information for the custom sensor that was found</param>
    private async void OnCustomSensorAdded(DeviceWatcher watcher, DeviceInformation customSensorDevice)
    {
            try
            {
                customSensor = await CustomSensor.FromIdAsync(customSensorDevice.Id);
            }
            catch(Exception e)
            {
                await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                {
                    rootPage.NotifyUser("The user may have denied access to the custom sensor. Error: " + e.Message, NotifyType.ErrorMessage);
                });
            }
    }
}

詳細な API リファレンスについては、こちら (英語) をご覧ください。UWP SDK サンプルは、こちら (英語) をご覧ください。

新しい Windows 10 のセンサー機能の詳細をお知りになりたい場合は、Build 2015 でのセンサー関連のセッション (英語) をご覧ください。バグや問題を見つけた場合は、Windows フィードバック ツールまたは MSDN フォーラムをご利用ください。新しく追加を希望する機能がある場合は、UserVoice (英語) からご意見をお寄せください。または、以下でコメントしてください。