3

I'm trying to get yaw of an android device expressed in euler angles.

To be clear i dont want 'Azimuth' (which is the angle to magnetic north) I want the rotation of the 'z' axis of an android device as shown in this picture.

enter image description here

This (IMHO) should be the axis used in some car games to determine the amount of steering.

It is my understanding I could just use the Accelerometer values (without the magnetic fields) but I'm unable to get the determined value. (probably due to a lack of understanding of how rotation matrixes works).

Can someone point me toward the right direction?

Andrea Baccega
  • 27,211
  • 13
  • 45
  • 46
  • This sound like the gyroscope - http://developer.android.com/guide/topics/sensors/sensors_motion.html#sensors-motion-rotate But I'm unclear to what the actual question is. – Morrison Chang Feb 09 '16 at 22:52
  • So in the picture a 90 degree rotation will turn the phone from portrait to landscape. Is that the rotation you want? If so then I already answered that at http://stackoverflow.com/questions/11175599/how-to-measure-the-tilt-of-the-phone-in-xy-plane-using-accelerometer-in-android/15149421#15149421 using only accelerometer. – Hoan Nguyen Feb 12 '16 at 05:50
  • I will post an answer that allow you to determine the rotation of the z-axis independent of the device position tomorrow. In the mean time you should read my answer at http://stackoverflow.com/questions/32372847/android-algorithms-for-sensormanager-getrotationmatrix-and-sensormanager-getori/35390001#35390001 to get a detail answer of what the getOrientation does so that you can understand the answer I will post. – Hoan Nguyen Feb 14 '16 at 09:04

1 Answers1

2

If you want to calculate the rotation about the device z-axis independent of the device position (that is flat or not flat) then you have to keep track of a few things. If the app support both Portrait and Landscape then it is more complicated, I am going to give an answer when the activity is restricted to Portrait only.

So flat here means the pitch is less than 25 or more than 155 degrees and not flat otherwise.
When the device is in transition from flat to not flat and vice versa there probably some inconsistent in the UI.

Register for TYPE_GRAVITY and TYPE_MAGNETIC_FIELD (needed for flat) and do the calculation below.

  • getRotationMatrix

    a[0] a[1] a[2]
    a[3] a[4] a[5]
    a[6] a[7] a[8]

  • Calculate pitch = Math.asin(-R[7])

  • Using pitch to determine the flatness of the device (I think you can use less than 45 and more than 135 to determine flatness, you just have to experiment to see if the azymuth value is correct)
  • if the device is not flat the rotation is Math.atan2(a[6], a[7])

  • If the device is flat to start with get the initial azymuth = Math.atan2(R[1], R[4]) and then take the difference with subsequent azymuths to get the rotation.

  • If the device transition from flat to not flat there should be no problem the rotation is just the rotation for not flat above.

  • If the device transition from not flat to flat then you need to get the initial azymuth. This initial azymuth can be set to the back camera direction Math.atan2(-a[2], -a[5]), if the device is upright and there is only rotation about the z-axis then this direction should not change. In reallity it will probably change by a few degrees so you will need to take the average.

All the math except for Math.atan2(a[6], a[7]) is explained at Android: Algorithms for SensorManager.getRotationMatrix and SensorManager.getOrientation()
So let me give the explanation for finding the rotation when the device is not flat.

As explained in the link above you have to specify the fixed vector and the vector that varies that you want to calculate the angle between them. In this case the vector that varies is a vector lying in the device y-axis and the fixed vector is the projection of the gravity vector into the device xy-plane. In the rotation matrix above the last row is the normalize gravity vector in device coordinate, thus the projection to the device xy-plane is (a[6], a[7]). Now it is simple trigonometry to see that Math.atan2(a[6], a[7]) is the angle between the device y-axis and the gravity projection. (Draw picture if you do not see it).

Community
  • 1
  • 1
Hoan Nguyen
  • 18,033
  • 3
  • 50
  • 54
  • Hello @Hoean Nguyen, Thank you for your effort. I really appreciate it. I tried to understand both this and the link answer but I might be missing some math background (or the lack of images might be holding me back). I'd like to understand more how things work but in the meantime i might have solved it by doing Math.atan2(gX, gY) where gX is values[0] and gY values[1] of TYPE_GRAVITY. – Andrea Baccega Feb 15 '16 at 19:41