Magnetometer calibration data interpretation

edited September 2020 in General

I have a use case where I'd like to log the quaternion output from sensor fusion, as well as magnetic field data from the magnetometer. As far as I can tell, it's not possible to log 2 outputs of sensor fusion at the same time, so it has to be quaternion data and raw magnetometer output.

Once the data is downloaded from the sensor, I'd like to perform hard/soft iron correction on it. Since sensor fusion was used for the quaternion output, I guess its calibration data could be used instead of me trying to perform calibration manually from the data.
Can you please describe what exactly is stored in the 10 bytes of MblMwCalibrationData.mag? Layout of the data as well as the units of the data would be useful.

Also, if you have any relevant guide available for how the magnetometer data correction happens based on MblMwCalibrationData.mag, please share it with me.



  • You can check the sensor calibration portion of our tutorial. These values are specific to BOSCH and their calibration (which is something we simply open to you). You should checkout their documentation:

  • Thank you for the pointer.

    The BNO055 driver lets you access the magnetometer offset:
    The parameter of this function (bno055_mag_offset_t) is 8 bytes long.

    It also lets you access the soft-iron correction matrix:
    The parameter of this function (bno055_sic_matrix_t) is 18 bytes long.

    I didn't find any function in the driver that lets you pass 10 bytes. So, in the terms of function calls to the Bosch BNO055 driver, can you please share how you call the two functions mentioned above, and how it relates to MblMwCalibrationData.mag?

    Is it possible that you get the offset from the 10 bytes of MblMwCalibrationData.mag somehow (how?) and set a wired-in soft iron matrix that's characteristic of Mbient boards? If so, what is the built-in soft-iron matrix?


  • @kustra MblMwCalibrationData.mag is equivalent to bno055_mag_offset_t with a calibration accuracy indicator appended to it. It represents a hard iron offset in xyz with a scaling radius. The units on radius are not indicated. Byte 9/10 contains a value from 0-3 representing un-calibrated to high accuracy calibration status. When reading the calibration data it is advised to only use outputs with high accuracy status. Soft iron correction is not presently applied, as it is highly dependent on environmental factors and is not generally capable of auto-calibration due to its complexity.

  • edited September 2020

    @Matt I may have found the reason for some complaints of accuracy with sensor fusion.
    The BNO055 chip's automatic background calibration of the magnetometer drifts in a few minutes if there's no significant change of heading, but the sensor moves a bit. The most natural example is when a person is wearing the sensor on the thorax, just sitting for a while. This becomes visible in the quaternion output, as a slow drift around the vertical (Z) axis.

    I think this could be worked around, since the calibration state reported by the firmware reflects the drift: while the accelerometer and gyroscope calibration states tend to stay high after reaching high once, the magnetometer calibration state goes back to low and unreliable at the same time when the drift becomes apparent. So I wrote the logic in the app to check the magnetometer calibration state and just reset the calibration data to the last known high state calibration once it degrades.

    But I can't get the bugger to accept the new calibration data! If I detect degraded magnetometer calibration while sensor fusion is running, then call mbl_mw_sensor_fusion_write_calibration_data with a previously stored good calibration, then immediately read back the calibration data with mbl_mw_sensor_fusion_read_calibration_data, it still returns the degraded calibration! I would expect it to return the calibration data that I've just written, maybe slightly changed.
    Briefly stopping sensor fusion, writing the calibration data, then starting it again behaves the same way.
    My goal is to be able to refresh calibration data periodically, preferably without interrupting the user's session (for long).

    According to BNO055's data sheet, there's a way to refresh the calibration data:

    To set the calibration profile the following steps need to be taken
    1. Select the operation mode to CONFIG_MODE
    2. Write the corresponding sensor offsets and radius data
    3. Change operation mode to fusion mode

    (Setting Calibration profile, 3.11.5 Reuse of Calibration Profile,

    Which Mbient SDK API triggers the above behavior, and why didn't mbl_mw_sensor_fusion_write_calibration_data work?

    p.s. I obviously made sure that the sensor wasn't near any metal while testing. I tested at the same place for several hours, and the ideal magnetometer offset and radius remained unchanged for the duration of the test. I just streamed the raw magnetometer data, rotated the sensor around and eyeballed the numbers to verify.

  • Any chance you can provide info about the issue above?

  • @kustra

    Very interesting theory about the magnetometer auto calibration. Let me shed some light on how the calibration endpoints in the MetaWear API work.

    Same as in the BNO, the calibration profile cannot be loaded into the sensor fusion process while it is active. To work around this, when the calibration data is written into the API, it is stored internally and then loaded when the operating mode is changed. This allows calibration data to be written back at any time, but it is not applied until the mode is updated.

    Normally you would use the calibration endpoints to carry the calibration state from one data capture session to another, avoiding the need to manually calibrate each time. Application of the profiles requires a mode update or change to occur. Typically that would happen with the transition from sleep mode to one of the active operating modes.

    Readout of the calibration profile is always pulled directly from the sensor fusion process, and so it always represents the present internal state.

    It seems from the description of your process that you are trying to update the calibration live, which is unfortunately not possible, and may explain why you are not seeing the values loaded. If you are cycling sensor fusion off and then on, it should be getting loaded, and you should be able to see that by reading back the calibration values. If that is not the case, then possibly your flow for cycling sensor fusion is missing a call to update the mode.

Sign In or Register to comment.