Magnetometer, accelerometer calibration

While I was bench testing hardware platforms with experimental filters, I noticed I was getting inaccurate magnetometer measurements ie a 90 degree rotation was not a 90 degree rotation in all quadrants. This was prevalent in all of my methods. I was trying to work around this but the errors were sufficient to cause problems.
I explored calibration methods and found a very nice solution. Similiar methods are outlined in multiple papers but I found this method already simulated in matlab, thus it only took a few hours to implement. The code is based on a paper by Merayo et al "Scalar calibration of vector magetometers". Essentially, a data set of real magnetometer measurements is collected from all quadrants (a complete sphere of rotations). This data is really a displaced, distorted 3 dimensional ellipse due to magnetometer calibration errors.

A Matlab routine crunches through the data and produces coefficients that best fit a sphere to the data.

The result is a matrix U[3x3] and a vector c[3] such that the calibrated measurement w = U*(v-c)
This is easily implemented in code using something like this:
void calibrate_magnetometer(void)
{
// float 3x3 matrix for elliptical magnetometer corrections
m3x3 U= {
{ 1.765e-03, 1.635e-04, -4.247e-05 },
{ 0.000, 1.734e-03, -8.498e-05 },
{ 0.000, 0.000, 1.944e-03 } };
// float 3 vector for center point corrections
vector3 c= { -2.368e+001, -4.000e+001, -8.719e+001 };
vector3 tmp; // temporary for calcs
// subtract c from magnetometer readings to correct center point tmp = magbuf - c
tmp[0] = (float)magbuf.x.i16 - c[0];
tmp[1] = (float)magbuf.y.i16 - c[1];
tmp[2] = (float)magbuf.z.i16 - c[2];
// multiply mag = U * tmp (this is matrix * vector with zeros on bottom left)
mag[0] = U[0][0] * tmp[0] + U[0][1] * tmp[1] + U[0][2] * tmp[2];
mag[1] = U[1][1] * tmp[1] + U[1][2] * tmp[2];
mag[2] = U[2][2] * tmp[2];
}
I thought this was very cool. I've attached a zip with the matlab code and some data. A similiar method could work for accelerometer triads also. I'm exploring that.
I explored calibration methods and found a very nice solution. Similiar methods are outlined in multiple papers but I found this method already simulated in matlab, thus it only took a few hours to implement. The code is based on a paper by Merayo et al "Scalar calibration of vector magetometers". Essentially, a data set of real magnetometer measurements is collected from all quadrants (a complete sphere of rotations). This data is really a displaced, distorted 3 dimensional ellipse due to magnetometer calibration errors.

A Matlab routine crunches through the data and produces coefficients that best fit a sphere to the data.

The result is a matrix U[3x3] and a vector c[3] such that the calibrated measurement w = U*(v-c)
This is easily implemented in code using something like this:
void calibrate_magnetometer(void)
{
// float 3x3 matrix for elliptical magnetometer corrections
m3x3 U= {
{ 1.765e-03, 1.635e-04, -4.247e-05 },
{ 0.000, 1.734e-03, -8.498e-05 },
{ 0.000, 0.000, 1.944e-03 } };
// float 3 vector for center point corrections
vector3 c= { -2.368e+001, -4.000e+001, -8.719e+001 };
vector3 tmp; // temporary for calcs
// subtract c from magnetometer readings to correct center point tmp = magbuf - c
tmp[0] = (float)magbuf.x.i16 - c[0];
tmp[1] = (float)magbuf.y.i16 - c[1];
tmp[2] = (float)magbuf.z.i16 - c[2];
// multiply mag = U * tmp (this is matrix * vector with zeros on bottom left)
mag[0] = U[0][0] * tmp[0] + U[0][1] * tmp[1] + U[0][2] * tmp[2];
mag[1] = U[1][1] * tmp[1] + U[1][2] * tmp[2];
mag[2] = U[2][2] * tmp[2];
}
I thought this was very cool. I've attached a zip with the matlab code and some data. A similiar method could work for accelerometer triads also. I'm exploring that.