Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting Direction Vector in Android

How can I get a direction vector representing the direction the back of the device is pointing relative to earth coordinates?

For example, if place down on a desk (screen facing up) it should read [0,0,-1] and if held vertically facing north it should read [1,0,0], etc.

I know how to calculate it from heading, pitch, and roll, as long as those are relative to earth coordinates. To be clear here I am not looking for angular velocity, but the actual current angle relative to the plane tangent to the earth. So if the device is held vertically and facing north, the angle "alpha" should read 0 or 360, the angle "beta" should read 90, and "gamma" should read 0. I can't figure out how to get these values either.

I've been reading the API all day and I still cannot find how to get either of these things.

public void onSensorChanged(SensorEvent event) {
    // ?    
}

Thanks for any insights.

like image 395
Joey Avatar asked Jun 17 '12 02:06

Joey


People also ask

What is vector in Android?

A VectorDrawable is a vector graphic defined in an XML file as a set of points, lines, and curves along with its associated color information. The major advantage of using a vector drawable is image scalability.

What is vector in Android studio?

Android Studio includes a tool called Vector Asset Studio that helps you add material icons and import Scalable Vector Graphic (SVG) and Adobe Photoshop Document (PSD) files into your project as vector drawable resources.


1 Answers

Read this page: http://developer.android.com/reference/android/hardware/Sensor.html

In API 8 and above, there are "virtual" sensors which are generated by combining the inputs of all available sensors and appropriate filters. The "TYPE_ORIENTATION" sensor gives you the allover orientation of your device, but this interface is deprecated due to failure states at certain orientations. The new sensor is TYPE_ROTATION_VECTOR (API 9 and above) which gives your device orientation as a quaternion. This is really the best sensor to use, but the math behind it is a little heavy.

Failing that, what you do is call SensorManager.getRotationMatrix(), passing the latest gravity and magnetometer data. This will return a rotation matrix which could be used to convert a vector from device coordinates to world coordinates or vice-versa (just transpose the matrix to invert it).

The getOrientation() function can give you heading, pitch, and roll, but these have the same failure states as the TYPE_ORIENTATION sensor.

Examples:

  Device flat on a table, top facing north:
    1  0  0
    0  1  0
    0  0  1

  Tilted up 30 degrees (rotated about X axis)
    1   0      0
    0   0.86  -0.5
    0   0.5    0.86

  Device vertical (rotated about X axis), facing north:
    1  0  0
    0  0 -1
    0  1  0

  Device flat on a table, top facing west:
    0 -1  0
    1  0  0
    0  0  1

  Device rotated about its Y axis, onto its left side, top
  facing north:
    0  0 -1
    0  1  0
    1  0  0

Here is some sample code you may find useful:

public void onSensorChanged(SensorEvent event) {
    long now = event.timestamp;     // ns

    switch( event.sensor.getType() ) {
      case Sensor.TYPE_ACCELEROMETER:
        gData[0] = event.values[0];
        gData[1] = event.values[1];
        gData[2] = event.values[2];
        break;
      case Sensor.TYPE_MAGNETIC_FIELD:
        mData[0] = event.values[0];
        mData[1] = event.values[1];
        mData[2] = event.values[2];
        haveData = true;
        break;
    }

    if( haveData ) {
        double dt = (now - last_time) * .000000001;

        SensorManager.getRotationMatrix(R1, Imat, gData, mData);
        getOrientation(R1, orientation);
        pfdView.newOrientation(orientation[2], (float)dt);


        Log.d(TAG, "yaw: " + (int)(orientation[0]*DEG));
        Log.d(TAG, "pitch: " + (int)(orientation[1]*DEG));
        Log.d(TAG, "roll: " + (int)(orientation[2]*DEG));

        acft.compass = orientation[0];

        last_time = now;
    }
}
like image 74
Edward Falk Avatar answered Sep 22 '22 02:09

Edward Falk