kriswiner/MPU9250

The magCalibration does not appear to be applied consistently when calculating the magScale values.

Opened this issue · 20 comments

In magcalMPU9250(), are the following lines:

    dest1[0] = (float) mag_bias[0]*mRes*magCalibration[0];  // save mag biases in G for main program
    dest1[1] = (float) mag_bias[1]*mRes*magCalibration[1];   
    dest1[2] = (float) mag_bias[2]*mRes*magCalibration[2];  
       
    // Get soft iron correction estimate
    mag_scale[0]  = (mag_max[0] - mag_min[0])/2;  // get average x axis max chord length in counts
    mag_scale[1]  = (mag_max[1] - mag_min[1])/2;  // get average y axis max chord length in counts
    mag_scale[2]  = (mag_max[2] - mag_min[2])/2;  // get average z axis max chord length in counts

    float avg_rad = mag_scale[0] + mag_scale[1] + mag_scale[2];
    avg_rad /= 3.0;

    dest2[0] = avg_rad/((float)mag_scale[0]);
    dest2[1] = avg_rad/((float)mag_scale[1]);
    dest2[2] = avg_rad/((float)mag_scale[2]);

In order to be consistent, I believe the magCalibration values should also be used when calculating the mag_scale, so those three lines become:

    mag_scale[0]  = (mag_max[0] - mag_min[0])/2*magCalibration[0];  // get average x axis max chord length in counts
    mag_scale[1]  = (mag_max[1] - mag_min[1])/2*magCalibration[1];  // get average y axis max chord length in counts
    mag_scale[2]  = (mag_max[2] - mag_min[2])/2*magCalibration[2];  // get average z axis max chord length in counts

This then correctly accounts for the case when the magCalibration values differ. In the case of my MPU9250 device, the values are {1.19, 1.19, 1.14}, so they can be different.

Thank you for your prompt reply.

My very limited understanding is that when you do
mx = (float)magCount[0]*mRes*magCalibration[0] - magBias[0]
you are a adjusting the count with the fuse value because different axes can have different sensitivities.

So my suggestion of
mag_scale[0] = (mag_max[0] - mag_min[0])/2*magCalibration[0]
is just adjusting the count for the sensitivity in the same way. I would suggest if you do not do this, then the operation of
avg_rad/((float)mag_scale[0]
is not taking into account the differing sensitivities when calculating the scaling? In other words, only by using the fuse values can you see the true differences in dynamic range?

I agree. Assuming you can do an accurate soft iron calibration, then the fuse values can be ignored, because the soft iron calibration will measure the combined effect of both. This would also simplify the code, which is always a good thing.

I note that If someone was just doing a hard iron calibration, then it might be useful to use the fuse values.

The reason I was looking at your code in detail is that I am working through Hideataki's MPU9250 library, which is encapsulates your code into a modular format. In doing so, I have found a number of issues. When I have finished the analysis, I plan to do a pull request to the library to fix the issues. I will add an issue concerning our discussion here, and will include removing the fuse values in my pull request.

Are then any other MPU9250 libraries I should be looking at?

Hi Kris,

Not sure why you are bothering at all, the MPU9250 has been out of production for more than a year now and there are better oavailable anyway...

While we're on this subject, may I ask?
Which currently available IMU solutions would you recommend for 9-DoF AHRS sensor fusion for new designs? Are there any good ones that are similar in design to the MPU9250, i.e., all three sensors in a single chip package? I've been eyeing the LSM9DS1, but it seems to be out of stock everywhere..

I will keep in mind your sketch for two MPU9250s.

Is there a decent open source library for the ICM20948?

Your approach to calibration appears to be novel, and so I am considering doing a mathematical analysis of it, or has someone already done this?

I have done a first cut of my mathematical analysis, which currently indicates the fuse values are useful even if calibrating. My first cut is often wrong, but I hope to have something for you to inspect in a week or two.

I have written a technical note that describes a mathematical analysis of the calibration algorithm. The paper has not been refereed so comments are especially welcome.

The paper considers the fuse values and demonstrates that the magnetometer can be calibrated without knowledge of these values. This means that if the person doing the calibration is not confident that the fuse values are correct, then the values should be ignored, and the fuse values should not be applied to any subsequent measurements. In the context of this repository, it would mean removing any use of the fuse values or setting them all to one.

If the person doing the calibration is confident that that fuse values are correct, then they should be applied to every measurement. In the context of this repository it would mean implementing changes along the lines suggested in the opening post of this issue.

In the case of the MPU-9250, it seems that the MPU-9250 has been out of production for a year, so all MPU-9250 units are at least one year old. Given this, without assurances from the manufacturer, I would not be confident in the fuse values and so would lean to ignoring them.

The technical note also describes a simplistic error analysis of the calibration algorithm. It finds that if a Figure 8 maneuver is used for the calibration, it will at best produce estimates that are only slightly more accurate that the MPU-9250's magnetic field measurement error. Given the magnetic field measurements will be integrated in the quaternion filter (so improving the signal to noise ratio), this means that the calibration error could significantly degrade the angular accuracy. As well, it is found that the Figure 8 maneuver can introduce sampling errors whereby the actual maximum or minimum values are missed. The combination of sampling errors and measurement errors make the calibration difficult to perform in a repeatable fashion, i.e. each calibration could give significantly different results.

A careful operator could obtain repeatable results, especially if scatter plots of the response surface are used, as described by in this post by Kris Winers. However even a careful approach will still result in calibration errors that are only slightly better than the measurement errors.

My technical note suggests a calibration maneuver that should result in a much more accurate and repeatable calibration. The suggestion would only make three small changes to the calibration algorithm:

  • Use a moving filter to average about one second of magnetic field measurements for the x, y, and z directions.
  • Print out the value of the averaged x, y, and z magnetic field measurements.
  • Use the averaged measurements to record the maximum and minimum values.

The main change is to use a different maneuver to the Figure 8. The recommended maneuver is a manual gradient ascent/descent to find the minima and maxima, guided by the print out of the averaged x,y, z field measurements. The procedure assumes the operator has a compass that is able to indicate the direction of Magentic North. Once the direction of North is known, then the operator knows that local magnetic vector points in that direction but is tilted upwards or downward depending on whether they located in the Northern or Southern hemisphere. The idea of the algorithm is align and anti-align the x-axis with the magnetic vector, and then do the same for the y-axis and the z-axis. The instructions are as follows:

  • Orient the x-axis in the direction of magnetic North
  • Keeping the x-axis aligned with North, rotate the box downwards towards the earth whilst observing the x-axis values. Depending in which hemisphere the procedure is being performed, the readings will either be increasing or decreasing.
  • If the initial measurements are increasing, keep rotating until a maximum value is found. Try moving a small amount to the left or right to see if you can increase the x-value further. Once you have found the maximum, keep the unit still at that orientation for a second or two. Then keep rotating the box in the same manner that you had started, while maintaining the x-axis pointing to North. Now the readings should be decreasing. Keep rotating until you find the minimum value, then try to move to left or right to see if you can decrease the value further. Once you have found the minimum, keep the unit still at that orientation for a second or two.
  • If the initial measurements are decreasing, then follow the procedure outlined in the above step, except look first for a minimum value and then a maximum value.
  • Repeat above steps but with the y-axis aligned to North and then do the same with the z-axis aligned to North.

This does somewhat increase the complexity of the calibration, but should provide a more accurate and repeatable outcome.

Here is the technical note.

I believe you when you state there is no fool proof recipe. I thought your algorithm interesting, so my major motivations were understanding it better and to understand the fuse issue.

It sounds like we have converged on the fuse issue.

I would be most interested if anyone can suggest a paper that derives the soft iron ellipsoid response surface and identifies the assumptions involved, and when those assumptions are violated.

I look forward to your comments on the paper.

Chris

The paper looks useful, but just states that the soft iron causes a linear/affine transformation, except in the case where there is hysteresis. I am after an earlier paper or book that derives the linear transformation.

Here is an updated version of the paper that calculates the process gain for the estimators, so making it easier to compare different approaches.
calibration.pdf