Search code examples
androidrotationquaternionsgoogle-project-tango

From rotation as quaternion to degrees (0 - 360°)


I've mounted a Google Project Tango device in landscape orientation on a robot and want to get the heading from the onPoseAvailable() event listener. I know the framework returns a quaternion as described in the API.

I tried a lot to convert the quaternion to a measurement in degrees only. The only orientation axis I'm interested in is y (https://developers.google.com/project-tango/overview/coordinate-systems#project_tango_coordinate_systems) which determines the heading of my robot.

My first approaches were to use TYPE_ROTATION_VECTOR, TYPE_GYROSCOPE or TYPE_ORIENTATION (depricated). But the resulting values were unusable. Later I read Tango has major issues with the magnetic sensors (How to detect an absolute rotation of an android device)

That was the reason to switch to the pose data from tango itself. But the same here. Either it's quite rocket science to the appropriate results or tango has also major issues here. I read a all stackoverflow articles and almost everything I found in the internet. I re-implemented almost every piece of code I found. But for my current scenario no piece was working as expected. For other movements in other axis it was!

I tried out the following:

Or is there another way to determine the rotation for robotic applications? (Just the heading). The only thing I want to achieve is making turns for a predefined angle (in degrees). Mostly I just want to turn right or left (90°).

If anyone can provide a piece of working code (targeting the Google Project Tango device) would be quite helpful. Lost already days with this. For other Android devices I've found solutions quite quickly. Not to be ruled out, that the device has other major bugs.


Solution

  • Try this code. Note that the calculated orientation is relative to the device orientation on start of service.

    double orientationRoll = Math.toDegrees(Math.atan2(
                2.0 * (rotation[TangoPoseData.INDEX_ROTATION_X] * rotation[TangoPoseData.INDEX_ROTATION_Y] + rotation[TangoPoseData.INDEX_ROTATION_W] * rotation[TangoPoseData.INDEX_ROTATION_Z]),
                Math.pow(rotation[TangoPoseData.INDEX_ROTATION_W], 2) + Math.pow(rotation[TangoPoseData.INDEX_ROTATION_X], 2) - Math.pow(rotation[TangoPoseData.INDEX_ROTATION_Y], 2) - Math.pow(rotation[TangoPoseData.INDEX_ROTATION_Z], 2)
        ));