I would like to create an augmented reality view that is going to point an object in a direction. However, the CoreLocation heading is not working correctly when you are facing upwards with your camera (say to a top of a 20-storeys building when you are on the ground floor).
It is giving the opposite direction (probably the direction that is pointing by the top of the phone).
I have tried a few methods to get it to work for the direction the camera is pointing, such as:
1, +180 degree when the device orientation is > 45 degree (not accurate enough, suddenly the direction goes off by 10~20 degree)
2, attempted to calculate using CMMotionManager with formula from the below tutorial. http://www.loveelectronics.co.uk/Tutorials/13/tilt-compensated-compass-arduino-tutorial.
3, attempted to simulate logic from android using ios deviceMotion.magneticField and deviceMotion.gravity.
4, use rotation matrix (some other post in stack overflow, but not accurate)
double heading = M_PI + atan2(self.altitudeData.rotationMatrix.m22, self.altitudeData.rotationMatrix.m12);
heading = heading*180/M_PI;
I am running out of idea what else could I try to get it right. I know there are some apps out there (some app that can see the sun and star) that is doing it correctly.
After much of research and testing. I ended up using GLKit for the calculation, as it saves me lots of trouble as well. Just leave it here for anyone who happen to get to this question.
First, I started the CMMotionManager device motion updates with CMAttitudeReferenceFrameXTrueNorthZVertical.
From some codes that I found on the web to draw an openGL world using CoreMotion rotation and mix it with getting a point from screen to 3D world:
To save anyone else's time, here's Chee's answer in Swift: