When a button is pressed with the iPhone held vertically in portrait mode, I am recording a compass magnetic heading - a live camera feed having been displayed with crosshairs. GPS, camera (medium preset), compass and attitude sensing are all going at once for up to 20 seconds here. There is one instance of CLLocationManager. For attitude I have tried a reference frame aligned to magnetic north + vertical as well as an arbitrary vertical one.
Without correction for attitude, no matter how hard I try to hold the iPhone vertically and avoid yaw, I've not been able to get reproducible results. There is a correct value at times, but usually not. I am unsure whether this entirely because I have not yet applied attitudinal corrections, or whether the iPhone compass simply does not work accurately when vertical.
I did some thorough testing in the middle of a large park, far from stray magnetism, having performed the rites of calibration, rotating 180 degrees over the three axes and other slightly embarrassing manoeuvers.
The results were not correct, and often wildly inaccurate. As an example, fixing on a target at magnetic 142 degrees, I successively got the values 155, 152, 154, 154, 153, 156 for the magnetic (not the true) heading. At other times I would get 175, 177, 142 and so on.
I am hoping this is not a deficiency in iOS (possibly related to gimbal lock?), and it is just that the magnetic compass heading must be corrected for iPhone attitude. I am getting the attitude of the phone relative to the reference axes in the form of Euler angles (but could equally get a rotation matrix or quaternion) -- using CMMotionManager / DeviceMotion.
My problem is, despite lengthy searches (and despite not being too afraid of math) I have not found the math needed to do the correction. Sometimes I seemed close but the server that was linked to was no longer available.
If you rotate the device to alter the yaw by a certain amount, the compass reading appears to alter by a similar amount, leading me to think perhaps I just add yaw to the heading, but that fails completely. I've seen suggestions to use quaternions or rotation matrices, in unspecified manners, but all I have is a single quaternion or matrix representing a rotation from the reference frame to the current phone orientation so not sure what exactly I would do with it.
Hoping it's not necessary to jump into raw magnetometer/gyro/accelerometer hard-iron interference and so on to apply the correction?
Any pointers or suggestions gratefully received.
-- Bill.