## Tuesday, November 22, 2011

### Gyroscope & Accelerometer - iOS SDK

Gyroscope : A gyroscope measures the rate at which a device rotates around each of the three spatial axes
Accelerometer : measures the acceleration of the device along each of the three spatial axes.

Access Accelerometer using UIAccelerometer

Configuring the accelerometer
#define kAccelerometerFrequency        50.0 //Hz
-(void)configureAccelerometer
{
UIAccelerometer*  theAccelerometer = [UIAccelerometer sharedAccelerometer];
theAccelerometer.updateInterval = 1 / kAccelerometerFrequency;
theAccelerometer.delegate = self;
// Delegate events begin immediately.
}

Receiving an accelerometer event
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
UIAccelerationValue x, y, z;
x = acceleration.x;
y = acceleration.y;
z = acceleration.z;
// Do something with the values.
}

It shows a simplified version of a low-pass filter.

This example uses a low-value filtering factor to generate a value that uses 10 percent of the
unfiltered acceleration data and 90 percent of the previously filtered value

Isolating the effects of gravity from accelerometer data
#define kFilteringFactor 0.1
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
// Use a basic low-pass filter to keep only the gravity component of each axis.
accelX = (acceleration.x * kFilteringFactor) + (accelX * (1.0 - kFilteringFactor));
accelY = (acceleration.y * kFilteringFactor) + (accelY * (1.0 - kFilteringFactor));
accelZ = (acceleration.z * kFilteringFactor) + (accelZ * (1.0 - kFilteringFactor));
// Use the acceleration data.
}

shows a simplified high-pass filter computation with constant effect of gravity.
Getting the instantaneous portion of movement from accelerometer data

#define kFilteringFactor 0.1
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
// Subtract the low-pass value from the current value to get a simplified high-pass filter
accelX = acceleration.x - ( (acceleration.x * kFilteringFactor) + (accelX * (1.0 - kFilteringFactor)) );
accelY = acceleration.y - ( (acceleration.y * kFilteringFactor) + (accelY * (1.0 - kFilteringFactor)) );
accelZ = acceleration.z - ( (acceleration.z * kFilteringFactor) + (accelZ * (1.0 - kFilteringFactor)) );
// Use the acceleration data.
}
Handling Accelerometer and Gycometer using COREMOTION

Core Motion is a system framework that obtains motion data from sensors on a device and presents that data to applications for processing.

Core Motion defines a manager class, CMMotionManager, and three classes whose instances encapsulate measurements of motion data of various types:
A CMAccelerometerData object encapsulates a data structure that records a measurement of device acceleration along the three spatial axes. This data derives from the accelerometer.
A CMGyroData object encapsulates a data structure that records a biased estimate of a device’s rate of rotation along the three spatial axes.
A CMDeviceMotion
object encapsulates processed device-motion data that derives from both the accelerometer and the gyroscope.

************Handling Accelerometer using CoreMotion************

To start receiving and handling accelerometer data, create an instance of the CMMotionManager class and call one of the following two methods on it:
After this method is called, Core Motion continuously updates the accelerometerData property of CMMotionManager with the latest measurement of accelerometer activity.
Before calling this method, the application assigns an update interval to the accelerometerUpdateInterval property. It also creates an instance of NSOperationQueue and implements a block of the CMAccelerometerHandler type that handles the accelerometer updates.

Configuring the motion manager and starting updates
- (void)startAnimation {
if (!animating) {
}
motionManager = [[CMMotionManager alloc] init]// motionManager is an instance variable
motionManager.accelerometerUpdateInterval = 0.01// 100Hz
memset(filteredAcceleration, 0sizeof(filteredAcceleration));
}

- (void)stopAnimation {
if (animating) {
}
}

Below code shows how the application, in this same method, gets the latest accelerometer data and runs it through a low-pass filter. It then updates the drawing model with the filtered acceleration values and renders its view.
Listing 4-8  Sampling and filtering accelerometer data

- (void)drawView {
// alpha is the filter value (instance variable)
filteredAcceleration[0] = filteredAcceleration[0] * (1.0-alpha) + newestAccel.acceleration.x * alpha;
filteredAcceleration[1] = filteredAcceleration[1] * (1.0-alpha) + newestAccel.acceleration.y * alpha;
filteredAcceleration[2] = filteredAcceleration[2] * (1.0-alpha) + newestAccel.acceleration.z * alpha;
[self updateModelsWithAcceleration:filteredAcceleration];
[renderer render];
}
Note: You can apply a low-pass or high-pass filter to acceleration values and thereby isolate the gravity and user-acceleration components:
To apply a low-pass filter, thereby isolating the gravity component,
To apply a high-pass filter, thereby isolating the user-acceleration component

*******Handling Gyroscope Using CORE MOTION*******

To start receiving and handling rotation-rate data, create an instance of the CMMotionManager class and call one of the following two methods on it:

After this method is called, Core Motion continuously updates the gyroData property of CMMotionManager with the latest measurement of gyroscope activity.

Before calling this method, the application assigns an update interval to the gyroUpdateInterval property.

It also creates an instance of NSOperationQueue and implements a block of the CMGyroHandler type that handles the gyroscope updates.

Creating the CMMotionManager object and setting up for gyroscope updates
motionManager = [[CMMotionManager alloc] init];
motionManager.gyroUpdateInterval = 1.0/60.0;
if (motionManager.gyroAvailable) {
opQ = [[NSOperationQueue currentQueue] retain];
gyroHandler = ^ (CMGyroData *gyroData, NSError *error) {
CMRotationRate rotate = gyroData.rotationRate;
// handle rotation-rate data here......
};
} else {
NSLog(@"No gyroscope on device.");
toggleButton.enabled = NO;
[motionManager release];
}
}