與眾不同 windows phone (19) - Device(設備)之陀螺儀傳感器, Motion API


[索引頁]
[源碼下載]


與眾不同 windows phone (19) - Device(設備)之陀螺儀傳感器, Motion API



作者:webabcd


介紹
與眾不同 windows phone 7.5 (sdk 7.1) 之設備

  • 陀螺儀傳感器
  • Motion API(運動 API



示例
1、演示如何使用陀螺儀傳感器
GyroscopeDemo.xaml

<phone:PhoneApplicationPage 
    x:Class="Demo.Device.GyroscopeDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
    shell:SystemTray.IsVisible="True">

    <Grid x:Name="LayoutRoot" Background="Transparent">
        <StackPanel Orientation="Vertical">

            <TextBlock Name="lblGyroscopeSupported" />
            <Button Name="btnStart" Content="打開陀螺儀" Click="btnStart_Click" />
            <Button Name="btnStop" Content="關閉陀螺儀" Click="btnStop_Click" />
            <TextBlock Name="lblGyroscopeStatus" />
            <TextBlock Name="lblTimeBetweenUpdates" />
            <TextBlock Name="lblMsg" />

        </StackPanel>
    </Grid>
 
</phone:PhoneApplicationPage>

GyroscopeDemo.xaml.cs

/*
 * 演示如何使用陀螺儀傳感器
 * 
 * Gyroscope - 用於訪問設備中的陀螺儀
 *     IsSupported - 設備是否支持陀螺儀
 *     IsDataValid - 是否可從陀螺儀中獲取到有效數據
 *     CurrentValue - 陀螺儀當前的數據,GyroscopeReading 類型
 *     TimeBetweenUpdates - 觸發 CurrentValueChanged 事件的時間間隔,如果設置的值小於 Gyroscope 允許的最小值,則此屬性的值將被設置為 Gyroscope 允許的最小值
 *     Start() - 打開陀螺儀
 *     Stop() - 關閉陀螺儀
 *     CurrentValueChanged - 陀螺儀傳感器獲取到的數據發生改變時所觸發的事件,屬性 TimeBetweenUpdates 的值決定觸發此事件的時間間隔
 *     
 * GyroscopeReading - 陀螺儀傳感器數據
 *     RotationRate - 獲取圍繞設備各軸旋轉的旋轉速率(單位:弧度/秒)
 *     DateTimeOffset - 從陀螺儀傳感器中獲取到數據的時間點
 *     
 * 
 * 
 * 手機坐標系:以手機位置為參照,假設手機垂直水平面放(豎着放),屏幕對着你,那么
 * 1、左右是 X 軸,右側為正方向,左側為負方向
 * 2、上下是 Y 軸,上側為正方向,下側為負方向
 * 3、里外是 Z 軸,靠近你為正方向,遠離你為負方向
 * 以上可以用相對於手機位置的右手坐標系來理解
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;

using Microsoft.Devices.Sensors;
using Microsoft.Xna.Framework;

namespace Demo.Device
{
    public partial class GyroscopeDemo : PhoneApplicationPage
    {
        private Gyroscope _gyroscope;

        public GyroscopeDemo()
        {
            InitializeComponent();

            // 判斷設備是否支持陀螺儀
            if (Gyroscope.IsSupported)
            {
                lblGyroscopeStatus.Text = "此設備支持陀螺儀";
            }
            else
            {
                lblGyroscopeStatus.Text = "此設備不支持陀螺儀";

                btnStart.IsEnabled = false;
                btnStop.IsEnabled = false;
            }
        }

        private void btnStart_Click(object sender, RoutedEventArgs e)
        {
            if (_gyroscope == null)
            {
                // 實例化 Gyroscope,注冊相關事件
                _gyroscope = new Gyroscope();
                _gyroscope.TimeBetweenUpdates = TimeSpan.FromMilliseconds(1);
                _gyroscope.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<GyroscopeReading>>(_gyroscope_CurrentValueChanged);

                lblTimeBetweenUpdates.Text = "TimeBetweenUpdates 設置為 1 毫秒,實際為 " + _gyroscope.TimeBetweenUpdates.TotalMilliseconds.ToString() + " 毫秒";
            }

            try
            {
                // 打開陀螺儀
                _gyroscope.Start();
                lblGyroscopeStatus.Text = "陀螺儀已打開";
            }
            catch (Exception ex)
            {
                lblGyroscopeStatus.Text = "陀螺儀打開失敗";
                MessageBox.Show(ex.ToString());
            }
        }

        private void btnStop_Click(object sender, RoutedEventArgs e)
        {
            if (_gyroscope != null)
            {
                // 關閉陀螺儀
                _gyroscope.Stop();
                lblGyroscopeStatus.Text = "陀螺儀已關閉";
            }
        }

        void _gyroscope_CurrentValueChanged(object sender, SensorReadingEventArgs<GyroscopeReading> e)
        {
            // 注:此方法是在后台線程運行的,所以需要更新 UI 的話注意要調用 UI 線程
            Dispatcher.BeginInvoke(() => UpdateUI(e.SensorReading));
        }

        private DateTimeOffset _lastUpdateTime = DateTimeOffset.MinValue; // 上一次獲取陀螺儀數據的時間
        private Vector3 _rotationTotal = Vector3.Zero; // 陀螺儀各軸的累積旋轉弧度
        // 更新 UI
        private void UpdateUI(GyroscopeReading gyroscopeReading)
        {
            // 以下用於計算陀螺儀各軸的累積旋轉弧度
            if (_lastUpdateTime.Equals(DateTimeOffset.MinValue))
            {
                _lastUpdateTime = gyroscopeReading.Timestamp;
            }
            else
            {
                TimeSpan timeSinceLastUpdate = gyroscopeReading.Timestamp - _lastUpdateTime;

                // 陀螺儀當前旋轉速率 * 計算此速率所經過的時間 = 此時間段內旋轉的弧度
                _rotationTotal += gyroscopeReading.RotationRate * (float)(timeSinceLastUpdate.TotalSeconds);

                _lastUpdateTime = gyroscopeReading.Timestamp;
            }


            Vector3 rotationRate = gyroscopeReading.RotationRate;

            // 顯示陀螺儀當前各軸的旋轉速率(單位:弧度/秒)
            lblMsg.Text += "RotationRate.X: " + rotationRate.X.ToString("0.0");
            lblMsg.Text += Environment.NewLine;
            lblMsg.Text += "RotationRate.Y: " + rotationRate.Y.ToString("0.0");
            lblMsg.Text += Environment.NewLine;
            lblMsg.Text += "RotationRate.Z: " + rotationRate.Z.ToString("0.0");
            lblMsg.Text += Environment.NewLine;

            // 顯示陀螺儀各軸的累積旋轉角度
            lblMsg.Text += "RotationTotal.X: " + MathHelper.ToDegrees(_rotationTotal.X).ToString("0.00");
            lblMsg.Text += Environment.NewLine;
            lblMsg.Text += "RotationTotal.Y: " + MathHelper.ToDegrees(_rotationTotal.X).ToString("0.00");
            lblMsg.Text += Environment.NewLine;
            lblMsg.Text += "RotationTotal.Z: " + MathHelper.ToDegrees(_rotationTotal.X).ToString("0.00");
        }
    }
}


2、演示如何使用 Motion API
MotionDemo.xaml

<phone:PhoneApplicationPage 
    x:Class="Demo.Device.MotionDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
    shell:SystemTray.IsVisible="True">

    <Grid x:Name="LayoutRoot" Background="Transparent">
        <StackPanel Orientation="Vertical">

            <TextBlock Name="lblMotionSupported" />
            <Button Name="btnStart" Content="打開 Motion 監測" Click="btnStart_Click" />
            <Button Name="btnStop" Content="關閉 Motion 監測" Click="btnStop_Click" />
            <TextBlock Name="lblMotionStatus" />
            <TextBlock Name="lblTimeBetweenUpdates" />
            <TextBlock Name="lblMsg" />

        </StackPanel>
    </Grid>

</phone:PhoneApplicationPage>

MotionDemo.xaml.cs

/*
 * 演示如何使用 Motion API
 * 
 * Motion - Motion API,其作用為:整合各個傳感器 Accelerometer, Gyroscope, Compass 的數據,通過復雜的運算計算出易用的數據
 *     IsSupported - 設備是否支持 Motion API
 *     IsDataValid - 是否可從 Motion API 中獲取到有效數據
 *     CurrentValue - Motion API 當前的數據,MotionReading 類型
 *     TimeBetweenUpdates - 觸發 CurrentValueChanged 事件的時間間隔,如果設置的值小於 Motion API 允許的最小值,則此屬性的值將被設置為 Motion API 允許的最小值
 *     Start() - 打開 Motion 監測
 *     Stop() - 關閉 Motion 監測
 *     CurrentValueChanged - 當 Motion API 獲取到的數據發生改變時所觸發的事件,屬性 TimeBetweenUpdates 的值決定觸發此事件的時間間隔
 *     Calibrate - 當系統檢測到 Motion API 用到的數字羅盤傳感器需要校准時所觸發的事件
 *     
 * MotionReading - Motion API 數據
 *     AttitudeReading - 設備的姿態(AttitudeReading 類型,可以獲得 Yaw Pitch Roll 數據)
 *     DeviceAcceleration - 設備的加速度(Vector3 類型)
 *     DeviceRotationRate - 設備的旋轉速率(Vector3 類型)
 *     Gravity - 重力(Vector3 類型)
 *     DateTimeOffset - 從 Motion API 中獲取到數據的時間點
 *     
 * 注:
 * 如果設備缺少必要的傳感器,那么 Motion API 將無法正常工作
 * 例如,如果只有 Accelerometer, Compass 而沒有 Gyroscope,那么雖然 Motion API 是被支持的,但是部分數據是不精准的
 * 例如,如果只有 Accelerometer 而沒有 Compass, Gyroscope,那么 Motion API 是不被支持的
 * 
 * 
 * 
 * 手機坐標系:以手機位置為參照,假設手機垂直水平面放(豎着放),屏幕對着你,那么
 * 1、左右是 X 軸,右側為正方向,左側為負方向
 * 2、上下是 Y 軸,上側為正方向,下側為負方向
 * 3、里外是 Z 軸,靠近你為正方向,遠離你為負方向
 * 以上可以用相對於手機位置的右手坐標系來理解
 * 
 * Yaw - 圍繞 Y 軸旋轉
 * Pitch - 圍繞 X 軸旋轉
 * Roll - 圍繞 Z 軸旋轉
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;

using System.Windows.Navigation;
using Microsoft.Devices.Sensors;
using Microsoft.Xna.Framework;

namespace Demo.Device
{
    public partial class MotionDemo : PhoneApplicationPage
    {
        private Motion _motion;

        public MotionDemo()
        {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            // 判斷設備是否支 Motion API
            if (Motion.IsSupported)
            {
                lblMotionStatus.Text = "此設備支持 Motion API";
            }
            else
            {
                lblMotionStatus.Text = "此設備不支持 Motion API";

                btnStart.IsEnabled = false;
                btnStop.IsEnabled = false;
            }
        }

        private void btnStart_Click(object sender, RoutedEventArgs e)
        {
            if (_motion == null)
            {
                // 實例化 Motion,注冊相關事件
                _motion = new Motion();
                _motion.TimeBetweenUpdates = TimeSpan.FromMilliseconds(1);
                _motion.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<MotionReading>>(_motion_CurrentValueChanged);

                lblTimeBetweenUpdates.Text = "TimeBetweenUpdates 設置為 1 毫秒,實際為 " + _motion.TimeBetweenUpdates.TotalMilliseconds.ToString() + " 毫秒";
            }

            try
            {
                // 打開 Motion 監測
                _motion.Start();
                lblMotionStatus.Text = "Motion 監測已打開";
            }
            catch (Exception ex)
            {
                lblMotionStatus.Text = "Motion 監測打開失敗";
                MessageBox.Show(ex.ToString());
            }
        }

        private void btnStop_Click(object sender, RoutedEventArgs e)
        {
            if (_motion != null)
            {
                // 關閉 Motion 監測
                _motion.Stop();
                lblMotionStatus.Text = "Motion 監測已關閉";
            }
        }

        void _motion_CurrentValueChanged(object sender, SensorReadingEventArgs<MotionReading> e)
        {
            // 注:此方法是在后台線程運行的,所以需要更新 UI 的話注意要調用 UI 線程
            Dispatcher.BeginInvoke(() => UpdateUI(e.SensorReading));
        }

        // 更新 UI
        private void UpdateUI(MotionReading motionReading)
        {
            AttitudeReading attitude = motionReading.Attitude;
            Vector3 deviceAcceleration = motionReading.DeviceAcceleration;
            Vector3 deviceRotationRate = motionReading.DeviceRotationRate;
            Vector3 gravity = motionReading.Gravity;

            // 在 UI 上顯示相關參數
            lblMsg.Text = "yaw: " + MathHelper.ToDegrees(attitude.Yaw).ToString("0.0");
            lblMsg.Text += Environment.NewLine;
            lblMsg.Text += "pitch: " + MathHelper.ToDegrees(attitude.Pitch).ToString("0.0");
            lblMsg.Text += Environment.NewLine;
            lblMsg.Text += "roll: " + MathHelper.ToDegrees(attitude.Roll).ToString("0.0");
        }
    }
}



OK
[源碼下載]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM