HongshiTan / RTIMULib2

9-dof, 10-dof and 11-dof IMU fusion library for Linux systems (development version)
Other
72 stars 240 forks source link

[Question] Orientation of MPU9250 and MPU9150 axis #8

Open SivertHavso opened 2 years ago

SivertHavso commented 2 years ago

I'm struggling to see why the orientation is handled the way it is for the MPU9250 (and similarly for the MPU9150), and have been getting unexpected outputs from the fusion with an offset on the z axis.

The relevant lines are:

https://github.com/HongshiTan/RTIMULib2/blob/e005545aca39e3a56c618e80eb0ccacb5c0ed137/RTIMULib/IMUDrivers/RTIMUMPU9250.cpp#L615-L635

Natively, the compass follows a North-East-Down (NED) frame convention, while the accelerometer and gyroscope is using East-North-Up (ENU) convention:

AxisOrientation

As RTIMULib expects the default orientation to be NED, I would have expected the accelerometer and gyroscope to have their x and y axis swapped and z axis flipped to bring it into the same orientation as the compass which is already in NED.

With the current solution, the y and z axis of the gyroscope is flipped which also brings it into NED, but 180 degrees offset from the native compass orientation:

mpu9250

The accelerometer only has its x axis flipped with its z axis left pointing up. Which neither follows NED nor ENU.

The compass has its x axis flipped then swapped with the y axis. Effectively rotating them 90 degrees, but it does not add an accompanying 90 degree offset on the z axis.

I might be misunderstanding completely, and am not very familiar with the core RTIMULib library codebase. What's the reason it's been done this way?

gigcastro commented 2 years ago

Around a year ago, we had the same doubt and sent a mail to the original author asking for this.

He kindly responded:

Hi there! While it is true that the axes of the gyro and accelerometer are aligned, the problem is that the gyro rotation directions are inverted from what I want for the rest of the calculations. So what you are seeing in the code is first the gyro rates having their signs changed. However, they also use a right hand rule for axes and RTIMULib uses a left hand rule so the X axis has to be reversed. That's why you see the gyro Y and Z values being negated but not the X value - the X value has been negated twice. The sense of the accelerometer is correct but it also needs the right hand to left hand conversion, hence the X value is negated.

Hope that makes sense!

Richard.

The key thing is that the gyro data are ANGLE RATES and are required in left-hand rule which are conventionally CLOCKWISE (contrary to the chip's right-hand standard). So a new left-hand axis needs to be decided, and it just invert the X axis as you noted in the accelerometer axis. That requires to negate angles rates of Y and Z, but not X, while only negates X axis in the accelerometer.

This leads to:

mpu9250

The compass remained kind of a mystery for us, but we did ask him about that and, while he was a bit hesitant, we got:

... If you look at lines 633 to 635 of that file you can see the magnetometer outputs being adjusted to match the IMU as the raw IMU and magnetometer data are in different frames. All of the drivers output data in the standard AxisRotation 0 frame. ...

So we understand that, to take the compass MPU9250-Right-Hand-NED (RH) to the same RTIMULib-MPU9250-Left-Hand (LH) as the gyro/accel it should: LH_X = -RH_Y LH_Y = RH_X LH_Z = -RH_Z

But he doesn't do that, he ends up with a right-hand axis again. I disagree with your interpretation of the resulting axis @SivertHavso, as I understand it is rotating 90 degrees in the opposite direction that you drawn.

At that point we just commented the lines in our internal repo and move on with our lives.

What is mind-blowing to me is that the default AxisRotation (explained in RTIMU.h) is in right-hand, as It is stated that "Standard configuration is X pointing at north, Y pointing east and Z pointing down", which is right-hand NED. That greatly differs from the gyro+accel left-hand axis delivered by the MPU9250 driver. Also, as I understand, changing AxisRotation, would lead to a right-hand matrix transformation being applied to left-hand raw data in the RTIMU::handleGyroBias() function.

I don't know if any of this happens with any other IMU chip/driver, but we set the AxisRotation as 0, so identity matrix would be used and performed data reinterpretation at a later point in our code and didn't use any fusion capabilities.

I would be really nice to document and state requirements for the drivers on which coordinate system they should deliver the samples, what is left-hand / right-hand and how data should be expected. Some examples on how to use the AxisRotation would be nice also.

Hope this helps.

brightproject commented 7 months ago

I use an Adafruit 10DOF breadboard. I orient it vertically, as in the picture. IMU In the settings I select the orientation RTIMU_XSOUTH_YDOWN https://github.com/jordandcarter/RTIMULib-Arduino/blob/cac4454680dd6798f1f4d7fa61ab465e960dd570/libraries/RTIMULib/RTIMULibDefs.h#L96 And everything seems to work, but in the code itself https://github.com/jordandcarter/RTIMULib-Arduino/blob/cac4454680dd6798f1f4d7fa61ab465e960dd570/libraries/RTIMULib/RTIMU.cpp#L134 As far as I understand, if the axis is -1 or 1, then the sign changes for all axes and for the accelerometer and for the gyroscope and for the magnetometer. But this is not true, because sometimes the rotation axes need to be changed on different axes and these settings do not always match. I had an idea to rewrite the logic for assigning signs and rotating axes, but I’m not yet sure exactly how to do it. In the example, the IMU code axes are defined using coefficients int SENSOR_SIGN[9] = {1,1,1,1,1,1,1,1,1}; Perhaps someone had similar thoughts?