Windows Phone Mango–What’s New? (“New Sensors & Tooling Enhancements” – Part 3 of 8)

May 24, 2011

Windows Phone devices are modern devices. As such, they usually have few sensors such as built-in accelerometer, A-GPS, light sensor, magnetometer, etc. Windows Phone minimum hardware spec requires that all Windows Phone will have at least 4 of them – A-GPS, Accelerometer, Compass and Light sensors. While accelerometer and A-GPS were available for developers with first version of Windows Phone, there are some new sensors which were added with Mango. The hardware market is not standing still, thus we could see much advanced sensors coming out on the modern phone models. Some of those sensors (like gyro for example) were added to Mango API. The table below provides quick compare between RTM and Mango sensors support:







































Sensor Windows Phone RTM Windows Phone Mango
Accelerometer Yes Yes
Microphone Yes Yes
A-GPS Yes Yes
Camera Yes Yes
Compass No Optional
Gyro No Optional
Motion No Optional
FM Radio Yes Yes

In some case, even when the sensor hardware component installed on the device it doesn’t mean that is have the managed (.NET) API to access it (for example light sensor).


Mango tools provide better developers support while developing sensors-enables application. In previous release developing accelerometer-enabled or A-GPS-enabled (location-aware) applications required real developer-unlocked phone device or some community solution to emulate sensors input. With Mango release this support provided by Windows Phone Emulator. To emulate accelerometer or location readings open “Additional Tools” windows of emulator:


image


The opened “Addition Tools” window enables accelerometer and location changes emulation. To simulate the accelerometer data, move the pink “ball” with you mouse:


image


The Location tab enables not only to send current location to the Windows Phone Emulator, but also to record the geographical point and send them at given time interval to emulate the device movement:


image


One important note here: while the Windows Phone Emulator provides you a way to simulate the accelerometer and GPS location data, it is advised to check your application also in real device, since real sensors data is subject to environmental influence, network availability, magnetic fields, etc. Always check you application on the real device to see how it behaves under real-world conditions.


Now let’s get back to the sensors. I will cover the changes (or actually additions) to he Camera in next post and focus to new sensors in this post.


All sensor classes in Mango derive from single base class, SensorBase<T>, which makes developer life really easy. All the sensors will be initialized and operated the same way. Only the events and readings data vary between different sensors.


Let’s see common parts of sensors interface:



























Base Class Member Info
CurrentValue Property, contains current value of the sensor
IsDataValid Property, contains the validity of the sensor’s data
CurrentValueChanged Event, occurs when new data arrives from the sensor
TimeBetweenUpdates Property, gets or sets the preferred time between CurrentValueChanged events
Start Function, starts acquisition of data from the sensor
Stop Function, stops acquisition of data from the sensor
Dispose Function, releases the managed and unmanaged resources used by the sensor

In general, the pattern to work with the sensor should be as the following:


1. The sensor variable defined at the class level and available for all functions in the class (page).

//Class level variable
Motion motion;

2. Activate the sensor at the latest possible time. Usually OnNavigatedTo event handler is good place for it:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
if (Motion.IsSupported)
{
motion = new Motion();
//Subscribe to sensor-specific events
motion.Calibrate += new EventHandler<CalibrationEventArgs>(motion_Calibrate);
motion.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<MotionReading>>(motion_CurrentValueChanged);
motion.Start();
//…
}
else
//Always have a backup plan for non-supported sensor scenario!
//…

base.OnNavigatedTo(e);
}

Subscribe to sensor-specific events (only those you actually need) and always have a backup plan when the sensor is not supported on the device.


3. Release the sensor at earliest possible time and unsubscribe from events:

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
//If sensor were initialized
if (null != motion)
{
//Unsubscribe from sensor-specific events
motion.Calibrate -= motion_Calibrate;
motion.CurrentValueChanged -= motion_CurrentValueChanged;
//Stop the readings flow and release
motion.Stop();
motion.Dispose();
motion = null;
}
base.OnNavigatedFrom(e);
}

4. Keep in mind, that the CurrentValueChanged (and other) event handlers will not arrive on UI thread. If your code need to change some on-screen element properties, use Dispatcher:

void motion_CurrentValueChanged(object sender, SensorReadingEventArgs<MotionReading> e)
{
//Schedule UI related work to dispatcher queue
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
imageProjection.RotationY = e.SensorReading.Attitude.Pitch * bankLimit;
imageProjection.RotationX = e.SensorReading.Attitude.Roll * angleOfAttackLimit;
imageProjection.RotationZ = e.SensorReading.Attitude.Yaw * yawLimit;
});
}

In addition to the base class members, all sensors adds some specific logic and functionality. The sample code above represents Motion sensor functionality. This sensor is a new virtual sensor which combines gyroscope, compass and accelerometer reading with some mathematic calculations needed to identify the device orientation, device movement, the gravity, etc. Those values are ready to be consumed by the applications. The motion sensors gives most accurate information since it combines all sensors and eliminates possible sensor accuracy problems when single sensor is used. This sensor is recommended to use when available.


The availability of this sensor and the readings quality depends on availability of other sensors and represented below:




























Accelerometer Compass Gyroscope Motion
Yes Yes Yes Yes, full quality
Yes Yes No Yes, degraded quality
Yes No Yes No
Yes No No No

Compass sensor (aka magnetometer sensor) the following data to the application:



  • HeadingAccuracy — The accuracy of compass heading readings in degrees. We will use this value later for compass calibration

  • MagneticHeading — The compass heading relative to Earth’s magnetic north (provided in degrees)

  • TrueHeading — The compass heading relative to Earth’s geographic north (provided in degrees)

  • MagnetometerReading — The raw magnetometer reading values in microteslas (values provided in XNA’s Vector3 type. To use those readings you are required to add a reference to Microsoft.Xna.Framework assembly)

In addition, compass sensor enables application to subscribe to the Calibrate event, since magnetometer sensor which used to implement the compass is subject to external interference. Metal obstacles, high-voltage electrical installations and some electronic devices could interfere with Earth’s magnetic field and change the local magnetic field’s values. In case the sensor needs to be calibrated and the compass API fires the Calibrate event. When this event fired the application have to present the UI with instructions to perform sensor calibration. Sensor calibration performed by waving the device in figure 8 pattern:


image


The API doesn’t provide any “CalibrationComplete” notification, and it is up to developer to decide when data accuracy sufficient to the application. In general, HeadingAccuracy below 10-15 degrees should enough for most applications. This means that your calibration code should look like the follows:

void compass_Calibrate(object sender, CalibrationEventArgs e)
{
//Show calibration instructions
stkCalibration.Visibility = Visibility.Visible;
//Hide compass sensor related UI
imgRose.Visibility = Visibility.Collapsed;
//Set “Is Calibrating” flag to consume it later
compassCalibrating = true;
}

Then, in CurrentValueChanged event handler check if compass already calibrated to hide the calibrating instructions:

void compass_CurrentValueChanged(object sender, SensorReadingEventArgs<CompassReading> e)
{
//Check is compass is calibrating
if (compassCalibrating)
{
//Check if current HeadingAccuracy below threshold value
if (e.SensorReading.HeadingAccuracy < 10)
{
//Compass calibrated, restore the compass UI
compassCalibrating = false;

//The compass reading are not guaranteed to arrive in UI thread
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
imgRose.Visibility = Visibility.Visible;
stkCalibration.Visibility = Visibility.Collapsed;
ContentPanel.Background = new SolidColorBrush(Colors.Transparent);
});
}
}

if (!compassCalibrating)
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
imageRotation.Angle = e.SensorReading.TrueHeading;
});
}


This code hides the calibration UI and display the compass UI I’m using in this sample:


image


Note: same calibration procedures applies also on motion sensor


Last new sensor in Mango is a Gyroscope. A gyroscope is a device for measuring or maintaining orientation, based on the principles of conservation of angular momentum. In Mango, Gyroscope API provides the rotational velocity around each one of 3 axis (X, Y and Z) of the device in radians per second.


Note: Since gyroscope is relatively rare sensor in current generation of Windows Phone devices it very important to have a fallback plan in case it is not supported


The GyroscopeReading class (an instance of CurrentValue) class provides us with gyroscope’s RotationRate – the rotational velocities around each one of 3 axis of the device, and Timestamp which indicates when the reading was taken.


That’s it about new sensors in Mango. Sample used to demonstrate it hosted here.


Stay tuned to the part 4 – “Camera”


Alex

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

4 comments

  1. Jimmy EngströmMay 25, 2011 ב 11:20

    Hi
    Great article.
    When I run the sample code in the emulator it says compass not supported, is there a way to fake compass readings right now?
    Is there some other way like a hardware compass i can connect to my computer?

    Cheers
    /Jimmy

    Reply
  2. Alex GoleshMay 25, 2011 ב 11:31

    No, unfortunately. You have to have a real device with this sensor :(

    Reply
  3. Jimmy EngströmMay 25, 2011 ב 12:00

    So I have to wait for Mango to be released for developers (or public) to be able to test the compass?
    hmm I was afraid of that, well I guess I need to build some kind of fake class.
    Thanks

    Reply
  4. Alex GoleshMay 25, 2011 ב 12:26

    Not yet… Sorry…

    Reply