Question

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.

Was it helpful?

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.

OTHER TIPS

Apple supplies an observer for this. Here is an example.

File.h

#import <UIKit/UIKit.h>

@interface RotationAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

-(void)orientationChanged;
@end

File.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.

    //Get the device object
    UIDevice *device = [UIDevice currentDevice];

    //Tell it to start monitoring rthe accelermeter for orientation
    [device beginGeneratingDeviceOrientationNotifications];

    //Get the notification center for the app
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

    //Add yourself an observer
    [nc addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:device];

    HeavyViewController *hvc = [[HeavyViewController alloc] init];
    [[self window] setRootViewController:hvc];

    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}




- (void)orientationChanged:(NSNotification *)note
{
    NSLog(@"OrientationChanged: %d", [[note object] orientation]);
    //You can use this method to change your shape.
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top