Reaali Robootika.COM

NXT robotimaailm ja programmeerimine C-keeles

Windows Phone – Accelerometer, kiirendusandur

Windows Phone’i on sisse ehitatud kolmesuunaline kiirendusandur. Alljärgnevas rakenduses kasutatakse punase palli liigutamiseks kahte dimensiooni, kuid värvilised jooned ekraanil iseloomustavad telefoni liikumist kolmes erinevas suunas.

MSDN artikkel: http://msdn.microsoft.com/en-us/library/ff431810(v=vs.92).aspx 

Antud kood on internetinäidete põhjal kokku pandud kahest erinevast rakendusest – kolmemõõtmeliste joonte kuvamine ning palli edasi-tagasi sõitmine mööda ekraani.

How accelerometer is working–check it out!

MainPage.xaml

<phone:PhoneApplicationPage
   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"
   x:Class="AccelerometerTest.MainPage"
   mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
   FontFamily="{StaticResource PhoneFontFamilyNormal}"
   FontSize="{StaticResource PhoneFontSizeNormal}"
   Foreground="{StaticResource PhoneForegroundBrush}"
   SupportedOrientations="Portrait" Orientation="Portrait"
   shell:SystemTray.IsVisible="True">

    <Grid Name="MyGrid" Width="411" Height="768">
        <Line x:Name="xLine" X1="200" Y1="400" X2="260" Y2="400" Stroke="Red" StrokeThickness="4" Margin="0"/>
        <Line x:Name="yLine" X1="200" Y1="400" X2="200" Y2="340" Stroke="Green" StrokeThickness="4" Margin="0"/>
        <Line x:Name="zLine" X1="200" Y1="400" X2="260" Y2="340" Stroke="Blue" StrokeThickness="4" Margin="0"/>
        <Rectangle x:Name="Track" Height="80" Stroke="#FFC0C0C0"
            RadiusX="40" RadiusY="40" Margin="0" Width="410" />
        <Ellipse x:Name="Ball" Width="80" Height="80" Margin="0">
            <Ellipse.Fill>
                <RadialGradientBrush GradientOrigin="0.234,0.255">
                    <GradientStop Color="White"/>
                    <GradientStop Color="Red" Offset="0.759"/>
                </RadialGradientBrush>
            </Ellipse.Fill>
            <Ellipse.RenderTransform>
                <TranslateTransform x:Name="BallTransform" />
            </Ellipse.RenderTransform>
        </Ellipse>
        <TextBlock Height="50" HorizontalAlignment="Left" Margin="0" Name="textBlock1" Text="TextBlock" VerticalAlignment="Top" Width="200" />
        <TextBlock Height="50" HorizontalAlignment="Left" Margin="0,50,0,0" Name="textBlock2" Text="TextBlock" VerticalAlignment="Top" Width="200" />
        <TextBlock Height="50" HorizontalAlignment="Left" Margin="0,100,0,0" Name="textBlock3" Text="TextBlock" VerticalAlignment="Top" Width="200" />
    </Grid
>

</
phone:PhoneApplicationPage
>

MainPage.xaml.cs

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;
using Microsoft.Phone.Shell;

namespace AccelerometerTest
{
    public partial class MainPage : PhoneApplicationPage
    {
        private const int sum = 25;
        private const double gravity = 32.2; // raskusjõud (ft/sec2)
        private const double damping = 0.5;  // põrketugevus
        private const double mul = 128.0;    // palli liikumise tundlikkus
        private double _sx = 0.0;
        private double _sy = 0.0;
        private double _vx = 0.0;
        private double _vy = 0.0;
        private double _ax = 0.0;
        private double _ay = 0.0;
        private double _time = DateTime.Now.Ticks;
        private double width, height;
        private double time;

        private Accelerometer _accel = new Accelerometer();
        Vector3 acceleration;
        public MainPage()
        {
            InitializeComponent();

            //järgmised kaks rida on selle jaoks, et telefonile ei tuleks "lukku" peale
            PhoneApplicationService phoneAppService = PhoneApplicationService.Current;
            phoneAppService.UserIdleDetectionMode = IdleDetectionMode.Disabled;

            width = (Application.Current.Host.Content.ActualWidth - Ball.Width) / 2.0;
            height = (MyGrid.Height - Ball.Height) / 2.0;

            // Start acceleroemeter
            _accel.CurrentValueChanged +=
                new EventHandler<SensorReadingEventArgs<AccelerometerReading>>(OnReadingChanged);
            _accel.Start();
        }
        private void OnReadingChanged(object sender, SensorReadingEventArgs<AccelerometerReading> e)
        {
            time = e.SensorReading.Timestamp.Ticks;
            acceleration = e.SensorReading.Acceleration;
            Dispatcher.BeginInvoke(() => UpdateDisplay());
            // käivita UI thread 
        }

        private double calculate(double[] k) {
            double ysum = 0;
            for (int i = 0; i < sum; i++)
                ysum += k[i];
            return ysum;
        }
        private void UpdateDisplay()
        {
            //saadakse kätte kiirendused kolmes suunas
            double x = acceleration.X;
            double y = acceleration.Y;
            double z = acceleration.Z;

            //time on suurusjärgus 0,02 ja = (praegune aeg - eelmine aeg) / 10 000 000
            double ajavahemik = (time - _time) / 10000000.0;

            //ax = ((kiirendus * raskusjõud (1G)) + eelmine kiirendus) / 2
            // keskmine kiirendus kahe ajavahemiku vahel
            double ax = ((x * gravity) + _ax) / 2.0;
            double ay = ((y * gravity) + _ay) / 2.0;

            // vx (kiirus) = eelmine keskmine kiirus + (keskmine kiirendus * aeg [ehk hetkel keskmine kiirus])
            double vx = _vx + (ax * ajavahemik);
            double vy = _vy + (ay * ajavahemik);

            //palli uus asukoht teljel = eelmine asukoht + ((((eelmine kiirus + praegune kiirus) / 2 ) * aeg ) * kordaja=128)
            //lühemalt: palli uus asukoht = eelmine asukoht + käesoleva asukoht
            double sx = _sx + ((((_vx + vx) / 2.0) * ajavahemik) * mul);
            double sy = _sy - ((((_vy + vy) / 2.0) * ajavahemik) * mul);

            //alljärgnev arvutus tekitab põrkamise
            // kui asukoht on väiksem kui -laius. laius on pool ekraanilaiusest - palli läbimõõt
            //siis palli asukoht on minimaalne laius ja kiirus on -kiirus * 0,5
            //(see on siis kiiruse vähenemine poole võrra aga vastassuunas)
            if (sx < -width)
            {
               sx = -width;
               vx = -vx * damping;
           }
           else if (sx > width)
            {
               sx = width;
               vx = -vx * damping;
           }
            if (sy < -height)
            {
                sy = -height;
                vy = -vy * damping;
            }
            else if (sy > height)
            {
                sy = height;
                vy = -vy * damping;
            }
            // salvesta parameetrid järgmise tsükli tarvis
            _time = time;
            _ax = ax;
            _ay = ay;
            _vx = vx;
            _vy = vy;
            _sx = sx;
            _sy = sy;

            //tehakse transformX ning omistatakse sellele asukoha väärtus
            //tulemus on see, et pall liigub ettenähtud kohale
            BallTransform.X = sx;
            BallTransform.Y = sy;

            //joonistatakse kolmemõõtmelised värvilised jooned
            xLine.X2 = xLine.X1 + acceleration.X * 400;
            yLine.Y2 = yLine.Y1 - acceleration.Y * 400;
            zLine.X2 = zLine.X1 - acceleration.Z * 200;
            zLine.Y2 = zLine.Y1 + acceleration.Z * 200;

            //kuvatakse kiirendusnumbrid
            textBlock1.Text = "X: " + x.ToString("0.000");
            textBlock2.Text = "Y: " + y.ToString("0.000");
            textBlock3.Text = "Z: " + z.ToString("0.000");
        }
    }
}

Add comment

Loading