-
Notifications
You must be signed in to change notification settings - Fork 85
Description
Hi Paul,
now that the compass data is available to the DMP, I tried to verify the output against a BNO055 board from production.
In modes ORIENTATION and ROTATION_VECTOR the heading (x-axis) will drift to the a magnetic direction, but roll and pitch axis always start at 0°. Even if the sensor is kept at a constant 90° tilt (vertical), the output stays permanently at the initial ~0° value in those modes.
Only the mode GEOMAGNETIC_ROTATION_VECTOR seems to give an absolute orientation and outputs the 90° tilt correctly.
However, for some reason this mode is extremely slow to update. A 90° change in tilt takes over 10sec to settle, even tough the DMP is supposed to run at 55Hz.
Other 9-axis modes show large rotations instantly + get the heel and pitch axis correct, but do not give absolute orientation. Even worse, if you tilt the sensor by only 45° the heading suddenly changes. It should be steady as long as it "points" in the same direction. This makes none of the modes very useful for real world applications where absolute orientation is important.
In summary, the following things do not work for me when using DMP results:
- Incorrect magnetic heading. For example +90° yaw causes output to go from 80° to 170° (ok) but then drift to 110° (wrong)
- Heading is not independent of tilt, in any mode. For example, roll by -45° and the heading changes by 160° (woah!)
- Output is not referenced to absolute orientation (gravity), which should be provided by the Accelerometer
This leads me to believe that at least the axis configuration of of the magnetometer could be wrong.
For testing we have to be able to convert the Quaternion output into Euler angles.
I would like to contribute the following code for that:
#include <cmath>
// heading, roll, pitch in degrees
struct Vector3D { double x, y, z; }
const double RAD2DEG = (180.0 / M_PI);
const double DEG2RAD = (M_PI / 180.0);
Vector3D toEuler( double w, double x, double y, double z)
{
Vector3D ret;
double sqw = w*w;
double sqx = x*x;
double sqy = y*y;
double sqz = z*z;
ret.x = atan2(2.0*(x*y+z*w),(sqx-sqy-sqz+sqw)) * RAD2DEG;
ret.z = atan2(2.0*(y*z+x*w),(-sqx-sqy+sqz+sqw)) * RAD2DEG;
double siny = -2.0*(x*z-y*w)/(sqx+sqy+sqz+sqw);
// prevent NaN and use 90 deg when out of range
if (fabs(siny) >= 1.0)
ret.y = copysign(90.0, siny);
else
ret.y = asin(siny) * RAD2DEG;
return ret;
}
Sorry for the bother with these issues, but I would really like to get some "truth" out of this sensor.
I know this IMU is especially difficult to configure, but I have a good reference, some experience, and would like to help :)
Best regards,
Bernhard