Friday, March 16, 2012

Magnetometer Calibration Error

In building my Sparkfun AVC robot, I wanted to investigate the effects of magnetometer calibration on heading error.

I've been working on calibrating my compass and have run into some snags along the way. I'm working on a calibration machine to measure real world error but I thought it'd be interesting to model calibration error first. Here's how. Time for Octave and and simple trig....
To keep things simple, I assumed a 2d compass, and modeled only hard iron offset and scale issues. I wrote an Octave script to do the work. In the script, I wrote a function that computes the heading error per degree of true heading given an x and y offset and x and y scale.

H=[-180:2:180]';
x=xscale*cos(H*pi/180) + xoff;
y=yscale*sin(H*pi/180) + yoff;
mag=atan2(y,x)*180/pi; % Range: 0 to 2*pi radians
err=H-mag;

For scale error, heading error maximums occur at 45°, 135°, 225°, 315°. Minimums occur 45° apart from maximums. Here's a plot of heading error due to a 10% scale calibration error:


To plot the relationship between scale error and maximum heading error, call this function for values of xscale that range from 100% to 120% of yscale, and offset of 0.  Then, obtain max(err) and plot maximum error vs heading. If axes are mis-scaled by 10% the error exceeds 5°.


Next, I run the same function with an x axis offset of 0-10% (of the radius) and matching x and y scale, and plot the result. An offset of 10% results in over 2.5° of error.


Understanding the sensitivity of maximum heading error to scale and offset calibration gives me some clear goals for magnetometer calibration.

Meanwhile I will soon investigate the approach of swinging the compass: collecting real world error data after initial calibration that I can use to further correct magnetometer readings at runtime.

Here's the Octave script:

% MagError
% Figure out theoretical magnetometer heading error vs offset,
% scale calibration errors
%
% Michael Shimniok 
% www.bot-thoughts.com
%
function MAG=simplemagerr(xscale, xoff, yscale, yoff)
 H=[-180:2:180]';
 x=xscale*cos(H*pi/180) + xoff;
 y=yscale*sin(H*pi/180) + yoff;
 mag=atan2(y,x)*180/pi; % Range: 0 to 2*pi radians
 err=H-mag;
 %close all;
 %figure;
 %plot(H, mod(err-180,360)-180 )
 %axis([-180,180,-10,10]);
 %axis("auto y");
 %xlabel("true heading", "fontsize", 14);
 %ylabel("heading error", "fontsize", 14);
 %title("Calibration heading error","fontsize",18);
 %grid on;
 %figure;
 %plot(x, y);
 MAG=[H, mag, err];
end

% to plot magnetometer error vs. offset/scale calibration use
% this function
%
function ERR=MagError
 ERR1=[];
 for xscale=100:1:110
  e=simplemagerr(xscale,0,100,0);
  ERR1=[ERR1; xscale max(e(:,3))];
 end

 ERR2=[];
 for xoff=0:0.1:10
  e=simplemagerr(100,xoff,100,0);
  ERR2=[ERR2; xoff max(e(:,3))];
 end
 figure;
 plot(ERR1(:,1),ERR1(:,2));
 xlabel("Scale (%)", "fontsize", 14);
 ylabel("Heading error (deg)", "fontsize", 14);
 title("Single axis scale vs error", "fontsize", 18);
 figure;
 plot(ERR2(:,1),ERR2(:,2));
 xlabel("Offset (%)", "fontsize", 14);
 ylabel("Heading error (deg)", "fontsize", 14);
 title("Single axis offset vs error", "fontsize", 18);
end

No comments:

Post a Comment