Georg fährt extra nach Berlin um Steve Ballmer zu treffen

31 Tage Mango | Tag #5: Das Gyroskop

Die­ser Arti­kel ist Tag #5 der Serie 31 Tage Man­go von Jeff Blan­ken­burg.

Der Ori­gi­nal­ar­ti­kel befin­det sich hier: Day #5: Gyro­scope.

Heu­te reden wir über einen neu­en Sen­sor, das Gyro­skop. Die­ser Sen­sor wird nur in Gerä­ten ver­füg­bar sein, die nach dem Man­go Start erschie­nen sind und sogar dann wird er nicht in allen Gerä­ten vor­han­den sein. Da das Gyro­skop aber ein mäch­ti­ger Sen­sor ist, soll­ten wir von ihm Gebrauch machen, wenn er zur Ver­fü­gung steht.

Was ist ein Gyroskop?

Laut Wiki­pe­dia wer­den Gyro­sko­pe „als Navi­ga­ti­ons­in­stru­men­te sowie zur akti­ven Lage­re­ge­lung ein­ge­setzt“. Vie­le von Ihnen wer­den ein Gyro­skop (auch „Krei­sel­instru­ment“) schon ein­mal gese­hen haben. Hier ist trotz­dem eine klei­ne Illus­tra­ti­on eines phy­si­ka­li­schen Krei­sel­instru­ments (von der eng­li­schen Wiki­pe­dia-Sei­te):

Wie Sie sehen, kann es sich um alle drei Ach­sen X, Y, und Z dre­hen (ähn­lich wie der Acce­le­ro­me­ter, den wir in Day #11 of the 31 Days of Win­dows Pho­ne behan­delt haben). Wäh­rend der Acce­le­ro­me­ter Beschleu­ni­gung misst, dient das Gyro­skop der Bestim­mung der Dreh­ge­schwin­dig­keit.

Ein Tele­fon ent­hält natür­lich nicht einen phy­si­ka­li­schen Krei­sel wie er oben abge­bil­det ist. Tele­fo­ne benut­zen ein soge­nann­tes MEMS Gyro­skop. Die­se Sen­so­ren nut­zen in der Regel Vibra­tio­nen oder Reso­nanz zur Bestim­mung der Dreh­ge­schwin­dig­keit.

Das Gyroskop benutzen

Das Gyro­skop ist prin­zi­pi­ell so ein­fach zu benut­zen wie der Acce­le­ro­me­ter. Im Gegen­satz zum Acce­le­ro­me­ter haben wir aller­dings den Nach­teil, dass es kein Simu­la­ti­ons-Werk­zeug im Emu­la­tor gibt. Das Gyro­skop misst Dreh­ge­schwin­dig­keit und lie­fert die­se Daten in Radi­an pro Sekun­de.

Mit die­sem Sen­sor lässt sich die aktu­el­le Aus­rich­tung des Tele­fons also prä­zi­ser und „wei­cher“ bestim­men. Beson­ders nütz­lich kann das wer­den, wenn man Aug­men­ted Rea­li­ty Anwen­dun­gen baut. Aller­dings wird man in den meis­ten Fäl­len gar nicht direkt auf das Gyro­skop zugrei­fen. Das hat fol­gen­de Grün­de:

  • Nicht alle Win­dows Pho­nes haben ein Gyro­skop. Nur Gerä­te, die nach Man­go erschie­nen sind kön­nen ein Gyro­skop ver­baut haben und sogar nach Man­go bleibt die­ser Sen­sor eine optio­na­le Hard­ware­kom­po­nen­te.
  • Micro­soft hat eine Moti­on Klas­se ent­wi­ckelt, die die Daten des Acce­le­ro­me­ters, des Kom­pas­ses und des even­tu­ell vor­han­de­nen Gyro­skops in einer API ver­eint und die damit wesent­lich prak­ti­scher in der Benut­zung ist (die­se Klas­se wer­den wir mor­gen behan­deln). Wenn Sie an der aktu­el­len Lage (also Nei­gung, Gie­rung und Dre­hung) des Geräts inter­es­siert sind, ist es sinn­vol­ler, sich auf die Moti­on Klas­se zu kon­zen­trie­ren.

Wenn man den­noch direk­ten Zugriff auf das Gyro­skop unab­hän­gig von der Moti­on Klas­se braucht, soll­te man immer über­prü­fen, ob das aktu­el­le Gerät die­sen Sen­sor über­haupt unter­stützt. Hier­für brau­chen wir zwei Stück­chen Code. Ers­tens fügen wir ein using State­ment für den Microsoft.Phone.Sensors Name­space hin­zu. Zwei­tens brau­chen wir ein if State­ment, wel­ches den Wert von Gyroscope.IsSupported über­prüft. Bis­her sieht unse­re Code-behind Datei also so aus:

using System;
using Microsoft.Phone.Controls;
using Microsoft.Devices.Sensors;
using Microsoft.Xna.Framework;

namespace Day5_Gyroscope
{
   public partial class MainPage : PhoneApplicationPage
   {
      public MainPage()
      {
         InitializeComponent();

         if (Gyroscope.IsSupported)
         {
            // DO SOMETHING
         }
      }
   }
} 

Jetzt müs­sen wir nur noch die Stel­le mit dem Kom­men­tar „DO SOMETHING“ mit Leben fül­len. Dazu defi­nie­ren wir uns zunächst eine Benut­zer­schnitt­stel­le, die die Daten des Gyro­skops dar­stel­len wird.

In der obi­gen Benut­zer­schnitt­stel­le haben wir drei Text­Block Ele­men­te, wel­che uns die Roh­da­ten aus­ge­ben wer­den und drei Lini­en, wel­che jeweils den Aus­schlag eines der Wer­te reprä­sen­tie­ren wer­den. Um die­se Ober­flä­che nach­zu­bau­en, nut­zen Sie das fol­gen­de XAML in Ihrer Sei­te:

<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="31 DAYS OF MANGO" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="gyroscope" 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">
            <TextBlock Height="30" HorizontalAlignment="Left" Margin="20,100,0,0" Name="xTextBlock" Text="X: 1.0" VerticalAlignment="Top" Foreground="Red" FontSize="28" FontWeight="Bold"/>
            <TextBlock Height="30" HorizontalAlignment="Center" Margin="0,100,0,0" Name="yTextBlock" Text="Y: 1.0" VerticalAlignment="Top" Foreground="Yellow" FontSize="28" FontWeight="Bold"/>
            <TextBlock Height="30" HorizontalAlignment="Right" Margin="0,100,20,0" Name="zTextBlock" Text="Z: 1.0" VerticalAlignment="Top" Foreground="Blue" FontSize="28" FontWeight="Bold"/>
            <Line x:Name="xLine" X1="240" Y1="350" X2="340" Y2="350" Stroke="Red" StrokeThickness="4"></Line>
            <Line x:Name="yLine" X1="240" Y1="350" X2="240" Y2="270" Stroke="Yellow" StrokeThickness="4"></Line>
            <Line x:Name="zLine" X1="240" Y1="350" X2="190" Y2="400" Stroke="Blue" StrokeThickness="4"></Line>
            <TextBlock Height="30" HorizontalAlignment="Center" Margin="6,571,6,0" Name="statusTextBlock" Text="" VerticalAlignment="Top" Width="444" />
        </Grid>
</Grid> 

Im fol­gen­den Code­bei­spiel über­prü­fen wir zunächst, ob das Gyro­skop von der Hard­ware unter­stüzt wird, indem wir Gyroscope.IsSupported abfra­gen. Danach erstel­len wir ein neu­es Gyro­scope Objekt und einen Event Hand­ler für Cur­rentVa­lue­Ch­an­ged.

using System;
using Microsoft.Phone.Controls;
using Microsoft.Devices.Sensors;
using Microsoft.Xna.Framework;

namespace Day5_Gyroscope
{
   public partial class MainPage : PhoneApplicationPage
   {
      Gyroscope g;
        
      public MainPage()
      {
         InitializeComponent();

         if (Gyroscope.IsSupported)
         {
            g = new Gyroscope();
            g.TimeBetweenUpdates = TimeSpan.FromMilliseconds(20);
            g.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<GyroscopeReading>>(g_CurrentValueChanged);
            g.Start();
         }
         else statusTextBlock.Text = "gyroscope not supported";
      }

      void g_CurrentValueChanged(object sender, SensorReadingEventArgs<GyroscopeReading> e)
      {
         Dispatcher.BeginInvoke(() => UpdateUI(e.SensorReading));
      }

      private void UpdateUI(GyroscopeReading gyroscopeReading)
      {
         statusTextBlock.Text = "getting data";
         Vector3 rotationReading = gyroscopeReading.RotationRate;

         xTextBlock.Text = "X " + rotationReading.X.ToString("0.00");
         yTextBlock.Text = "Y " + rotationReading.Y.ToString("0.00");
         zTextBlock.Text = "Z " + rotationReading.Z.ToString("0.00");

         xLine.X2 = xLine.X1 + rotationReading.X * 200;
         yLine.Y2 = yLine.Y1 - rotationReading.Y * 200;
         zLine.X2 = zLine.X1 - rotationReading.Z * 100;
         zLine.Y2 = zLine.Y1 + rotationReading.Z * 100;
      }
   }
} 

Wie schon beim Kom­pass feu­ert der Event Hand­ler des Gyro­skops sobald nach der in Time­Bet­ween­Up­dates fest­ge­leg­ten War­te­zeit ein neu­er Wert fest­ge­stellt wur­de. In unse­rem Bei­spiel wer­den wir also Aktua­li­sie­run­gen nicht öfter bekom­men als alle 20 Mil­li­se­kun­den.

Sie wer­den mög­li­cher­wei­se über die­se Zei­le gestol­pert sein:

Dispatcher.BeginInvoke(() => UpdateUI(e.SensorReading));

Der Grund für die­se Zei­le ist, dass der Event Hand­ler nicht auf dem UI Thread auf­ge­ru­fen wird um die­sen nicht zu blo­ckie­ren. Um also die Benut­zer­ober­flä­che zu aktua­li­sie­ren, müs­sen wir erst wie­der den UI Thread benach­rich­ti­gen (mit Hil­fe der Metho­de Dispatcher.BeginInvoke) (Anm. leit­ning: die­ser Absatz lau­tet im Orgi­nal­ar­ti­kel anders. Ich habe hier geschrie­ben, war­um mei­ner Mei­nung nach Dispatcher.BeginInvoke auf­ge­ru­fen wird und las­se mich ger­ne eines Bes­se­ren beleh­ren).

Wir über­ge­ben das gan­ze Gyro­scope­Rea­ding Objekt an die Metho­de UpdateUI (Anm. leit­ning: wel­che auf dem UI Thread aus­ge­führt wird). Die­ses Objekt erlaubt uns, die Wer­te von X, Y und Z aus dem Vector3 der Rota­ti­on­Ra­te Eigen­schaft aus­zu­le­sen. Wir zei­gen die Wer­te in den Text­Block Fel­dern an. Die eigent­lich coo­le Visua­li­sie­rung pas­siert aller­dings über die Line Ele­men­te, die wir zuvor im XAML erstellt haben.

Jede der Lini­en soll jeweils einen der Daten­punk­te reprä­sen­tie­ren (die rote Linie ist für X, die gel­be ver­ti­ka­le Linie reprä­sen­tiert Y und die blaue dia­go­na­le Linie steht für Z). Die Län­ge einer Linie soll jeweils die Rota­ti­ons­ge­schwin­dig­keit des Geräts dar­stel­len. Bei jedem Auf­ruf der Metho­de UpdateUI ver­län­gern oder ver­kür­zen wir die Lini­en ent­spre­chend der Daten des Gyro­skops. Damit erhal­ten wir einen Ein­druck davon, wel­cher Rota­ti­on unser Gerät gera­de aus­ge­setzt ist.

Bit­te beden­ken Sie, dass der Bei­spiel­code die­ses Arti­kels nur auf einem Gerät lau­fen wird, wel­ches auch ein Gyro­skop ein­ge­baut hat. Der Emu­la­tor sowie alle Win­dows Pho­nes der ers­ten Genera­ti­on haben die­sen Sen­sor nicht. Hier ist ein klei­nes Video von einem Gerät mit einem Gyro­skop:

Zusammenfassung

Das Gyro­skop ist ein prak­ti­scher klei­ner Sen­sor. Er lie­fert uns ein sehr prä­zi­ses Bild der Bewe­gung des Geräts im Raum. Das kann beson­ders für Aug­men­ted Rea­li­ty Anwen­dun­gen nütz­lich sein. Wenn Sie die Bei­spiel­an­wen­dung die­ses Arti­kels her­un­ter­la­den möch­ten, drü­cken Sie auf den Down­load Code But­ton unten:

Micro­soft hat in Win­dows Pho­ne 7.5 eine neue Klas­se mit dem Namen Moti­on ein­ge­führt. Die­se ver­eint die Daten des Gyro­skops, des Acce­le­ro­me­ters und des Kom­pas­ses und lie­fert dadurch Daten mit erstaun­li­cher Genau­ig­keit. Die Moti­on Klas­se wird Gegen­stand des mor­gi­gen Arti­kels sein. Wir wer­den die­se Klas­se im Detail behan­deln und uns bei­spiels­wei­se anschau­en, wie man die aktu­el­le Lage (also Nei­gung, Gie­rung und Dre­hung) des Geräts ermit­teln kann.

Bis dahin!

4 Kommentare

  • Hal­lo,
    wel­ches Gerät ist das auf dem Video?
    Das HTC Titan scheint mir lei­der das ein­zi­ge WP7 Smart­pho­ne zu sein wel­ches ein Gyro­skop ver­baut hat oder täu­sche ich mich da? Das auf dem video sieht nämich deut­lich klei­ner aus…

  • Ich weiß auch nicht, wel­ches Gerät da im Video zu sehen ist. In den Kom­men­ta­ren zum Ori­gi­nal­ar­ti­kel schreibt Jeff, dass das HTC Titan und das Sam­sung Focus S ein Gyro­skop haben müss­ten.

  • Wel­che Genau­ig­keit ist mit dem Kom­pass auf einem OMNIA7 zu errei­chen? Genau­er als die Anzei­ge „10Grad“ habe ich noch nie geschafft. Ist das das Ende der Mög­lich­kei­ten?

  • Hi Uwe,

    ich habe sel­ber ein Omnia 7 und bei mir funk­tio­niert der Kom­pass über­haupt nicht — auch wenn ich eine der Kom­pass Apps aus dem Mar­ket­place aus­pro­bie­re. Viel­leicht ist das ja ein gene­rel­les Pro­blem beim Omnia 7.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert