トップ回答者
Visualstudio + Accelerometer

質問
回答
-
空のプロジェクトから作成しているアプリケーションはコンソールだとかATLやMFCのデスクトップアプリケーションといった形式がありますが、どの形式で進めているのでしょうか。
たとえばコンソールアプリと以下のようにSensor APIで加速度センサの値を取得できました
#コードレシピの「[C++] Native Code (VC++) で Windows 7 Sensor API を使う」を加速度センサに書き換え
#include "stdafx.h" //#include "targetver.h" //#include <stdio.h> //#include <tchar.h> //#include <atlbase.h> // ATLを参照 //#include <atlstr.h> //#include <INITGUID.H> //#include <SensorsApi.h> //#include <sensors.h> //#include <iostream> class CSensorEventSink : public ISensorEvents { public: // ISensorEvents で定義されているイベント STDMETHOD(OnStateChanged)(ISensor* pSensor, SensorState state); STDMETHOD(OnLeave)(REFSENSOR_ID sensorID); STDMETHOD(OnDataUpdated)(ISensor* pSensor, ISensorDataReport* pNewData); STDMETHOD(OnEvent)(ISensor* pSensor, REFGUID eventId, IPortableDeviceValues* pEventData); // 以下は、COMのおまじない CSensorEventSink() : m_lRefCount(0) {} STDMETHODIMP QueryInterface(REFIID riid, void **ppObject) { *ppObject = 0; if (riid == __uuidof(ISensorEvents)) { *ppObject = reinterpret_cast<ISensorEvents*>(this); } else if (riid == IID_IUnknown) { *ppObject = reinterpret_cast<IUnknown*>(this); } else { return E_NOINTERFACE; } (reinterpret_cast<IUnknown*>(*ppObject))->AddRef(); return S_OK; } ULONG _stdcall AddRef() { m_lRefCount++; return m_lRefCount; } ULONG _stdcall Release() { ULONG lRet = --m_lRefCount; if (m_lRefCount == 0) delete this; return lRet; } private: long m_lRefCount; }; int _tmain(int argc, _TCHAR* argv[]) { //DebugBreak(); MessageBox(0, _T("WAIT"), NULL, 0); CoInitializeEx(NULL, COINIT_MULTITHREADED); // センサーマネージャを取り出す為の変数 CComPtr<ISensorManager> pSensorManager = NULL; // 取得したセンサーを格納する為の変数 CComPtr<ISensor> pAccelerometerSensor = NULL; // センサーがサポートするプロパティのキーを格納するコレクション IPortableDeviceKeyCollection* pKeys; // センサーがサポートするプロパティ値を格納するコレクション。キーと値のペアを格納 IPortableDeviceValues* pValues; // センサーマネージャの取得 HRESULT hr = CoCreateInstance( __uuidof(SensorManager), NULL, CLSCTX_INPROC_SERVER, __uuidof(ISensorManager), (LPVOID*)&pSensorManager); // センサーコレクション変数 CComPtr<ISensorCollection> pAccelerometerSensors; // 加速度センサーを取り出す hr = pSensorManager->GetSensorsByType(SENSOR_TYPE_ACCELEROMETER_3D, &pAccelerometerSensors); if (!SUCCEEDED(hr)) { return 1; } PROPERTYKEY pKey; PROPVARIANT pValue; while (true) { // 取得に成功したので、複数の候補から所望のセンサーを取り出す DWORD count = 0; hr = pAccelerometerSensors->GetCount(&count); for (DWORD i = 0; i < count; i++) { CComPtr<ISensor> pCandidate; hr = pAccelerometerSensors->GetAt(i, &pCandidate); if (SUCCEEDED(hr)) { pAccelerometerSensor = pCandidate; // 例えばフレンドリーネームを条件にする場合 BSTR friendlyName; hr = pCandidate->GetFriendlyName(&friendlyName); // 取得したフレンドリーネームを基に比較等を行い、確定 std::wcout << friendlyName << "\t"; SysFreeString(friendlyName); // センサーの説明を取得 hr = pAccelerometerSensor->GetProperty(SENSOR_PROPERTY_DESCRIPTION, &pValue); std::wcout << pValue.pwszVal << std::endl; PropVariantClear(&pValue); // サポートするプロパティキーを取得する HRESULT hr = pAccelerometerSensor->GetSupportedDataFields(&pKeys); if (SUCCEEDED(hr)) { // 取得したキーに対応する変数群を取り出す ISensorDataReport* pNewData; hr = pAccelerometerSensor->GetData(&pNewData); if (SUCCEEDED(hr)) { hr = pNewData->GetSensorValues(pKeys, &pValues); if (SUCCEEDED(hr)){ DWORD count = 0; hr = pKeys->GetCount(&count); for (DWORD i = 0; i < count; i++){ hr = pKeys->GetAt(i, &pKey); if (!SUCCEEDED(hr)) { continue; } // プロパティ値を取り出す。 hr = pValues->GetValue(pKey, &pValue); if (!SUCCEEDED(hr)) { continue; } switch (pValue.vt) { case VT_I8: std::cout << pValue.intVal << "\t"; break; case VT_R4: std::cout << pValue.fltVal << "\t"; break; case VT_R8: std::cout << pValue.dblVal << "\t"; break; case VT_FILETIME: FILETIME ft = pValue.filetime; FILETIME ftLocal; SYSTEMTIME st; FileTimeToLocalFileTime(&ft, &ftLocal); FileTimeToSystemTime(&ftLocal, &st); std::wcout << st.wYear << L"/" << st.wMonth << L"/" << st.wDay << L" " << st.wHour << L":" << st.wMinute << L":" << st.wSecond << L"\t"; break; } PropVariantClear(&pValue); } std::cout << std::endl; } } } break; } } Sleep(100); } CoUninitialize(); return 0; }
#イベントでなくループで取出してます
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
-
Visual C++ の 「空のプロジェクト」 から新規作成してみました。(Surfaceで動作確認済)
- Visual C++ の 「空のプロジェクト」 を作成
- プロジェクトに「Source.cpp」を追加して、下記をコピペ
#include <iostream> using namespace Platform; using namespace Windows::Devices::Sensors; [MTAThread] int main(void) { Accelerometer^ accelerometer = Accelerometer::GetDefault(); if (accelerometer) { accelerometer->ReadingChanged += ref new Windows::Foundation::TypedEventHandler<Accelerometer^, AccelerometerReadingChangedEventArgs^>( [](Accelerometer^ sender, AccelerometerReadingChangedEventArgs^ args) { std::cout << "X:" << args->Reading->AccelerationX; std::cout << "Y:" << args->Reading->AccelerationY; std::cout << "Z:" << args->Reading->AccelerationZ << std::endl; }); } std::cin.get(); return 0; }
- プロジェクトのプロパティで「構成のプロパティ」→「C/C++」→「全般」→「追加の #using ディレクトリ」に下記の2つのパスを追加。
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcpackages\C:\Program Files (x86)\Windows Kits\8.1\References\CommonConfiguration\Neutral\
- 同じ画面で「Windows ランタイム拡張機能の使用」を「はい (/ZW)」に設定
- 「構成のプロパティ」→「C/C++」→「コード生成」の「最小リビルドを有効にする」を「いいえ (/Gm-)」に設定
- プロジェクトをビルド&実行
※3のパスは環境によって異なるかもしれません。(Platform.winmdとWindows.winmdが存在するフォルダをそれぞれ追加しました)
作成したプロジェクトは、http://work.vc/Project1.zip に置いています。
- 編集済み kenjinoteMVP 2016年8月3日 1:26
- 回答の候補に設定 星 睦美 2016年8月3日 2:29
- 回答としてマーク ken120 2016年8月3日 3:39
すべての返信
-
こんにちは、
以下のサイトから加速度センサーを使うためのサンプルがダウンロードできます。
https://code.msdn.microsoft.com/windowsapps/Accelerometer-Sensor-Sample-22982671
参考になりますでしょうか?
> 複数のサイトをみて、プロパティをいじったりしたのですが、うまくいきません。
どの部分がどううまくいかなかったのか、具体的に質問されたほうが回答が得やすいかと思います。
Visual Studioのバージョンや言語の詳細も教えてください。- 編集済み kenjinoteMVP 2016年8月2日 1:32
-
返信ありがとうございます。
こちらは以前試そうとしたのですが、このサンプルはwindows8用でして、申し上げてなかったのですが、自分はwindows10で開発しています。そのため、このサンプルは起動できません。
詳細としまして、windows10のvisualstudio2015で、言語はC++です。
私が行ったのは、空のプロジェクトを立ち上げ、プロパティからwindowsランタイムの拡張をして、加速度センサーのクラスである、Accelerometerを使用するための、Windows::Devices::sensorsの名前空間の使用を可能にし、Accelerometer::GetDefault()を使用しました。コンパイルは通ったのですが、実行時に、中断されてしまい、その原因がわかりません。
-
私の環境 (Surface, Windows 10, Visual Studio 2015) では上記サンプルは、Visual Studio 2015 でビルドでき、動きました。加速度もリアルタイムで取得できていました。
サンプルではターゲットが Windows 8.1 でしたので、「空白のアプリ(ユニバーサル Windows)」のプロジェクトを新規に作成し、必要なコードをサンプルからコピー&ペーストして動作させてみましたが、やはり動きました。
MainPage.xaml.cpp
// // MainPage.xaml.cpp // MainPage クラスの実装。 // #include "pch.h" #include "MainPage.xaml.h" using namespace App1; using namespace Platform; using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; using namespace Windows::UI::Xaml; using namespace Windows::UI::Xaml::Controls; using namespace Windows::UI::Xaml::Controls::Primitives; using namespace Windows::UI::Xaml::Data; using namespace Windows::UI::Xaml::Input; using namespace Windows::UI::Xaml::Media; using namespace Windows::UI::Xaml::Navigation; using namespace Windows::Devices::Sensors; using namespace Windows::UI::Core; MainPage::MainPage() { InitializeComponent(); accelerometer = Accelerometer::GetDefault(); if (accelerometer) { uint32 minReportInterval = accelerometer->MinimumReportInterval; accelerometer->ReportInterval = minReportInterval > 16 ? minReportInterval : 16; readingToken = accelerometer->ReadingChanged::add(ref new TypedEventHandler<Accelerometer^, AccelerometerReadingChangedEventArgs^>(this, &MainPage::ReadingChanged)); } } void MainPage::ReadingChanged(Accelerometer^ sender, AccelerometerReadingChangedEventArgs^ e) { Dispatcher->RunAsync( CoreDispatcherPriority::Normal, ref new DispatchedHandler( [this, e]() { AccelerometerReading^ reading = e->Reading; ScenarioOutput_X->Text = reading->AccelerationX.ToString(); ScenarioOutput_Y->Text = reading->AccelerationY.ToString(); ScenarioOutput_Z->Text = reading->AccelerationZ.ToString(); }, CallbackContext::Any ) ); }
MainPage.xaml.h
// // MainPage.xaml.h // MainPage クラスの宣言。 // #pragma once #include "MainPage.g.h" namespace App1 { /// <summary> /// それ自体で使用できる空白ページまたはフレーム内に移動できる空白ページ。 /// </summary> public ref class MainPage sealed { public: MainPage(); private: Windows::Foundation::EventRegistrationToken readingToken; Windows::Devices::Sensors::Accelerometer^ accelerometer; void ReadingChanged(Windows::Devices::Sensors::Accelerometer^ sender, Windows::Devices::Sensors::AccelerometerReadingChangedEventArgs^ e); }; }
作成したプロジェクトは下記からダウンロードできます。
http://work.vc/AccelerometerCPP.zip- 編集済み kenjinoteMVP 2016年8月2日 8:55
-
空のプロジェクトから作成しているアプリケーションはコンソールだとかATLやMFCのデスクトップアプリケーションといった形式がありますが、どの形式で進めているのでしょうか。
たとえばコンソールアプリと以下のようにSensor APIで加速度センサの値を取得できました
#コードレシピの「[C++] Native Code (VC++) で Windows 7 Sensor API を使う」を加速度センサに書き換え
#include "stdafx.h" //#include "targetver.h" //#include <stdio.h> //#include <tchar.h> //#include <atlbase.h> // ATLを参照 //#include <atlstr.h> //#include <INITGUID.H> //#include <SensorsApi.h> //#include <sensors.h> //#include <iostream> class CSensorEventSink : public ISensorEvents { public: // ISensorEvents で定義されているイベント STDMETHOD(OnStateChanged)(ISensor* pSensor, SensorState state); STDMETHOD(OnLeave)(REFSENSOR_ID sensorID); STDMETHOD(OnDataUpdated)(ISensor* pSensor, ISensorDataReport* pNewData); STDMETHOD(OnEvent)(ISensor* pSensor, REFGUID eventId, IPortableDeviceValues* pEventData); // 以下は、COMのおまじない CSensorEventSink() : m_lRefCount(0) {} STDMETHODIMP QueryInterface(REFIID riid, void **ppObject) { *ppObject = 0; if (riid == __uuidof(ISensorEvents)) { *ppObject = reinterpret_cast<ISensorEvents*>(this); } else if (riid == IID_IUnknown) { *ppObject = reinterpret_cast<IUnknown*>(this); } else { return E_NOINTERFACE; } (reinterpret_cast<IUnknown*>(*ppObject))->AddRef(); return S_OK; } ULONG _stdcall AddRef() { m_lRefCount++; return m_lRefCount; } ULONG _stdcall Release() { ULONG lRet = --m_lRefCount; if (m_lRefCount == 0) delete this; return lRet; } private: long m_lRefCount; }; int _tmain(int argc, _TCHAR* argv[]) { //DebugBreak(); MessageBox(0, _T("WAIT"), NULL, 0); CoInitializeEx(NULL, COINIT_MULTITHREADED); // センサーマネージャを取り出す為の変数 CComPtr<ISensorManager> pSensorManager = NULL; // 取得したセンサーを格納する為の変数 CComPtr<ISensor> pAccelerometerSensor = NULL; // センサーがサポートするプロパティのキーを格納するコレクション IPortableDeviceKeyCollection* pKeys; // センサーがサポートするプロパティ値を格納するコレクション。キーと値のペアを格納 IPortableDeviceValues* pValues; // センサーマネージャの取得 HRESULT hr = CoCreateInstance( __uuidof(SensorManager), NULL, CLSCTX_INPROC_SERVER, __uuidof(ISensorManager), (LPVOID*)&pSensorManager); // センサーコレクション変数 CComPtr<ISensorCollection> pAccelerometerSensors; // 加速度センサーを取り出す hr = pSensorManager->GetSensorsByType(SENSOR_TYPE_ACCELEROMETER_3D, &pAccelerometerSensors); if (!SUCCEEDED(hr)) { return 1; } PROPERTYKEY pKey; PROPVARIANT pValue; while (true) { // 取得に成功したので、複数の候補から所望のセンサーを取り出す DWORD count = 0; hr = pAccelerometerSensors->GetCount(&count); for (DWORD i = 0; i < count; i++) { CComPtr<ISensor> pCandidate; hr = pAccelerometerSensors->GetAt(i, &pCandidate); if (SUCCEEDED(hr)) { pAccelerometerSensor = pCandidate; // 例えばフレンドリーネームを条件にする場合 BSTR friendlyName; hr = pCandidate->GetFriendlyName(&friendlyName); // 取得したフレンドリーネームを基に比較等を行い、確定 std::wcout << friendlyName << "\t"; SysFreeString(friendlyName); // センサーの説明を取得 hr = pAccelerometerSensor->GetProperty(SENSOR_PROPERTY_DESCRIPTION, &pValue); std::wcout << pValue.pwszVal << std::endl; PropVariantClear(&pValue); // サポートするプロパティキーを取得する HRESULT hr = pAccelerometerSensor->GetSupportedDataFields(&pKeys); if (SUCCEEDED(hr)) { // 取得したキーに対応する変数群を取り出す ISensorDataReport* pNewData; hr = pAccelerometerSensor->GetData(&pNewData); if (SUCCEEDED(hr)) { hr = pNewData->GetSensorValues(pKeys, &pValues); if (SUCCEEDED(hr)){ DWORD count = 0; hr = pKeys->GetCount(&count); for (DWORD i = 0; i < count; i++){ hr = pKeys->GetAt(i, &pKey); if (!SUCCEEDED(hr)) { continue; } // プロパティ値を取り出す。 hr = pValues->GetValue(pKey, &pValue); if (!SUCCEEDED(hr)) { continue; } switch (pValue.vt) { case VT_I8: std::cout << pValue.intVal << "\t"; break; case VT_R4: std::cout << pValue.fltVal << "\t"; break; case VT_R8: std::cout << pValue.dblVal << "\t"; break; case VT_FILETIME: FILETIME ft = pValue.filetime; FILETIME ftLocal; SYSTEMTIME st; FileTimeToLocalFileTime(&ft, &ftLocal); FileTimeToSystemTime(&ftLocal, &st); std::wcout << st.wYear << L"/" << st.wMonth << L"/" << st.wDay << L" " << st.wHour << L":" << st.wMinute << L":" << st.wSecond << L"\t"; break; } PropVariantClear(&pValue); } std::cout << std::endl; } } } break; } } Sleep(100); } CoUninitialize(); return 0; }
#イベントでなくループで取出してます
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
-
Visual C++ の 「空のプロジェクト」 から新規作成してみました。(Surfaceで動作確認済)
- Visual C++ の 「空のプロジェクト」 を作成
- プロジェクトに「Source.cpp」を追加して、下記をコピペ
#include <iostream> using namespace Platform; using namespace Windows::Devices::Sensors; [MTAThread] int main(void) { Accelerometer^ accelerometer = Accelerometer::GetDefault(); if (accelerometer) { accelerometer->ReadingChanged += ref new Windows::Foundation::TypedEventHandler<Accelerometer^, AccelerometerReadingChangedEventArgs^>( [](Accelerometer^ sender, AccelerometerReadingChangedEventArgs^ args) { std::cout << "X:" << args->Reading->AccelerationX; std::cout << "Y:" << args->Reading->AccelerationY; std::cout << "Z:" << args->Reading->AccelerationZ << std::endl; }); } std::cin.get(); return 0; }
- プロジェクトのプロパティで「構成のプロパティ」→「C/C++」→「全般」→「追加の #using ディレクトリ」に下記の2つのパスを追加。
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcpackages\C:\Program Files (x86)\Windows Kits\8.1\References\CommonConfiguration\Neutral\
- 同じ画面で「Windows ランタイム拡張機能の使用」を「はい (/ZW)」に設定
- 「構成のプロパティ」→「C/C++」→「コード生成」の「最小リビルドを有効にする」を「いいえ (/Gm-)」に設定
- プロジェクトをビルド&実行
※3のパスは環境によって異なるかもしれません。(Platform.winmdとWindows.winmdが存在するフォルダをそれぞれ追加しました)
作成したプロジェクトは、http://work.vc/Project1.zip に置いています。
- 編集済み kenjinoteMVP 2016年8月3日 1:26
- 回答の候補に設定 星 睦美 2016年8月3日 2:29
- 回答としてマーク ken120 2016年8月3日 3:39