ジャイロスコープセンサーを使った、カウンターのサンプル
ジャイロスコープセンサーを使った、カウンターのサンプル
2つ目は、ジャイロスコープセンサーを使った「カウンター」の作り方です。
加速度センサーもジャイロスコープも、どちらも元の状態からの移動を検出するものですが、ジャイロスコープでは、1秒間に何ラジアン回転したか、つまり、どのようにデバイスの姿勢が変化したかを検出できます。
実機を傾けた時の処理には加速度センサーを、実機を振ったり回転させたりした時の処理にはジャイロスコープを使ってみるとよいでしょう。
- このサンプルでは、ページをロードした時点では、X、Y、Zそれぞれのカウンターの値は「0」です。
- スライダーで検出レベルを設定してから「開始」ボタンをタップして実機を振ると、カウンターが加算されていきます。
- 「停止」ボタンをタップすると、センシングは停止します。
スライダーの値が小さい時は、実機を少し振ってもカウントします。一方、スライダーの値を大きくすると、実機をリズミカルに力強く振らなければカウントしません(図4)。
![]() |
図4:ジャイロスコープセンサーの働きにより、実機を振るとカウントする(クリックで拡大) |
プロジェクトの作成
VS 2010のメニューから[ファイル(F)/新規作成(N)/プロジェクト(P)]と選択します。次に、「Windows Phone アプリケーション」を選択して、「名前(N)」に任意のプロジェクト名を指定します。ここでは「GyroscopeSample」という名前を付けています。Windows Phoneのバージョンは7.1を選択します。
MainPage.xamlの編集とコントロールの追加
ツールボックスからButtonコントロールを1個、TextBlockコントロールを5個配置します。
また、Sliderコントロールを1個配置します。SliderのプロパティウィンドウでSmallChange、LargeChange、Value、Maximum、Minimumの値を指定して、1~5まで1刻みで設定できるようにします。
色や書体を指定したXAMLコードはリスト3のようになります。
リスト3 各プロパティを指定したXAMLコード(MainPage.xaml)
~前略~ <!--LayoutRoot は、すべてのページ コンテンツが配置されるルート グリッドです-->
<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="ジャイロスコープセンサー" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="カウンター" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Slider Height="120" HorizontalAlignment="Left" Margin="20,10,0,0" Name="Slider1" VerticalAlignment="Top" Width="300" SmallChange="1" Maximum="5" LargeChange="1" Value="2" Minimum="1" />
<TextBlock Height="80" HorizontalAlignment="Left" Margin="350,30,0,0" Name="LevelTextBlock" Text="0.2" VerticalAlignment="Top" Width="100" FontSize="40"/>
<Button Content="開始" Height="100" HorizontalAlignment="Left" Margin="80,150,0,0" Name="Button1" VerticalAlignment="Top" Width="300" IsEnabled="False" />
<TextBlock Height="60" HorizontalAlignment="Left" Margin="100,280,0,0" Name="TextBlockX" Text="X:0" VerticalAlignment="Top" Width="300" FontSize="48" Foreground="SkyBlue"/>
<TextBlock Height="60" HorizontalAlignment="Left" Margin="100,360,0,0" Name="TextBlockY" Text="Y:0" VerticalAlignment="Top" Width="300" FontSize="48" Foreground="OrangeRed"/>
<TextBlock Height="60" HorizontalAlignment="Left" Margin="100,440,0,0" Name="TextBlockZ" Text="Z:0" VerticalAlignment="Top" Width="300" FontSize="48" Foreground="LimeGreen" />
<TextBlock Height="37" HorizontalAlignment="Left" Margin="10,540,0,0" Name="StatusTextBlock" Text="センサーの状態" VerticalAlignment="Top" Width="400" FontSize="20" />
</Grid>
</Grid>
<!--ApplicationBar の使用法を示すサンプル コード--> ~後略~
ロジックコードを記述する前に、「プロジェクト/参照の追加」で、Microsoft.Devices.Sensors名前空間と、Microsoft.Xna.Framework名前空間への参照を追加しておきます。
MainPage.xaml.vbを開いて、ロジックコードを記述します(●リスト4)。
ロジックコードを記述する
リスト4 (MainPage.xaml.vb)
名前空間のインポートと変数の宣言
Microsoft.Devices.Sensors名前空間とXna.Framework名前空間をインポートしておきます。
このサンプルでは、計測間隔に200を指定して、200ミリ秒ごとに計測を実行させています。計測値と比較する値と、カウンターの値を設定しておきます。
Option Strict On
Imports Microsoft.Devices.Sensors
Imports Microsoft.Xna.Framework
Partial Public Class MainPage
Inherits PhoneApplicationPage
' Constructor
Public Sub New()
InitializeComponent()
End Sub
Dim MyGyro As Gyroscope 'ジャイロスコープセンサー
Dim MyTimeSpan As Integer = 200 '計測間隔
Dim MyCurrentRotationRate As Vector3 = Vector3.Zero 'センサーデータ
Dim CompareValue As Double = 0.2 '検出値設定用のスライダーの値を10で除算した値
Dim MyCountX As Integer = 0 'カウンターの値
Dim MyCountY As Integer = 0
Dim MyCountZ As Integer = 0
Dim CounterLevel As Double = 1 'デフォルトの比較値
このページがロードされた時の処理
デバイスがセンサーをサポートしているかどうかをチェックして、サポートしていなければ、メッセージを表示します。
Private Sub MainPage_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
'ジャイロスコープがサポートされていない機種への対応
If Gyroscope.IsSupported = False Then
MessageBox.Show("このデバイスはジャイロスコープセンサーをサポートしていません。")
Button1.IsEnabled = False
Exit Sub
Else
Button1.IsEnabled = True
End If
End Sub
スライダーの値が変化した時の処理
センサーにより取得されるRotationRateの値(rad/sec)と比較する値を、スライダーの設定値と計測間隔から求めておきます。
Private Sub Slider1_ValueChanged(sender As Object, e As System.Windows.RoutedPropertyChangedEventArgs(Of Double)) Handles Slider1.ValueChanged
CompareValue = CInt(Slider1.Value) / 10
LevelTextBlock.Text = CStr(CompareValue)
CounterLevel = CompareValue * 1000 / MyTimeSpan
End Sub
ボタンがタップされた時の処理
このサンプルでは、1個のボタンで、センシングの開始と停止を切り替えます。センサーオブジェクトが有効であれば、センサーを停止し、ボタンの文字列を「開始」にします。
センサーオブジェクトが空であれば、ジャイロスコープの新しいインスタンスを作成して、ボタンの文字列を「停止」にしたうえで、センシングを実行します。
Private Sub Button1_Tap(sender As Object, e As System.Windows.Input.GestureEventArgs) Handles Button1.Tap
If MyGyro IsNot Nothing AndAlso MyGyro.IsDataValid Then
Try
MyGyro.Stop()
MyGyro = Nothing
StatusTextBlock.Text = "ジャイロスコープセンサーを停止しました。"
Slider1.IsEnabled = True
Button1.Content = "開始"
Catch
MessageBox.Show("ジャイロスコープセンサーの停止に失敗しました。")
End Try
Else
If MyGyro Is Nothing Then
MyGyro = New Gyroscope
MyGyro.TimeBetweenUpdates = TimeSpan.FromMilliseconds(MyTimeSpan)
AddHandler MyGyro.CurrentValueChanged, Sub(senderValue As Object, eValue As SensorReadingEventArgs(Of GyroscopeReading))
Deployment.Current.Dispatcher.BeginInvoke(Sub() UpdateUI(eValue.SensorReading))
End Sub
End If
Try
Slider1.IsEnabled = False
Button1.Content = "停止"
StatusTextBlock.Text = "ジャイロスコープセンサーを開始しました。"
MyGyro.Start()
Catch
MessageBox.Show("ジャイロスコープセンサーを開始できません。")
End Try
End If
End Sub
センサーデータが更新された時の処理
GyroscopeReading 構造のRotationRate プロパティを用いて、取得されたセンサーデータを3軸に分解します。それぞれの軸の絶対値が、スライダーで設定した検出レベル以上であればカウントします。
Private Sub UpdateUI(MyReading As GyroscopeReading)
MyCurrentRotationRate = MyReading.RotationRate '単位はrad/sec
'デバイスのX, Y, Zの各軸の回転速度 (rad/sec)
'GyroscopeReading 構造 RotationRate プロパティで取得される値
Dim MyValueX As Double = MyCurrentRotationRate.X
Dim MyValueY As Double = MyCurrentRotationRate.Y
Dim MyValueZ As Double = MyCurrentRotationRate.Z
'カウンターの加算と表示
'計測値をスライダーで設定したレベルと比較
'3軸の値がそれぞれ設定値以上であればカウントする
If Math.Abs(MyValueX) >= CounterLevel Then
MyCountX = MyCountX + 1
TextBlockX.Text = "X:" & CStr(MyCountX)
End If
If Math.Abs(MyValueY) >= CounterLevel Then
MyCountY = MyCountY + 1
TextBlockY.Text = "Y:" & CStr(MyCountY)
End If
If Math.Abs(MyValueZ) >= CounterLevel Then
MyCountZ = MyCountZ + 1
TextBlockZ.Text = "Z:" & CStr(MyCountZ)
End If
End Sub
End Class
- この記事のキーワード
