Jump to content
I2Cdevlib Forums

Why is the DMP yaw stable?

Recommended Posts

I'm running the DMP example for Arduino.  Upon startup the yaw value wanders for about ten seconds before stabilizing at ~38°.  Pitch and roll are stable from the start, but after the ten seconds everybody is basically perfect.  This is confusing to me because of the way sensor fusion works.  In a fused sensor the acceleration vector is used to cancel drift in the x and y gyro readings, and a magnetometer does the same for roll around z.  The MPU-6050 doesn't have a magnetometer, so why does the yaw stabilize?  I know something's not quite right with the yaw; it drifts for a while when pitch and roll are steady from the start.  However, from looking at the erratic drift in the raw gyro rates, I don't see a reason why the yaw would ever stabilize.


I realize that I'm kind of asking "How does DMP work" and that nobody really knows.  But maybe someone has an idea?


Anyway, thanks for the work you've done, Jeff.  Your praises shall be sung to the farthest reaches of the interwebs, followed by lusty cursings of InvenSense.  But maybe a kind word every once in a while.

Link to comment
Share on other sites

Hi Joe,


My (rudimentary) understanding is that after that much time, the DMP algorithm realizes that the constant value it's getting for yaw drift from the gyro is error rather than movement, and it appropriately zeroes it out. I can't begin to tell you exactly how this happens, but it does seem to work that way. One idea is that if the accel X/Y values aren't exactly zero, then if the heading really were changing, the X/Y accel values should rotate accordingly. If they are stable but the heading is shifting, then the effect would necessarily have to be error rather than real movement. This is just a guess though.


One thing I have discovered recently through testing is that you can manually set your own axis offset values to "kickstart" this calibration process. For example, adding the mpu.setXXXXXOffset code after the mpu.dmpInitialize() call to MPU6050_DMP6.ino:

    // load and configure the DMP
    Serial.println(F("Initializing DMP..."));
    devStatus = mpu.dmpInitialize();

    // supply your own gyro offsets here, scaled for min sensitivity
    mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

...makes the initialization routine on the specific MPU I was using for testing virtually unnecessary. It starts up with a nearly rock-solid orientation value and changes a fraction of a degree over the first 8 seconds. These values are unique to every sensor, so don't just use the ones above; the easiest way I've found so far to determine them is to use the MPU6050_raw.ino example sketch and simply play with different values while the sensor is stationary and level until all of the measurements are suitably close to zero, accounting for noise. This process could undoubtedly be automated such that you could just run a "calibration" sketch and leave it sitting still for a few seconds--maybe even taking advantage of the DMP to do the work for you--but I haven't got this far yet.

Link to comment
Share on other sites

Thanks for the prompt response.


I did a little testing, and it sure looks like you're right: if I keep the board constantly moving after the initialization, it still wanders for ~10 seconds after I stop moving it.  And then it's steady, regardless of how I move it.  Mystical magical DMP.


That's a good tip about the calibration.  I have two MPU-6050 breakout boards, and one is much more stable than the other.  But maybe with calibration I can get it to play nice.  I'll start tinkering and see what I can get. 


I intend to use this as an IMU for a rocket project.  Even if the manual calibration doesn't work, a short calibration period before launch is no problem.  We're going to try to keep the rocket pointed straight up with a gimballed motor: http://trello.com/board/fx3-project/513e38ab920b322745000661


Link to comment
Share on other sites

  • 2 months later...

Hi Jeff, many thanks to you for your excellent library. I'm using your quaternion output code and I'm having problems with gyro drift with yaw. I've read everything I could on Invensense's developer forums and from what I understand the code to calibrate and correct the gyros is proprietary? And furthermore this is a prebuilt binary that must be uploaded to the mpu6050 everytime you wish to use your device? If so, this is incredibly obnoxious.


Anyways, I am trying to determine how to achieve some kind  of stability with yaw. So somehow, without the calibration and gyro correction binary from Invensense, the mpu6050 is still able to compensate for gyro drift? 


I will try the mpu.setXXXXXOffset code and maybe adjust the motion threshold value as well and see how well that works. Thanks .

Link to comment
Share on other sites

  • 2 weeks later...

By the way, thanks for the kind words about the code library as well! I'm always excited to see people getting to use it in some project or another.


Our project is now finished:


Once again, thanks for making it all possible.


Put this into Google patent search:


US 20120323520 A1


The description in that patent application explains the behavior you're describing.





Very useful info, Riccati.  That explains everything perfectly.

Link to comment
Share on other sites

  • 3 weeks later...
  • 3 weeks later...

Hi Jeff,


Thanks for all your work on the libaries and examples etc.


I have an MPU-6050 (actually, it's on a FreeIMU board) and I'm having yaw-drift problems. So I'm trying to calibrate the device and found your post here.

You mention using the _raw.ino to determine the settings. So I have uploaded that and get these readings:


Initializing I2C devices...
Testing device connections...
MPU6050 connection successful
Updating internal sensor offsets...
-76    -3100    1280    48    0    0    
-76    -3100    1280    48    0    0    
a/g:    -14236    -3500    15048    1168    -105    -109
a/g:    -14300    -3396    15220    1141    -61    -110
a/g:    -14296    -3472    15216    1157    -90    -121
a/g:    -14256    -3340    15032    1156    -78    -93
a/g:    -14320    -3420    15032    1162    -58    -111
a/g:    -14220    -3472    15052    1159    -52    -96
a/g:    -14300    -3424    15060    1162    -47    -102
a/g:    -14196    -3480    15064    1122    -43    -122
a/g:    -14272    -3524    15040    1110    -92    -99
a/g:    -14136    -3500    15060    1100    -151    -142
a/g:    -14344    -3360    15156    1078    -138    -119
a/g:    -14404    -3496    15184    1041    -93    -113
a/g:    -14276    -3472    15172    1022    -46    -130
a/g:    -14352    -3544    15040    990    -11    -129


It would be very helpful, if you could give some directions on how to change the settings.


BTW: these lines:



are in the code between the topmost lines with values. Seems the Offsets must be activated somehow?


Thanks in advance,





Link to comment
Share on other sites

Hi Wim,


I don't have a very scientific calibration routine, or any code beyond what you saw posted there to speak of. The basic approach is like this:

  1. Use the set*Offset() methods to set all offsets to 0. These are effective immediately.
  2. Place the sensor on a flat, level surface. Measure with an actual level if you have to. The level adjustment is less critical if your main concern is yaw drift, but it's still a good baseline.
  3. Print out at least few dozen raw measurement values, or even better, skip 50 or so to let the device "settle" and then collect + calculate the average for each axis over 200+ readings. The correct "still/level" values for all gyro axes and the x/y accel axes should be 0, and the correct "still/level" value for the Z accel axis should be 1g, or +16384 at the default +/- 2g sensitivity setting.
  4. Use the opposite (positive/negative) value of the calculated averages to determine the new offset values for each axis.
  5. Plug the new values in on start-up using the set*Offset() methods. Note that there is some scale factor which I am not sure of yet; I believe the offset values need to be smaller, possibly by a factor of 2x, 4x, or 8x from the raw measurements.

This is about all the info I currently have. I really should build an auto-calibration routine to do this, but I haven't had the time.

Link to comment
Share on other sites

Hello Jef (and others...),


Just had some time to play with the MPU a bit. It's hard to find any relation between the raw values and the correction factors! In the end I just tried some "Trial & Error" and came to these values:


    accelgyro.setXGyroOffset(15);    // 20131112
    accelgyro.setYGyroOffset(-2);    // 20131112
    accelgyro.setZGyroOffset(-3);    // Trial & Error ... 20131110


The roughly eliminate the "errors" I posted before. Especially the gyro offsets puzzle me: I have to use a negative offset to correct a negative error? Strange.


Now I will try and see if the yaw-drift has become less bad.

Link to comment
Share on other sites

  • 2 years later...

Hi, can I ask how can I run the code for mpu6050 raw in arduino uno? What is the important thing that I need to consider, the connections for the arduino with the mpu6050 is the same as running mpu6050_dmp6? and I have tried running the code but its not working, and it gave me weird results in the serial monitor. 



Another question is that, if I wish to get the raw data from the gyro mpu6050, I need to run the mpu6050_raw code right? Is this true or there is another way of doing it. 


Thanks, your reply is appreciated. 

Link to comment
Share on other sites

  • 3 years later...

Hello everyone.


Thanks for your explanation jeff.

I am building a robot that will drive straight and i intend to use the yaw angle error to make that happen.

Right now I am at the yaw angle reading stage. I used the calibration sketch (attached below) and got the offsets. Then i plugged those offsets into DMP6 example of Jeff Rowberg library (thanks to jeff). I was expecting 0 readings for yaw, pitch and roll as i had held it still all the while. But  the readings were  49.6(y)    0.6(p)    -2.81(r). Can anyone tell me what might be the error?

I did notice the comment above the offset setting part of dmp6 saying "supply your own offsets here, scaled to minimum sensitivity."

Can the reason be that my sensitivity factor is not correct?

// load and configure the DMP
    Serial.println(F("Initializing DMP..."));
    devStatus = mpu.dmpInitialize();

    // supply your own gyro offsets here, scaled for min sensitivity
    mpu.setZAccelOffset(1788); // 1688 factory default for my test chip




Can that be the reason? 



Tahnks in advance.


Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...