How can I detect if an iPhone is rotating while being face up in a table? - iphone

Is there a way to detect if an iphone lying down in a table face up is rotating?. I do realize that this kind of movement is not reported by the accelerometer and neither is it reported to the - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation method.
Is there a way to detect angle variations for the phone rotating this way?. Thank you.

The gravity vector will be constant as it rotates on a flat table so you won't see anything on the accelerometers. You could follow compass heading changes to detect this rotation but only on an iPhone 3G S. See the CLLocationManager for details, look at the heading methods.
EDIT - With an iPhone 4 you can detect the rotation using the gyros. There is a new class in iOS 4 called CMMotionManager for getting rotation rate from the gyros.

When the phone is stationary the sum of the acceleration vectors should be +1. When the phone is rotating (assuming the sensor is off-center) the sum of the vectors should be more than 1 and (hopefully) somewhat constant.
If you look at the decay of that curve, I wouldn't be surprised if that shape is distinctive enough to be used to determine whether the phone is rotating or not.
This is the AccelerometerGraph sample app from Apple.

I guess you could do it if the iPhone has a compass. Other than that I don't think it will be possible or reliable.

This would really depend on the location of the accelerometer on the device, i just tested this using the accelerometergraph sample application on a 2g itouch and you can see the initial acceleration on the x and y axis(the 2g does not have the accelerometer in the center of the device I guess). So in a sense you could detect the rotation, however I think the challenge would be differentiating that acceleration from directional acceleration. And I'm sure the values would change if apple placed the accelerometer in different locations on different models. There would definitally not be any way of doing it via shouldAutorotateToInterfaceOrientation, I recommend you load the accelerometergraph sample application in the sdk and experiment with the acceleration vectors to see if you can isolate a rotation vector reliably on multiple devices.

Related

How to get rotation around Y-axis relative to how the user holds the device?

I remember from WWDC that there was a talk showing a teapot in OpenGL ES, which rotated with movement of device. It appeared like the teapot stood still in space.
When the app launched, the teapot started in a specific position. Then when device got rotated, the teapot rotated too to stand still in space.
At this talk, they mentioned that we must get the "reference frame" e.g. upon app launch, which tells us how the user initially held the device.
For instance here's the accelerometer axis:
I want to know rotation around Y axis, but relative to how the user holds the device.
So when the user holds it upright and rotates around Y, I need to know that rotation value.
I think the key is removing the gravity from the readings? Also I target iPhone 4 / 4S with gyros, but I think CoreMotion would sensor-fusion them automatically.
How could I figure out by how much the user rotated the device around the Y-axis?
From your other question Why is this CMDeviceMotionHandler never called by CoreMotion? I know that you working on iOS 4 - things have changed slightly in iOS5. In general gyro data or even better sensor fusion of accelerometer and gyro data as done in DeviceMotion is the best approach for getting proper results.
So if you got this up and running, you will need to work with CMAttitude's multiplyByInverseOfAttitude method to get all CMDeviceMotion results relative to your reference frame. Just store a reference of the very first CMAttitude in a class member and call multiplyByInverseOfAttitude with it on all subsequent calls. Then all members of CMDeviceMotion.attitude will refer to this reference frame.
For getting the rotation around Y axis, a first approach is to take Euler angles i.e. CMAttitude.roll. If you just need to track small motions this might be fine. If motions are more extensive, you will run into trouble regarding Gimbal Lock. Then you need advanced techniques like quaternion operation to get stable results, but this sounds like an own question.

Detecting the user's spinning motion

I have been experimenting with the Core Motion framework to detect a user spinning around, say on a merry-go-round, holding an iphone in his hand.
There are ways to detect the device motion around its own axes, but what is a good way to detect the iPhone spinning in circles?
Thanks
You can use the gyroscope. Take a look here: Gyroscope example
You have to remind that it is only availble on iPhone4 and iPhone4S.
There is one degenerate case where you can run into trouble, only magnetometer (compass) can help in that particular case.
If you put the device (a) on the desk in stationary position then (b) on a perfectly horizontal turntable rotating slowly you will get the same qualitative sensor readings. Both the gyro and the accelerometer readings are constant in the two cases, although the readings quantitatively differ. The sad part is: gyro bias error can render case (a) to look like (b) and vice-versa. In this particular case you need a compass to cancel the gyro drift. Case (a) is typical for a phone.
Apart from this degenerate case, gyroscopes and accelerometers with sensor fusion are sufficient to track arbitrary rotations of the device.

iPhone/iPad gyroscope

I never really understand the applications of the gyroscope on the iPhone/iPad, does it serve the similar function as the accelerometer but like an improvement to the accelerometer? What is the practical use of it?
"An accelerometer is a direct measurement of orientation, while a gyro is a measurement of the time rate of change of orientation." (1) By combing the output of the two sensors, called sensor fusion, one can determine the orientation of the device precisely and fast.
If you only use accelerometer with a low-pass filter, you still get a reasonable estimate for the orientation but it will lag.
Here is an excellent live demo of both (Google Tech Talk), starting at 21:50.
Gyroscope measures orientation, where accelerometer measures movement. Both have useful applications (gyroscope: Which direction am I driving towards? Accelerometer: Did I just shake my device?)
The accelerometer tells you the difference in the force being experienced by the device and the force it would experience if it were in free fall. So if the device is static, the accelerometer tells you which way up is. When it's being shaken around, you get a summation of up plus the direction of the shake. Hence the accelerometer can detect some rotation, but not around the gravity vector and only if the device is otherwise static.
The gyroscope tells you the velocity at which the device is being rotated. So you can integrate values coming from it to keep track of orientation. That works across all axes and irrespective of device movement.

Transform device orientation to world frame in objective c

I'd like to transform the yaw, pitch and roll of the iPhone from the body frame to the world frame, i.e. azimuth, pitch and roll. On Android this is easily done with the
SensorManager.remapCoordinateSystem(), SensorManager.getOrientation methods as detailed here: http://blog.mysticlakesoftware.com/2009/07/sensor-accelerometer-magnetics.html
Are similar methods available for the iPhone or can someone point me in the right direction how to do this transformation?
Thanks
The accelerometer is good enough to get gravity direction vector in device coordinate system. That is in case when device calms down.
The next step for full device orientation is to use CLLocationManager and get the true north vector in device coordinate system.
With the normalized true north vector and gravity vector you can easily get all other directions using the dot and cross vectors product.
The accelerometer (UIAccelerometer) will give you a vector from the device's accelerometer chip straight down. If you can assume that the device is being held fairly steady (i.e., that you're not reading acceleration from actual movement), then you can use simple trig (acos(), asin()) to determine the device's orientation.
If you're worried that the device might be moving, you can wait for several accelerometer readings in a row that are nearly the same. You can also filter out any vector with a length that's ± TOLERANCE (as you define it) from 1.0
In more general terms, the device has no way of knowing its orientation, other than by "feeling gravity", which is done via the accelerometer. The challenges you'll have center around the fact that the accelerometer feels all acceleration, of which gravity is only one possible source.
If you're targeting a device with a gyroscope (iPhone 4 at the time of writing), the CoreMotion framework's CMMotionManager can supply you with CMDeviceMotion updates. The framework does a good job of processing the raw sensor data and separating gravity and userAcceleration for you. You're interested in the gravity vector, which can define the pitch and roll with a little trig. To add yaw, (device rotation around the gravity vector) you'll also need to use the CoreLocation framework's CLLocationManager to get compass heading updates.

iPhone - detecting motion with gyroscope/accelerometer

I'm trying to detect a swinging motion with an iPhone 4 using the gyro/accelerometer. I searched for some posts on SO about this, but couldn't find anything specific to my issues.
Do I need to do any sort of calibration for data from the gyroscope/accelerometer?
Anyone think of how I would measure a swinging motion?
Thanks!
1: Most iPhone games using the accelerometer don't do any calibration, but not all iphones are the same; there is some variation in accelerometer calibration. You could add a manual or automatic calibration to your program. If however, detecting a swinging motion is all you want, calibration is not necessary.
2: Apple has a nice little app that generates graphs of accelerometer motions in the iPhone SDK. You can download and build that and see the measurements for the motion you want. Then you can write code to detect similar accelerometer measurements.