owen gerig
owen gerig

Reputation: 6172

motion sensor, reading rotations

I have tried this project on both android and ios with little success. There is a good chance that this stuff is just over my head. However I figured I would post my question on here as a last effort.
I'm trying to figure out when a device is rotated or flipped. My app should know when it did a 180, 360 or if the device was flipped vertically.
In an attempt to understand the way its suppose to work I tried downloading two example projects: AccelerometerGraph and CoreMotionTeapot. With these and a mix of other stuff I have figured out I was trying this:

motionManager = [[CMMotionManager alloc] init]; 
motionManager.accelerometerUpdateInterval = 0.01;
motionManager.deviceMotionUpdateInterval = 0.01;
[motionManager startDeviceMotionUpdates];

if (motionManager.gyroAvailable) {
    motionManager.gyroUpdateInterval = 1.0/60.0;
        motionManager.deviceMotionUpdateInterval = 0.01;
    [motionManager startGyroUpdatesToQueue:[NSOperationQueue currentQueue]
                               withHandler: ^(CMGyroData *gyroData, NSError *error)
     {
         CMRotationRate rotate = gyroData.rotationRate;
         NSLog(@"rotation rate = [%f, %f, %f]", rotate.x, rotate.y, rotate.z);
     }];
} else {
    NSLog(@"No gyroscope on device.");
}

But I do not know how to gather the requested information(horizontal and vertical rotations) from these three values (x ,y, z).

Upvotes: 5

Views: 8627

Answers (4)

moxy
moxy

Reputation: 1624

Then maybe what you're looking for is just the device orientation. You should look at the UIDevice Class Reference. In particular the

– beginGeneratingDeviceOrientationNotifications
– endGeneratingDeviceOrientationNotifications

methods.

and use it like this :

[UIDevice currentDevice].orientation

You'll get in return these possible values :

typedef enum {
    UIDeviceOrientationUnknown,
    UIDeviceOrientationPortrait,
    UIDeviceOrientationPortraitUpsideDown,
    UIDeviceOrientationLandscapeLeft,
    UIDeviceOrientationLandscapeRight,
    UIDeviceOrientationFaceUp,
    UIDeviceOrientationFaceDown
} UIDeviceOrientation;

So you'll be able to check if it's in portrait (up or down) or landscape (left or right) and if it has been flipped.

You'll be able to implement the following methods :

- willRotateToInterfaceOrientation
- didRotateToInterfaceOrientation

You can look in this link to check how you can implement the methods.

Upvotes: 0

Raphael Ayres
Raphael Ayres

Reputation: 894

It all depends on the iPhone position. Say, if the phone gets flipped 360 around the y axis, the compass won't change 'cos it will still be pointing the same way during the flip. And that's not just it. My hint is that you log the accelerometer and compare the data you've collected with the movement made, and then, identify the stages of the trick and make a list of stages for each trick.

Upvotes: 0

moxy
moxy

Reputation: 1624

from the apple's documentation : CMMotionManager Class Reference (sorry lot of reading, i've bolded some sentences for quick over-reading)

After creating an instance of CMMotionManager, an application can use it to receive four types of motion: raw accelerometer data, raw gyroscope data, raw magnetometer data, and processed device-motion data (which includes accelerometer, rotation-rate, and attitude measurements). The processed device-motion data provided by Core Motion’s sensor fusion algorithms gives the device’s attitude, rotation rate, calibrated magnetic fields, the direction of gravity, and the acceleration the user is imparting to the device.

Important An application should create only a single instance of the CMMotionManager class. Multiple instances of this class can affect the rate at which data is received from the accelerometer and gyroscope. An application can take one of two approaches when receiving motion data, by handling it at specified update intervals or periodically sampling the motion data. With both of these approaches, the application should call the appropriate stop method (stopAccelerometerUpdates, stopGyroUpdates, stopMagnetometerUpdates, and stopDeviceMotionUpdates) when it has finished processing accelerometer, rotation-rate, magnetometer, or device-motion data.

Handing Motion Updates at Specified Intervals To receive motion data at specific intervals, the application calls a “start” method that takes an operation queue (instance of NSOperationQueue) and a block handler of a specific type for processing those updates. The motion data is passed into the block handler. The frequency of updates is determined by the value of an “interval” property.

Accelerometer. Set the accelerometerUpdateInterval property to specify an update interval. Call the startAccelerometerUpdatesToQueue:withHandler: method, passing in a block of type CMAccelerometerHandler. Accelerometer data is passed into the block as CMAccelerometerData objects. Gyroscope. Set the gyroUpdateInterval property to specify an update interval. Call the startGyroUpdatesToQueue:withHandler: method, passing in a block of typeCMGyroHandler. Rotation-rate data is passed into the block as CMGyroData objects. Magnetometer. Set the magnetometerUpdateInterval property to specify an update interval. Call the startMagnetometerUpdatesToQueue:withHandler: method, passing a block of type CMMagnetometerHandler. Magnetic-field data is passed into the block as CMMagnetometerData objects. Device motion. Set the deviceMotionUpdateInterval property to specify an update interval. Call the or startDeviceMotionUpdatesUsingReferenceFrame:toQueue:withHandler: or startDeviceMotionUpdatesToQueue:withHandler: method, passing in a block of type CMDeviceMotionHandler. With the former method (new in iOS 5.0), you can specify a reference frame to be used for the attitude estimates. Rotation-rate data is passed into the block as CMDeviceMotion objects. Periodic Sampling of Motion Data To handle motion data by periodic sampling, the application calls a “start” method taking no arguments and periodically accesses the motion data held by a property for a given type of motion data. This approach is the recommended approach for applications such as games. Handling accelerometer data in a block introduces additional overhead, and most game applications are interested only the latest sample of motion data when they render a frame.

Accelerometer. Call startAccelerometerUpdates to begin updates and periodically access CMAccelerometerData objects by reading the accelerometerData property. Gyroscope. Call startGyroUpdates to begin updates and periodically access CMGyroData objects by reading the gyroData property. Magnetometer. Call startMagnetometerUpdates to begin updates and periodically access CMMagnetometerData objects by reading the magnetometerData property. Device motion. Call the startDeviceMotionUpdatesUsingReferenceFrame: or startDeviceMotionUpdates method to begin updates and periodically access CMDeviceMotion objects by reading the deviceMotion property. The startDeviceMotionUpdatesUsingReferenceFrame: method (new in iOS 5.0) lets you specify a reference frame to be used for the attitude estimates.

About gathering the data :

@property(readonly) CMGyroData *gyroData

Discussion If no gyroscope data is available, the value of this property is nil. An application that is receiving gyroscope data after calling startGyroUpdates periodically checks the value of this property and processes the gyroscope data.

So you should have something like

gyroData.rotationRate.x
gyroData.rotationRate.y
gyroData.rotationRate.z

by storing them and comparing them periodically you should be able to see if the device flipped around an axis, etc.

Upvotes: 0

quellish
quellish

Reputation: 21254

What you're attempting is not trivial, but is certainly possible. This video should be very helpful in understanding the capabilities of the device and how to get closer to your goal: http://www.youtube.com/watch?v=C7JQ7Rpwn2k

While he's talking about Android, the same concepts apply to the iPhone.

Upvotes: 1

Related Questions