Search code examples
objective-cioscore-animationcore-motion

iPhone orientation -- how do I figure out which way is up?


I'm trying to draw a 2D image on the screen that is always facing "up". If the user is rotating their phone, I want to ensure my 2D object does not rotate with the device; it should always "stand vertical". I want to compensate for the user tilting left or right, but not tilting away or towards themselves.

I'm using CoreMotion to get Pitch, Roll and Yaw from the device, but I don't understand how to translate the points into the direction up, especially as the user rotates the device. Ideally, I can translate these 3 numbers into a a single value that will always tell me which way is up, without having to relearn all of Trigonometry.

I've looked at the 3D teapot example but it doesn't help because this example is 2D and I don't need tilt away/tilt towards. Also, I don't want to use the compass/magnetometer because this needs to run on the iPod Touch.


Solution

  • Look at image to better understand what I'm saying:

    enter image description here

    So you are only interested in XY plane. Accelerometer always measures the acceleration of the device relative to freefall. So when you're holding device as it is on image the acceleration value is (0, -1, 0). When you tilt device 45 degrees clockwise the value is (0.707, -0.707, 0). You can get the angle by calculating the dot product of current acceleration value and some reference axis. If we are using an up vector the axis is (0,1,0). So the dot product is

    0*0.707 - 1*0.707 + 0*0 = -0.707
    

    Which is exactly acos(-0.707) = 45 degrees. So if you want your image to stay still you need to rotate it in reverse side, i.e. -45 degrees in XY plane. If you want to ignore the Z value then you take only X and Y axes: (X_ACCEL, Y_ACCEL, 0). You need to renormalize that vector (it must gave magnitude of 1). Then calculate an angle as I explained.