minimu9-ahrs
minimu9-ahrs copied to clipboard
Altimu10v5 strange readings in XY axis Euler output
Ok, so i've calibrated the device and have a strange output in euler. sample.txt
Every axis works and shows correct values when i turn the Z axis clockwise. But when i turn it to the lef(crossing North - 0 value) Z axis shows correct values but as you can see the other pitch and roll suddenly shows really high values around 170+ being still flat on the table.
When i switch to quaternion output the readings behave just fine and shows correct values for yaw pitch and roll however i turn the board around Z axis.
Can someone point me to the code thats responsible for that? I've looked through the main cpp file, but i dont see where it can fail like that. Any help is appreciated Thanks in advance!
Ps. Somehow turning the device along the Z axis counterclockwise interferes with calculating X and Y and its quite magical to me how this is happening
Conversion from a quaternion to Euler angles is handled here:
void output_euler(quaternion & rotation)
{
std::cout << (vector)(rotation.toRotationMatrix().eulerAngles(2, 1, 0)
* (180 / M_PI));
}
The Eigen library does all the work.
I forget what order the pitch, yaw, and roll variables get printed and how those angles are defined so I can't easily tell whether your output looks normal or not. Some discontinuities are to be expected if you put your board at a weird angle.
Lets say i have Y=5 P=0 R =0. Device laying flat on the table. When i turn Yaw clockwise, P and R behave normally, showing right values when turning on angles +clockwise, but when i turn Yaw counter clockwise lets say it will be looking like this: Y P R 3 0 0 2 0 0 1 0 -1 0 0 0 179 177 176 178 176 177 177 177 176 176 176 177 175 177 175 174 177 176 etc
As you see, turning the device counterclockwise makes readings from Pitch and roll acting weird
The numbers are technically valid because Euler angles of {0, 0, 0} represent the same rotation as Euler angles of {180, 180, 180}. I used a Euler angle visualizer to verify that:
http://danceswithcode.net/engineeringnotes/rotations_in_3d/demo3D/rotations_in_3d_tool.html
It looks like the Eigen library method we are using is trying to keep the yaw variable between 0 and 180. That's an unfortunate choice; it would be better if it tried to keep pitch variable between -90 and 90, because that's how we think about the pitch of a plane. I'll keep this issue open as a reminder to look into that.
You can probably just subtract 180 from each angle when it gives you annoying values like this; I suspect that's valid but haven't thought about it hard enough to be sure.
Thanks for the answer. It seems like this is the case. With a change on Yaw from 180- -> 0, Pitch and roll are also changing base angle , and are showing values from 180->0. Everything works fine between Yaw 0+ -> 180. So the solution that you proposed may be accurate.
Thanks!
Hi @DavidEGrayson and @GrzegorzKarczewski - I'm struggling with the same thing as you guys. I understand that the readings are correct, but I'm having a hard time converting them to "normal" readings (although I'm also having a hard time defining "normal").
Did you guys come up with something workable or more intuitive that this? If so, how did you calculate it?
Hi @kramer65. I've dropped that project because there was many noise in the readings when i attached the device to car(probably due to shaking and interference from metal). I'm no cpp expert so apart from showing you my changes to code i cant really help you further.
@GrzegorzKarczewski and for any future readers. In the end I read out the results in Go and converted it using the (Go) code below. This gives every number between -180 and 180.
yaw_raw, _ := strconv.ParseFloat(imu_results[0], 64)
pitch_raw, _ := strconv.ParseFloat(imu_results[1], 64)
roll_raw, _ := strconv.ParseFloat(imu_results[2], 64)
yaw := 0.0
pitch := 0.0
roll := 0.0
if pitch_raw > 90 {
yaw = -(180 - yaw_raw)
pitch = 180 - pitch_raw
if roll_raw > 0 {
roll = (180 - roll_raw) * -1
} else {
roll = 180 - math.Abs(roll_raw)
}
} else if pitch_raw < -90 {
yaw = -(180 - yaw_raw)
pitch = 180 - math.Abs(pitch_raw)
if roll_raw > 0 {
roll = (180 - roll_raw) * -1
} else {
roll = 180 - math.Abs(roll_raw)
}
} else {
yaw = yaw_raw
pitch = pitch_raw
roll = roll_raw
}
fmt.Println("CLEAN: yaw", yaw, "pitch", pitch, "roll", roll)
After this I'll also need a Kalman filter, but that's for later.