-
Notifications
You must be signed in to change notification settings - Fork 7.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MPU 6050 roll function of pitch? #470
Comments
I have updated the MPU6050_6Axis_MotionApps20.h code to include a very fast PID based calibration routine. Make a backup of the old MPU6050 library just to be safe. you may want to try these equations out:
The first function has 2 options each react differently to the use of acceleration and gravity with unique output ranges. The second function (Not in the mpu6050.c code) uses the DMP Quaternion only. I believe the DMP already integrates the acceleration values with the Gyro portion for the Quaternion calculations that are used with Pitch and Roll so I believe this to be the most accurate way to handle pitch and roll. Each of these functions generates different value ranges like pitch =+-90 while yaw and roll are -+180 (on the second function). In addition to the new calibration routines, I have added the code for MPU6050_6Axis_MotionApps_V6_12.h which uses the latest instance of the DMP firmware. Although it is bigger it contains an auto-calibration routine for gyro which further stabilizes drift after several seconds of no motion. Z |
Sorry, I tested all this, but the results are similar. So I left aside my own code and flashed only MPU6050_DMP6_using_DMP_V6.12.ino. Which works, as long only either pitch or roll changes. As soon as both picth and roll are changed, they seem to affect each other also. I've added quaternion dump, to see what happens there. Those results seem already affected. For aprox 39° roll, I get q.x = -0.34. If I then change pitch also, I do see q.x varing according to q.y sign and value. For negative q.y values, q.x increases. For positive q.y values, q.x decreases. Or if quaternion is correct, something is wrong with the maths? In my hardware or mechanical setup, q.x changes for roll, q.y changes for pitch. There also, I see the same, if only q.x or q.y change, outputs look correct. Best regards
As output example:
|
Sorry, I'm very new to quaternions and such subjects. I now found and used QuatView to compare its outputs with MPU6050_DMP6_using_DMP_V6.12.ino For QuatView, 45° roll, 30° pitch, 0 yaw, Euler/Degrees, the quaternion shall be 0,89 / 0,37 / 0,24 / 0,1 (rounded) Using DMP_V6.12.ino, I do read 49° roll, 21° pitch for 0,89 / 0,37 / 0,24 / 0,1 Shouldn't the readings be the same for the same quaternion? Is this the difference I noticed? |
If I'm understanding you correctly you are saying the Euler angles are incorrect?
the function for Euler:
you may want to change your code to this to test it
Z |
I clarify again my needs and what I don't succeed to do. I would like to record the roll data of a moving object. That object pitch and yaw change also. I'm now using unchanged original MPU6050_DMP6_using_DMP_V6.12.ino example to read pitch/roll data. And I now have a better test bed but the roll results I get out are still incorrect as soon as pitch changes also. Using that example code to read out MPU6050 roll and pich angles: Step 1, I change roll to any non zero and high value, roll readout is now 34.70°. Step 2, I change pitch also to any non zero and high value, pitch readout is now 25.50°; After step 2 and pitch change, I was expecting to see the roll readout still at 34.70, not at 38.30°. And my concern or question is why does the roll output shift away when pitch is non zero? |
If I'm understanding you correctly you are saying that the values that are generated from the pre-compiled Digital Motion Processing (DMP) code are generating invalid Quaternion values. as any change on the Pitch alters the roll values and vice versa. This is with clean calibration where when the MPU is set flat you are getting close to zero on all acceleration and gyro values after removing gravity from Z acceleration. If it does, I must refer you to TDK InvenSense There development team created the DMP firmware that generated the Quaternion values and I have no control as to how the code determines the Quaternion values. If this is not correct. and you believe an error in the math is the problem I am sorry I do not understand the Quaternion math enough to correct any Quaternion mathematical errors we may have generated in our attempt to bring you this library. I have copied others works when it comes to Quaternion math (the second Function) or like Jeffs function that uses Acceleration and gravity only to do the math for yaw and pitch so Quaternion values are not used. I have attempted to determine the values are close to my understanding of what they should be but I am not a mathematician. If you or anyone watching this, have a suggestion or a correction to the math I would be grateful and would like to add your version to the library with notation as to how it corrects the problem/error. If there is anything I can help further figure this out I will, I have enjoyed working on this project of Jeffs as I know he has also. We would like to try to further help you if we can. A Suggestion would be to post your complete code so I can test it on my rig. Maby it is simple to resolve. But I am not able to determine how to proceed at this time. |
Yes, correct, this is what I get with my MPU6050 chip and the Arduino libs, including the latest MPU6050_DMP6_using_DMP_V6.12.ino example code.
Just use MPU6050_DMP6_using_DMP_V6.12.ino example code to check or reproduce what I do get. If my MPU6050 isn't bad, you shall get the same results.
I thought the math could wrong. But I checked many examples and all do similar math to get roll/pitch from the quaternion. So this shall not be the issue. What I've done with QuatView was wrong, I was told by its author. Such comparison is to be done again. I had the idea to compare QuatView output, an alternate tool, to MPU6050_DMP6_using_DMP_V6.12.ino output. This might allow to compare Euler angles and quaternions and maybe help to find out if it is any math or overflow issue or it it is a DMP code issue. I was told following about my previous comparisons with QuatView: "The first set of numbers you gave with Euler angles of (YPR=45,30,0) gave a quaternion with values of (0.89,0.37,0.24,0.10). This corresponds to the rotation order of 123. When I change the rotation sequence in Quatview to be 321 instead of 123, then I get the same Euler angles that you get from your MPU6050. So perhaps your MPU6050 is doing the rotations in the order of 321 instead of 123." That was the answer to "For QuatView, 45° roll, 30° pitch, 0 yaw, Euler/Degrees, the quaternion |
Can you access the Motion Driver 6.21 files in the TDK InvenSense Developer Page Snips from that Motion Driver 6.21 example code:
What I did is I pre-loaded this orentation into the DMP image but it can be changed after the fact to another orientation. |
I see, I see that in TDK InvenSense package, they allow to define an orientation matrix for each chip or component, assuming they could be mounted differently than aligned and flat. Then in main.c, they do:
I do not know if the "pre-loaded orentation into the DMP image" is the issue neither if any mod there could change something. Our MPU6050 (gyro+accel) are all flat on our breakout PCBs... Is the default hard coded matrix correct in the lib? But I'm now almost convinced that with the current lib, some math are missing in quaternion to Euler or to ypr conversion process. Which would then mean additionnal work for CPU on any sample... I do not know how exactly those attitude conversion fonctions could be translated to Arduino codes, to make further tests:
Here is another example I found, in Python code, with Quaternion Rotation done before any Euler/ypr math: |
So let us simplify this.
What did you find does the math work? |
To run such a math test, one would need a list of quaternion values and the corresponding expected ypr outputs. I now believe an expert in rotation sequences and quaternion/Euler angle/ypr shall have a look at the lib internals and the bunddled examples. So the orientation matrix is hard coded in the lib:
I digged around Euler angles, quaternions and the related maths, Making it short, looks like the DMP algorithm uses that orientation matric data to calculate the quaternion. And that any next math ops must also be done according to that orientation - if not, next math ops will need to be done according to the DMP maths results and the quaternion output. DMP setup is done here in the InvenSense demo, using the orientation, calling dmp_set_orientation:
Digging further in InvenSense lib and source codes, you shall find references to xyx, xyz, xzx... associated to the orientation matrix data and functions. A search on Google for Euler plus xyx, xyz, xzx, xzy, yxy, yxz, yzx, yzy, zxy, zxz returns some infos about the maths that shall be done according to the orientation or Euler rotations. So I found that code which lists the maths from quaternions to Euler angles "based on various rotation sequences": By the way, I noticed issue #300 was opened for similar reasons: So looks like the DMP setup inside the lib and the lib current maths are inconsistent. I've now done some tests skipping mpu.dmpGetEuler(euler, &q); call inside MPU6050_DMP6_using_DMP_V6.12, and this seems to confirm there are maths issues with the lib and the bundled examples, at least, case zxy (not zyx, neither xyz) is much closer to my expectations:
But Euler angles aren't what I need. I still have to figure out what the maths should be for ypr (which excludes gravity). Or I may use Euler angles. I've added here the modified MPU6050_DMP6_using_DMP_V6.12.ino sketch, it gets the quaternions, then run some alternate maths to get out Euler angles, as described above: PS: Last days, I had tested also MPU9255 (because it features a magnetometer). And I had similar issues with roll&pitch. Now that I digged again into that sphere, I read issue with MPU9250 Sparkfun driver might be similar (take the quaternion, do your own additionnal math): https://forum.sparkfun.com/viewtopic.php?p=193530 Other related discussions are there: ENSTABretagneRobotics/razor_imu_9dof#36 (comment) |
Thank you for your persistence in discovering this issue. If you were to pick a fix for the Euler math. What do you think about this change:
To use replace the dmpGetEuler function with the above code. Would this fix the Eular side? and give every rotation option available? Z |
The conventions are standard, and very limited. By the fundamental orientation maths. There are 12 conventions for Euler, 6 conventions for YPR. I still didn't find the 6 corresponding YPR maths. So what you suggest for Euler angles could be a fix with a warning or an error flag using pragmas: "please, pick your convention for dmpGetEuler". For YPR, what the 6 maths ops should be remains to be defined... But I'm now trying to figure out how one could configure the DMP to force what it outputs. Might be a better choice. If the DMP would output quaternions based on eg XYZ convention, the next maths ops would be strict and unique. So far, I didn't succeed to force the DMP. In InvenSense demo code, see around motion_driver_6.12\msp430\eMD-6.0\core. If my understanding is correct, forcing the DMP to output quaternions according to precise math convention shall be done during DMP setup phase, using the matrix (if tweaks are required), and then calling: dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation)); There also, we can see InvenSense refer to those commun math conventions:
I'm stucked in "int dmp_set_orientation(unsigned short orient)" and in "mpu_write_mem" (a double write op to regs/mem), where I don't succeed to push correctly the data to the appropriate MPU/DMP memory. If that could work, it would be a much more decent fix, with unique maths ops and the DMP forced to calculate accordingly.
|
I'm not at my home till later but this will get you direct access to the dmp memory MPU6050 class functions to access DMP memory
address is the memory locating of the DMP firmware to change chunkSize can be set to 1 |
Somewhat messy but...
This should work. Matches example code memory dump for V6.12 I don't think it will work with any other version.Concerning MPU9255 |
Ok, I see, I had figured out the same from InvenSence source code, this is functionnaly almost equivalent:
But we need to write there "3, gyro_regs", 3 bytes. Regs data are defined as 3 bytes:
I believe mpu_write_mem needs that mod, for data lenght:
What the outcome is confuses me. Because I'm now getting some minimal angle errors in my outputs, and because so far, DMP output convention looks to be ZXY only (but with euler angles signs changing according to the used chip orientation matrix), I have to figure out what I could have done wrong to get now some 1-2° angles errors, in init, maybe with the math ops, or with my mechanical setup. What I'm now running is here, allows to chose a matrix or not, allows also to swap euler math methods during runtime: https://github.com/bk4nt/tests/blob/master/MPU6050/MPU6050_DMP6_using_DMP_V6.12.modded_DMP_settings.ino Looking further, DMP may only output ZXY quaternions, with an exception for Android only (using DMP_FEATURE_ANDROID_ORIENT).
Here is an NXP application note inside which they consider "Aerospace, Android and Windows Coordinate Systems": We might have to figure out what ZXY convention is. Or we could experiment with DMP_FEATURE_ANDROID_ORIENT. Edit... I'll check again later. Matrix#4 could produce ZYX quaternions outputs. |
Android Orient is enabled here
Note that the FIFO Buffer is now increased by 4 bytes
To Decode the gestures used
The ANDROID_ORIENT is only a small portion of the char array sent. Just 2 bits 6 & 7 which are >>6 shifted to bits 0 and 1 or just values 0-3.
I do not believe that ANDROID_ORIENT will fix this problem. Z |
Hello,
I'm using MPU6050_6Axis_MotionApps20.h plus main lines of MPU6050_DMP6 to get roll out of the MPU6050. That works fine as long as pitch = zero. Code being that of the example:
Callibration is done, using offsets provided by IMU_ZERO sketch (adding extra setX/YAccelOffset lines, but that made no difference):
Works, but when pitch is different than zero, roll gets affected. For example, extrem, if pitch (MPU6050 chip orientation) is 90°, the roll output of MPU6050 is some 80-85° for 45° chip roll.
With a roll of 24°, if pitch varies between +/-30°, roll output shifts from 24° to 27-28°.
With a roll of 36°, if pitch varies between +/-30°, roll output shifts from 36° to 42-43°.
Do I miss use MPU6050_6Axis_MotionApps20.h and MPU6050 or is any exta math required when both roll and pitch are different from zero?
Best regards
The text was updated successfully, but these errors were encountered: