Magnetometer calibration algorithm using ellipsoid fit and least squares method with light weight linear algebra library. Unlike similar algorithms, it does not require external linear-algebra library thus it's perfect for:
- ESP32
- Arduino
- Lightweight applications
Visualization (graphs not included in the code)
// data arrays
double x[231] = {18.923634, 20.785405, 23.265396, ...};
double y[231] = {94.943907, 103.939205, 113.472091, ...};
double z[231] = {27.951207, 32.958822, 31.772349, ...};
// Create vector based on data arrays
Vector vx = vec_from_array(x, 231);
Vector vy = vec_from_array(y, 231);
Vector vz = vec_from_array(z, 231);
// Fit best ellipsoid to the data and save offest vector, translation matrix
Callibration_t calib = calib_calibrate_sensor(vx, vy, vz);
// Print the result
vec_print(calib.offset);
mat_print(calib.transform);
// Compensate new data point based on calib
// new data = calib.transform*(old data - calib.offset)
Vector new_data_vector = vec_new(3);
VEC_X(new_data_vector) = 18.923634;
VEC_Y(new_data_vector) = 94.943907;
VEC_Z(new_data_vector) = 27.951207;
calib_calibrate_point(calib, new_data_vector);
// Print calibrated vector
vec_print(new_data_vector);
Average variance of points length in relation to calibration data noise (random mag. 100 data points):
Average chance of algorithm failure in relation to data point count (random mag. data with 10% noise):
Example of data calibration with 50% noise:
The World Magnetic Model (WMM) describes the Earth's magnetic field and is used to convert magnetometer readings from magnetic north to true north. Why compensate?
Magnetometers measure the Earth's field plus local distortions. Even after calibration, the result still points to magnetic north. WMM compensation adjusts for this by accounting for magnetic declination, enabling accurate heading and navigation.
The magnetometer was calibrated using an ellipsoid fit (50 data points) along with World Magnetic Model (WMM) compensation:
The gravity vector was assumed to be constant at [0, 0, -1], as the sensor was only rotated around the Z-axis.
(Note: Normally, you would use an accelerometer to determine the gravity vector.)