Magnetometer, accelerometer calibration

Just put anything that is not directly related to the Gluon-specific implementation here. I will create subforums if required!

Moderator: lukasz

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.
Attachments
calibration.zip
Matlab code, sample data

Mitch

Posts: 118
Joined: Sat Dec 05, 2009 1:59 pm
Location: Florida, USA

Re: Magnetometer, accelerometer calibration

Hi Mitch,

To use this approach for accelerometers: do you think the U matrix could possibly not be a diagonal matrix?

Tom

Posts: 1016
Joined: Fri Nov 13, 2009 6:27 pm
Location: Belgium

Re: Magnetometer, accelerometer calibration

I think mathematically the analysis should be the same. The problem is one cannot take a continuous stream of measurements from the accelerometers because the measurements are corrupted by the movement of the sensors. I think a limited number of points could be collected by collecting data only when the sensor is static. Perhaps I will mount the board in a gimbal or something so it can be moved to selected orientations and held stationary while a measurement is collected.

Using the calibrated magnetometer values has dramatically cleaned up the "orthogonality" - independence in each axis of my vector matching algorithm. I expect calibrating the accelerometers will create more improvement so I will look into it further. I was hoping to avoid calibrating each sensor but it may be unavoidable.

Right now I am focusing on using an "estimator" to create the best estimated quaternion position from sensor values (in the navigation frame), accelerometers, magnetometers, and eventually gps. This estimation will be integrated into the EKF as a single quaternion. This should mitigate the large matrix manipulation requirements and allow modifications without rewriting the entire filter algorithm each time a sensor change is made.

Mitch

Posts: 118
Joined: Sat Dec 05, 2009 1:59 pm
Location: Florida, USA