Sensor Fusion Drift

Hi all,

I am developing with MetaMotionR sensor from quite a while. Yesterday,
for the fist time I had some serious problems of quaternion data
drifting. The sensors are running the last firmware version. Their
battery level was 99%. This happened with 2 out of 3 sensors that were streaming simultaneously to an Android App. Do you have any idea on why this is happening? Have you ever experienced something similar?

Thank you


  • Post the MetaWear code you are use, attach log files of the measured values, and describe how you are using the boards and what values you expect to see.
  • We have developed our own APP using 3.0.32 API.

    This is how the data normally look like when the sensor is clipped to the upper trunk of a subject performing exercises.

    From when the problem has occurred this is how the data in the same condition looks like:
  • Put images on an image sharing site like Imgur or even Dropbox.

    Please also post the actual sensor values, code you are running, and describe the boards' motions and what are the expected values.
  • Sorry for the images, I was able to see them when I posted. Here's the Imgur link:

    The sensors is expected to register little motion, since it is fixed on the upper part of the trunk while the subject is sitting and performing movements with his arm.

    The code of the App we used to generate the file is quite rich so I have extrapolated the parts regarding quaternion configuration and streaming. Hope it is useful to you.

  • [code]
    // parameters class
    public class ConnectionParams {
        private SensorFusionBosch.Mode mMode;
        private float mMaxConnectionInterval;

         * Creates a new {@link ConnectionParams}. By default sensor fusion mode is set to
         * {@link SensorFusionBosch.Mode#NDOF}, accelerometer data range is set to
         * {@link SensorFusionBosch.AccRange#AR_16G} and gyroscopes data range is set to
         * {@link SensorFusionBosch.GyroRange#GR_2000DPS}. Max connection interval is set by default to
         * 11.25 milliseconds for Android version 23 and above, to 7.5 milliseconds for previous
         * versions
        private ConnectionParams(){
            this.mMode = SensorFusionBosch.Mode.NDOF;
            this.mAccRange = SensorFusionBosch.AccRange.AR_16G;
            this.mGyroRange = SensorFusionBosch.GyroRange.GR_2000DPS;
            this.mMaxConnectionInterval = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? 11.25f : 7.5f;

        public SensorFusionBosch.Mode getMode() { return this.mMode; }
        public float getMaxConnectionInterval() { return this.mMaxConnectionInterval; }

         * Using the Builder design pattern to create a {@link ConnectionParams} object
        public static class Builder {

            private ConnectionParams mObj;

             * Creates a {@link Builder} that can be used to generate a {@link ConnectionParams}
             * object.
            public Builder() {
                this.mObj = new ConnectionParams();

             * Returns a new instance of {@link ConnectionParams} built from the given configuration.
             * Once the method has been called, the builder is invalidated and can not be used to create
             * a second instance of {@link ConnectionParams}.
             * @return a new instance of {@link ConnectionParams}
            public ConnectionParams build() {
                ConnectionParams tmp = this.mObj;
                this.mObj = null;
                return tmp;

             * Sets the sensor fusion operation mode.
             * @param mode the mode to set
             * @return the {@link Builder} instance to chain calls
            public Builder setMode(SensorFusionBosch.Mode mode) {
                this.mObj.mMode = mode;
                return this;

             * Set the max connection interval of the BLE connection. Reducing this value allows higher
             * streaming frequencies.
             * @see <a href="">
             * @param interval The max connection interval in milliseconds
             * @return the {@link Builder} instance to chain calls
            public Builder setMaxConnectionInterval(float interval) {
                this.mObj.mMaxConnectionInterval = interval;
                return this;


    // configuration
    private SensorFusionBosch mSF;
    private void configure (ConnectionParams params) {
            this.mSF = this.mBoard.getModule(SensorFusionBosch.class);

            this.mQuatProducer = this.mSF.quaternion()


    // streaming
    if(params.isQuatEnabled()){ //stream quaternions
        task = task.continueWithTask((Task<Void> t) ->
                this.mQuatProducer.addRouteAsync((RouteComponent source) -> {
                        source = source.limit(hzToMS(params.getQuatFrequency()));
           data, Object... env) -> {
                }).continueWith((Task<Route> t2) -> {
                    mRouteQuat = t2.getResult();
                    return null;


  • Code looks fine to me so I have some additional quesetions:
    • The first picture in your image corresponds to the erroneous data I assume?
    • Were you receiving correct quaternion values before?
    • Have you tried using the IMUPlus mode?
    • Does resetting the boards fix the problem?
    • Have you done random motions with the board to calibrate the magnetometer?
    • Are the boards near any external sources of magentic fields?
    • The first picture in your image corresponds to the erroneous data I assume?

    Yes, it does

    • Were you receiving correct quaternion values before?

    Yes, we did. The sensors showed this behavior for a couple of trials and than got back to normal without any intervention.

    • Have you tried using the IMUPlus mode?

    Not yet. We were quite happy about the NDoF results, but we can have a look to the alternatives. AS I understand IMUPlus calculates relative orientation in space taking by reference the initial position. What does "Initial position" mean exactly? the position in which the sensor is placed when it stars streaming? Is it possible to force the sensors to reset the initial position to current position?

    • Does resetting the boards fix the problem?

    The problem went away without any intervention. Therefore now we are worried this can randomly append again while we are collecting important data.

    • Have you done random motions with the board to calibrate the magnetometer?

    We didn't know that was useful. Where can we find this kind of suggestions?

    • Are the boards near any external sources of magentic fields?

    Since we are acquiring in an hospital, it is impossible to exclude all the magnetic fields. However this is the first time in a couple of months of acquisitions we are experiencing something like this. We are trying to figure out if they have acquired some new machinery that could have caused this new issue. Do you think that using IMUPlus can help us in this condition?

  • edited October 2017
    Initial position means just that, the board's position when the sensor fusion algorithm starts running.  However, it doesn't matter what the initial position is as you are determining if the board's orientation has deviated from said position.

    IMUPlus may help as it doesn't use magnetometer data.  You will have to test this yourself to see if it does indeed help.

    It would also be interesting to do your tests as normal with NDoF mode but also simultaneously collect magnetometer data.  If this issue occurs again, you could look over the magnetometer data to see if there was indeed fluctuations in the measured magnetic fields.
This discussion has been closed.