方向传感器
方向传感器融合了陀螺仪、加速计和指南针的功能,它能检索四元数。四元数由一个实数和三个有向数据组成,可以使用四元数综合测量设备的运动状态和方位。下面通过示例介绍使用方向传感器API获取四元数。
新建一个Windows应用商店的空白应用程序项目,并命名为OrientationSensorExample,在MainPage.xaml文件的Grid元素中添加如下代码。
<TextBlock Text="获取方向传感器读数" Height="40" FontSize="25" Margin="65,40,1062,688"/>
<!--控制按钮-->
<Button Name="GetDataButton" Content="获得读数" Click="GetData_Click" Margin="65,274,0,456"/>
<Button Name="CloseButton" Content="停止" Click="CloseData_Click" Margin="190,274,0,456"/>
<!--显示数据的文本控件-->
<TextBlock Name="InfoText" Width="200" Height="50" Margin="85,322,1081,396"></TextBlock>
<TextBlock HorizontalAlignment="Left" Height="38" Margin="65,98,0,0" TextWrapping="Wrap" Text="四元数X轴" VerticalAlignment="Top" Width="125" FontSize="20"/>
<TextBlock HorizontalAlignment="Left" Height="43" Margin="64,144,0,0" TextWrapping="Wrap" Text="四元数Y轴" VerticalAlignment="Top" Width="125" FontSize="20"/>
<TextBlock HorizontalAlignment="Left" Height="38" Margin="65,187,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="125" Text="四元数Z轴" FontSize="20">
</TextBlock>
<TextBlock x:Name="ScenarioOutput_X" HorizontalAlignment="Left" Height="38" Margin="190,98,0,0" TextWrapping="Wrap" Text="获取读数" VerticalAlignment="Top" Width="95" FontSize="20"/>
<TextBlock x:Name="ScenarioOutput_Y" HorizontalAlignment="Left" Height="43" Margin="190,144,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="91" FontSize="20" Text="获取读数">
</TextBlock>
<TextBlock x:Name="ScenarioOutput_Z" HorizontalAlignment="Left" Height="41" Margin="190,184,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="90" RenderTransformOrigin="0.5,0.5" FontSize="20" Text="获取读数"/>
<TextBlock HorizontalAlignment="Left" Height="39" Margin="65,230,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="125" Text="四元数W轴" FontSize="20">
</TextBlock>
<TextBlock x:Name="ScenarioOutput_W" HorizontalAlignment="Left" Height="39" Margin="190,230,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="90" FontSize="20" Text="获取读数">
</TextBlock>
在上面的代码中,放置了多个显示信息的TextBlock控件,其中有4个用于显示方向传感器数据。然后又添加了2个按钮,并为这2个按钮定义了事件处理方法,一个用于启动方向传感器数据获取,另外一个按钮则用于停止数据获取。
前台运行效果如图12-9所示。
图12-9显示方向传感器读数的界面
布局好前台界面后,接下来介绍如何从方向传感器获取读数。首先在后台定义几个全局变量并在构造方法中初始化,以便在后续代码中使用。代码如下所示:
//定义全局变量
private OrientationSensor sensor;
private uint desiredReportInterval;
public MainPage()
{
this.InitializeComponent();
//获得对传感器的引用
sensor = OrientationSensor.GetDefault();
if (sensor != null)
{
uint minReportInterval = sensor.MinimumReportInterval;
desiredReportInterval = minReportInterval > 16 ? minReportInterval : 16;
CloseButton.IsEnabled = false;
}
else
{
InfoText.Text = "未发现方向传感器设备";
}
}
在上面的代码中,使用OrientationSensor.GetDefault方法获得方向传感器的引用对象sensor,通过定义全局变量desiredReportInterval来设置期望的报告间隔。
定义全局变量后,接下来对“获得读数”按钮添加GetData_Click事件处理方法,单击这个按钮启动方向传感器读数捕获。代码如下所示:
private void GetData_Click(object sender, RoutedEventArgs e)
{
if (sensor != null)
{
//设置报告时间
sensor.ReportInterval = desiredReportInterval;
//注册ReadingChanged事件的处理方法
sensor.ReadingChanged += new TypedEventHandler<OrientationSensor, OrientationSensorReadingChangedEventArgs>(GetChangedData);
GetDataButton.IsEnabled = false;
CloseButton.IsEnabled = true;
}
else
{
InfoText.Text = "没有发现方向传感器";
}
}
在上面的事件处理程序中,使用了sensor对象ReportInterval属性设置方向传感器的报告间隔,报告间隔会影响改变灵敏度,可参照表12-5选择合适的报告间隔。接着为sensor对象的ReadingChanged事件添加事件处理方法GetChangedData,当方向传感器驱动程序捕获到设备的四元数数据时,会触发ReadingChanged事件进而执行GetChangedData方法。
表12-5方向传感器当前报告间隔与改变灵敏度的关系
当前报告间隔(毫秒) |
改变灵敏度(角度) |
1 ms ~ 16 ms |
0.01 ° |
17 ms ~ 32 ms |
0.02 ° |
>= 33 ms |
0.05 ° |
接下来定义上面用到的GetChangedData 方法,这个方法异步检索方向传感器改变后的读数,然后将读数显示在前台界面中。具体代码如下所示:
async private void GetChangedData (object sender, OrientationSensorReadingChangedEventArgs e)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
//获得对传感器读数的引用
OrientationSensorReading reading = e.Reading;
//获得对传感器四元数的引用
SensorQuaternion quaternion = reading.Quaternion;
//读取并显示四元数
ScenarioOutput_X.Text = String.Format("{0,8:0.00000}", quaternion.X);
ScenarioOutput_Y.Text = String.Format("{0,8:0.00000}", quaternion.Y);
ScenarioOutput_Z.Text = String.Format("{0,8:0.00000}", quaternion.Z);
ScenarioOutput_W.Text = String.Format("{0,8:0.00000}", quaternion.W);
});
}
在上面的方法中,首先从参数e中获得OrientationSensorReading类型的对象reading,然后获得四元数对象quaternion,接着根据quaternion对象的X属性获取四元数的第一个数据,将它显示在ScenarioOutput_X控件中,使用quaternion对象的Y、Z和W属性获取另外三个数据,方法中调用了String.Format方法设置输出数据的格式以增加数据的可读性。为了避免UI线程的阻塞,使用调度器Dispatcher的RunAsync方法异步实现上述过程。
为“停止”按钮添加单击事件处理方法CloseData_Click(),当单击此按钮时停止获取方向传感器数据,CloseData_Click方法的代码如下所示:
private void CloseData_Click(object sender, RoutedEventArgs e)
{
if (sensor != null)
{
sensor.ReadingChanged -= new TypedEventHandler<OrientationSensor, OrientationSensorReadingChangedEventArgs>(GetChangedData);
GetDataButton.IsEnabled = true;
CloseButton.IsEnabled = false;
}
else
{
InfoText.Text = "结束方向传感器读数失败";
}
}
在上面的代码中,停止捕获的原理与停止指南针传感器数据的捕获相似,请参照12.2.1节的原理介绍。
启动调试,单击“获得读数”按钮后,“获得读数”按钮将转变为不可用状态,界面上显示当前设备方向传感器的四元数信息。“停止”按钮变为可激活状态。
单击“停止”按钮,将停止更新四元数信息,此时“停止”按钮变为不可用,“获得读数”按钮变为可激活状态。程序运行效果如图12-10所示。
图12-10 显示传感器数据的界面
OrientationSensor类有一个GetCurrentOrientation方法,该方法能获得当前方向传感器的读数,返回值类型为OrientationSensorReading,参照主动获取陀螺仪读数的部分,也可以使用计时器每隔一段时间主动获取一次当前设备方向传感器的四元数数据信息。
注:本文选自机械工业出版社3月出品的《Windows 8 应用开发权威指南》第12章 传感器
另外:为在4月27日举办的微软云体验营免费活动做一下宣传。