BNO085 Calibration Process

I'm trying to use a BNO085 in its full 9-DOF mode (i.e. with magnetometer enabled) and have found its calibration process to be both opaque and ineffective. Wondering if anybody here has intimate experience with it and can tell me what I might have got wrong.

The calibration process described in datasheet 1000-4044 is;

  • Enable dynamic calibration on all 3 sensors.
  • Enable Game Rotation Vector output (this is accelerometer+gyroscope only).
  • Enable Magnetic Field output and monitor the accuracy level (0-3) in the report status field.
  • Perform described motions to calibrate the accelerometer, gyroscope & magnetometer in turn.

When I do this accuracy is usually already reported at 3 (Highest) or very quickly climbs to 3 while I'm still doing the first set of accelerometer orientations. From there it will sometimes fluctuate between 2 or 3 while I complete the other motions but definitely doesn't impart any sense of improvement or progression. Nevertheless I read the DCD content and save it to reload on restart.

If I follow the process to first clear the Dynamic Calibration Data (Reset, Erase DCD FRS, Clear DCD & Reset) I see a slightly different progression where accuracy starts at 0 but then quickly climbs to 3 per the above.

In all of the above cases when I subsequently try and use the 9-DOF Rotation Vector quarternion the heading is prone to large movements (sometimes by as much as 45 or 90 degrees), I think in particular, but not only, after periods of high motion.

I actually get much better results just using the 6-DOF Game Rotation Vector but really want to remove the periodic drift and I have no idea how I might improve on the 9-DOF performance since as far as I can tell I'm following the data sheet guidance.


The BNO0xx 9DOF sensors all have opaque and inadequate calibration. I gave up on them years ago, and have not heard encouraging news since.

Just about any modern 9DOF sensor will work better, and you have complete control over it.

Hi Jim, yeah I had run across some of your disparaging comments on the Bosch parts.

And it seems true, since you helped me tame the LSM6/LIS3 calibration I do get better magnetometer readings from that part (for half the price). But I still haven't nailed the sensor fusion and I was tempted by the Bosch's onboard processing - which does seem to work very well for the 6-DOF.

I've posted example sensor fusion code for several of the more modern 9DOF sensors on Github. The LSM9DS1 and ICM20948 both work much better than the Bosch sensors.

Thanks, I'll certainly have a look but I need to be careful not to lift anything GPL (i.e. Seb Madgwick's code).

I've started porting fusion from RTIMULib but put it aside in the hope of a quick win via BNO.

Follow up question for you if you don't mind. Having looked at your LSM9DS1 example;

I can see how the gyro calibration is arrived at (average of 300 samples at rest), and;

You've already coached me through the magnetometer calibration, but;

It's not clear to me what process is used to take the accelerometer samples and create A_B and A_AInv.

Thus far I've just been doing much the same as with the gyro (store a 'zero' offset at rest and subtract this from the live samples). The offset and matrix suggest the accelerometer gets the same ellipse-fitting treatment as the magnetometer samples?

It is exactly the same process as with the magnetometer. See Tutorial: How to calibrate a compass (and accelerometer) with Arduino | Underwater Arduino Data Loggers

Crikey. It's probably just as well I had no idea when I started how hard it would be to get solid sensor data (I probably wouldn't have started). Trying to craft a device an end-user can calibrate through a web interface (just to ramp up the difficulty a bit more).

Once again I am immensely grateful to you for sharing your expertise.

With some effort, the calibration process could be made easier, but it doesn't need to be done often. It takes me about 15 minutes to do a reasonably good job for one sensor, and to verify the results. Then the sensor will perform as well as possible. But that comes nowhere near what a professional AHRS box can do (for $10K-$50K).

A lot of people are happy with the poor performance of the BNO0xx, which might explain why little effort was put into the calibration firmware of those sensors.

Would there be a case (leaving no stone unturned in the pursuit of accuracy) for incorporating the gyroscope when capturing accelerometer samples for calibration? Presumably all of the calibration readings are going to contain some small amount of linear acceleration?

That might help, if you can figure out how to do it.

Those extra accelerations, along with sensor noise, show up as deviations from "1 g". The version of Magneto that I posted on Github allows to eliminate outlier measurements with significant deviations from the average, before the fitting process, and doing so certainly does help.

If you don't know then I'm sure I could never work out how - this whole subject would be a lot more approachable if there were a way to fuse just gyroscope and accelerometer to get gravity which could then be used to tilt-correct the compass, even if only through euler math.

What I could do though is describe the process as 'starting from rest', get my gyroscope bias first then discard any accelerometer calibration sample if the gryoscope isn't near-to-resting. Also potentially useful as a component of sample rate control as I spent quite a bit of time working out how to ensure I didn't fill my sample buffer with captures from just the starting quadrant.

But then if one captured gyroscope values along with the other samples the resulting calibration could be used to refine a subsequent run with the process repeated until some minimal change threshold is achieved?