Using the Gyroscope Sensor

,

The gyroscope sensor is not a required component of Windows Phone devices. It is therefore important to verify that it is supported before attempting to use it. For this, the static Gyroscope.IsSupported property is used, as demonstrated in the GyroscopeViewModel class (see Listing 16.9). The Start method of the GyroscopeViewModel oversees the creation of the Gyroscope instance.

The default value of the Gyroscope’s TimeBetweenUpdates property is 20 milliseconds, which on my test device was the minimum allowed value.

As with all sensor types, the CurrentValueChanged event is used to receive periodic updates from the sensor.

LISTING 16.9. GyroscopeViewModel.Start Method


public void Start()
{
    if (!Gyroscope.IsSupported)
    {
        MessageService.ShowMessage(
            "Gyroscope is not supported on this device.");
        return;
    }

    gyroscope = new Gyroscope();
    gyroscope.TimeBetweenUpdates = TimeSpan.FromMilliseconds(20);
    gyroscope.CurrentValueChanged += HandleGyroscopeCurrentValueChanged;
    gyroscope.Start();
}


When the CurrentValueChanged event is raised, the event handler receives a SensorReadingEventArgs<GyroscopeReading> object. GyroscopeReading contains two properties: a Timestamp property of type DateTimeOffset, which indicates when the sensor reading was taken, and a RotationRate property of type Vector3, which retrieves the rotational velocity around each axis of the device (X, Y, and Z) in radians per second.

The handler for the compass’s CurrentValueChanged event in the GyroscopeViewModel converts the RotationRate property of the event arguments, which is of type Vector3, to a custom ThreeDimensionalVector instance and assigns it to the viewmodel’s RotationRate property (see Listing 16.10).

The viewmodel tracks the angular rotation of the device by accumulating the value of each reading into a ThreeDimensionalVector called cumulativeRotationRadians. The amount of rotation since the last CurrentValueChanged event is calculated by multiplying the rotation rate by the time since the last event was raised. Put simply: (radians/second) * secondsSinceLastReading = radiansSinceLastReading.

LISTING 16.10. HandleGyroscopeCurrentValueChanged Method


void HandleGyroscopeCurrentValueChanged(
    object sender, SensorReadingEventArgs<GyroscopeReading> e)
{
    GyroscopeReading reading = e.SensorReading;
    Vector3 rate = reading.RotationRate;
    RotationRate = new ThreeDimensionalVector(rate.X, rate.Y, rate.Z);

    if (lastUpdateTime.Equals(DateTimeOffset.MinValue))
    {
        lastUpdateTime = e.SensorReading.Timestamp;
        cumulativeRotationRadians = rotationRate;
        return;
    }

    TimeSpan timeSinceLastUpdate = e.SensorReading.Timestamp - lastUpdateTime;

    cumulativeRotationRadians
                      += rotationRate * (timeSinceLastUpdate.TotalSeconds);
    CumulativeRotation = new RotationAngles(
        MathHelper.ToDegrees((float)cumulativeRotationRadians.X),
        MathHelper.ToDegrees((float)cumulativeRotationRadians.Y),
        MathHelper.ToDegrees((float)cumulativeRotationRadians.Z));

    lastUpdateTime = e.SensorReading.Timestamp;
}


The viewmodel’s CumulativeRotation property is of type RotationAngle, a simple custom class with three read-only properties: X, Y, and Z, all of which are of type double.

As with most of the examples in this chapter, the page calls the viewmodel’s Start method within its OnNavigatedTo method and calls the Stop method within its OnNavigatedFrom method.

The Stop method of the viewmodel disposes the Gyroscope instance, as shown:

public void Stop()
{
    if (gyroscope == null)
    {
        return;
    }

    gyroscope.Stop();
    gyroscope.CurrentValueChanged -= HandleGyroscopeCurrentValueChanged;
    gyroscope.Dispose();
    gyroscope = null;
}

The GyroscopeView page contains TextBlock elements that display both the raw reading values in radians/second and the accumulated angular rotation values in degrees.

The cumulative rotation values serve to rotate colored rectangles. As the device is rotated, a RotateTransform is applied to each rectangle, as shown:

<Canvas Width="400" Height="400" Margin="0,50,0,0">
    <Ellipse Width="400" Height="400" StrokeThickness="2"
                Stroke="{StaticResource PhoneSubtleBrush}" />
    <Rectangle Canvas.Left="195" Canvas.Top="0"
                Width="10" Height="200" Fill="Honeydew">
        <Rectangle.RenderTransform>
            <RotateTransform Angle="{Binding CumulativeRotation.X}"
                            CenterX="5" CenterY="200" />
        </Rectangle.RenderTransform>
    </Rectangle>
    <Rectangle Canvas.Left="195" Canvas.Top="0"
                Width="10" Height="200" Fill="Red">
        <Rectangle.RenderTransform>
            <RotateTransform Angle="{Binding CumulativeRotation.Y}"
                            CenterX="5" CenterY="200" />
        </Rectangle.RenderTransform>
    </Rectangle>
    <Rectangle Canvas.Left="195" Canvas.Top="0"
                Width="10" Height="200" Fill="Orange">
        <Rectangle.RenderTransform>
            <RotateTransform Angle="{Binding CumulativeRotation.Z}"
                            CenterX="5" CenterY="200" />
        </Rectangle.RenderTransform>
    </Rectangle>
</Canvas>

Figure 16.7 shows the GyroscopeView page with the rotation of the device across three dimensions indicated by the three colored lines.

Image

FIGURE 16.7 GyroscopeView page.

You may notice, while running the sample, that the cumulative rotation drifts over time. This drift is indicative of the main disadvantage of the gyroscope; the gyroscope measures changes in angular rotation, and not the absolute angular rotation of the device. This is where the Accelerometer has an advantage, because it can provide the same rotational information without drift. In the case of the accelerometer, however, the magnitude of the signal is biased by gravity. This is not the case with the gyroscope.

The next section explores the Motion class, which promises to overcome the disadvantages of the individual sensors by unifying them into a single software virtual sensor.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.76.234