5

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).

owen gerig
  • 6,165
  • 6
  • 52
  • 91
  • Exactly what kind of rotation are you looking for? For example the easiest situation would be that the phone is laying with the screen upward on the table and when you put it with the screen down it has rotated 180 degrees (around any axis). But what constitutes a 90 degree rotation? Is it on it's side? Is it standing upright? Or are you looking for a solution whereby you're holding your device in a random orientation and you want to know when it has rotated 180 degrees in any direction within, say, 2 seconds? I.e. a very general solution, but very interesting :) – Desmond Feb 02 '12 at 15:18
  • 3
    By no means was I trying to pry your idea from you. :) I'm sorry about that. But I do understand your problem now. It can be done, but this is a tricky one to do and it is doubtful a 'simple' answer on stackoverflow.com will do. You have intrigued me though, sounds like a lot of fun to build! – Desmond Feb 02 '12 at 15:30
  • going to try and convert these numbers to degrees and see if it helps: http://stackoverflow.com/questions/4576493/how-can-i-use-sensormanager-getorientation-for-tilt-controls-like-my-paper-plan – owen gerig Feb 02 '12 at 16:48
  • I think you should use the compass for this one, not the accelerometer, cool idea man :) – yairchu Feb 13 '12 at 22:36
  • 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. In order for someone to accomplish a trick, i'll have to track a series of events. 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. – Raphael Ayres Feb 14 '12 at 16:14

4 Answers4

1

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.

quellish
  • 21,123
  • 4
  • 76
  • 83
  • definitely some good information in that video but still far from an answer. but i think my answer might be to much this quote sums up what i mean "Application developers who wish to make sense of rotational motion must master Euler angles, rotation matrices, and quaternions. Under the hood, sensor fusion algorithms must be used in order to create responsive, accurate, and low noise descriptions of motion." – owen gerig Feb 15 '12 at 01:48
  • You have to understand the capabilities of the device and how to use them. Some aspects of CoreMotion already use sensor fusion to provide high fidelity data, that's not the problem. How to use the data provided by the device to describe motion in 3 dimensions, that's what you need to solve. What you're trying to implement is the equivalent of an inertial measurement unit, which is non trivial on the device. You have to decide how close to an IMU/INS is "good enough" for your purposes.In the video he talks about this. Kalman filtering can help, but may not meet your needs. – quellish Feb 15 '12 at 02:38
0

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.

moxy
  • 1,634
  • 1
  • 11
  • 19
  • ya i have read the documentation, and the sample u gave is the same that i posted. my question is the same, how to get rotation information from these x y z values. – owen gerig Feb 15 '12 at 01:49
  • in the documentation i've quoted, it's said that you have to store the x, y, z values then compare it frequently to see if they change. according to this change you see if there was a rotation or not. – moxy Feb 15 '12 at 06:21
  • for example : when application launched, you had x=20, y=3, z=40. You store them in referenceX, referenceY and referenceZ variables, then you monitor gyroData.rotationRate.x, y and z with frequent updates, you'll probably find out, small variations, and then something like x=30, y=170, z= 10 so you deduce that iPhone has been flipped on y axis (better put some error margin, not purely 180 degree. x, y and z are the 3 dimensional axis and it's by looking how they change (monitoring and updating them periodically) – moxy Feb 15 '12 at 06:28
  • you won't have the giroData.rotationRate.x.iPhoneHasBeenFlipped property. you have to keep the original data and call the gyroData frequently to see how it change. my bad it's not in degrees, but from -1 to +1 values. look at this [link](http://blog.digitalagua.com/2008/07/15/accelerometer-xyz-based-on-iphone-position/), i think that's your looking for – moxy Feb 15 '12 at 06:35
0

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.

Raphael Ayres
  • 864
  • 6
  • 16
  • ya its pretty rough sorting though all these values that update so frequently. plus i dont get it because as my example shows im query the gyroscope but it seems like there is g-force applied which i dont understand. meaning that flipping the phone fast or slow has different reading, which shouldnt b the case if its just gyroscope – owen gerig Feb 15 '12 at 01:51
0

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.

Community
  • 1
  • 1
moxy
  • 1,634
  • 1
  • 11
  • 19