Skip to content

Not able to read absolute orientation (tilt) using DMP #59

@bernhardHartleb

Description

@bernhardHartleb

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:

  1. Incorrect magnetic heading. For example +90° yaw causes output to go from 80° to 170° (ok) but then drift to 110° (wrong)
  2. Heading is not independent of tilt, in any mode. For example, roll by -45° and the heading changes by 160° (woah!)
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions