The library for the LSM303D doesn’t seem to compensate for magnetic inclination. This seems to lead to headings that can be 20 degrees off!
Here’s the description from the code:
Description of heading algorithm:
Shift and scale the magnetic reading based on calibration data to find
the North vector. Use the acceleration readings to determine the Up
vector (gravity is measured as an upward acceleration). The cross
product of North and Up vectors is East. The vectors East and North
form a basis for the horizontal plane. The From vector is projected
into the horizontal plane and the angle between the projected vector
and horizontal north is returned.
The problem is that the projection of the magnetic field through the ground plane, when rotated a full circle, is an ellipse.
Also, the code doesn’t actually “scale” the readings; it just “offsets” them (and, evenso, it “offsets” them by the default of zero unless you hack at the code to set another calibration.)
I imagine that the correct way to deal with this is to measure inclination based on the down vector, and then rotate the reading back to ground plane, rather than reconstruct it simply using cross products (which will apply a skew based on the elongation of the ellipse.)
However, I could be off here – is there some other way this is supposed to work?