4

For my App I need to calculate the acceleration of my device in reference to true north. My idea was to calculate the device orientation to magnetic north and apply the declination to it to get the orientation to true north. Then I want to calculate the acceleration of the device and reference it to the orientation, but I do not know how I should do this.

I would try to get the device orientation using SensorManager.getRotationMatrix() and SensorManager.getOrientation(). Then I get the declination by GeomagneticField.getDeclination()and apply it on the azimuth of the orientation values from SensorManager.getOrientation().

But how do I map the accelerometer values to this orientation? Is it even possible?

htz
  • 1,037
  • 1
  • 13
  • 37
  • If I understood you correctly, what you are saying is if the device is moving toward the West or East then the accelerator value in this case should be 0, am I right? – Hoan Nguyen Feb 20 '13 at 04:32
  • No, I need to remap the axis of the accelerometer in that way, that when the device (i.e.) is moving north, the y-value is positive and moving south it is negative. And when moving east the x- value is positive and when moving west it is negative. The z-value is currently not needed. I think I found a good source in this question: http://stackoverflow.com/questions/11578636/acceleration-from-devices-coordinate-system-into-absolute-coordinate-system – htz Feb 20 '13 at 12:01
  • Of course, when there is a constant motion towards any direction, the values should be 0, because there is no acceleration measureable. – htz Feb 20 '13 at 12:13
  • All the calculations in the solution in the above link seem unnessaire. See my solution below. – Hoan Nguyen Feb 20 '13 at 19:30

1 Answers1

8

The accelerometer sensor returns the acceleration of the device. This is a vector in 3 dimentional space. This vector is returned in the device coordinate system. What you want is the coordinate of this vector in the world coordinate, which is simply

R = rotation matrix obtained by calling getRotationMatrix
A_D = accelerator vector return by sensor ( A_D = event.values.clone )
A_W = R * A_D is the same acceleration vector in the world coordinate system.

A_W is an array of dimention 3 
A_W[0] is acceleration due east.
A_W[1] is acceleration due north.

Here is some code to compute it (assumes gravity and magnetic contain output from their respective sensors):

            float[] R = new float[9];
            float[] I = new float[9];
            SensorManager.getRotationMatrix(R, I, gravity, magnetic);
            float [] A_D = values.clone();
            float [] A_W = new float[3];
            A_W[0] = R[0] * A_D[0] + R[1] * A_D[1] + R[2] * A_D[2];
            A_W[1] = R[3] * A_D[0] + R[4] * A_D[1] + R[5] * A_D[2];
            A_W[2] = R[6] * A_D[0] + R[7] * A_D[1] + R[8] * A_D[2];
gregm
  • 12,019
  • 7
  • 56
  • 78
Hoan Nguyen
  • 18,033
  • 3
  • 50
  • 54
  • 1
    I believe your answer may be wrong (see my comment in the accepted answer in http://stackoverflow.com/questions/11578636/acceleration-from-devices-coordinate-system-into-absolute-coordinate-system) – ravemir Apr 16 '13 at 18:36
  • No, if you really understand what the rotation matrix is and look at how it is calculate in the source code. It is just the change of basis matrix from the device coordinate system to the world coordinate system. – Hoan Nguyen Apr 16 '13 at 18:40
  • This [link] (http://gentlenav.googlecode.com/files/DCMDraft2.pdf) provides an explanation of the rotation matrix, and reports the World Coords as the product of the Rotation Matrix and the Plane Coords. Given that, the rotation matrix computed by Android may be one that maps Device to World (the reverse of the example), but how can you know for sure? – ravemir Apr 16 '13 at 18:54
  • 1
    In the android-sdk --> sources --> android-17 --> android --> hardware --> SensorManager. Or any android-number you want instead of 17 – Hoan Nguyen Apr 16 '13 at 19:04
  • To get rotation matrix, you would need gravity. But how can you get gravity when there is also nonzero linear acceleration which is the point of this calculation? – windchime Jun 15 '13 at 05:09
  • You have to filter out linear acceleration, that is why you have to at least use low pass filter. You can read my answer at http://stackoverflow.com/questions/15315129/convert-magnetic-field-x-y-z-values-from-device-into-global-reference-frame/15317814#15317814. It is better if you use TYPE_GRAVITY, it is better estimate than low pass filter. – Hoan Nguyen Jun 15 '13 at 05:16
  • What is the line of code to compute: A_W = R * A_D is the same acceleration vector in the world coordinate system? – gregm Sep 12 '13 at 20:06
  • This is just a product of a matrix and a vector so A_W[0] = R[0] * A_D[0] + R[1] * A_D[1] + R[2] * A_D[2], A_W[1] = R[3] * A_D[0] + ... – Hoan Nguyen Sep 12 '13 at 20:34
  • I edited the answer. Does my code look correct? When I run it, the values don't make complete sense. – gregm Sep 13 '13 at 18:31
  • The code is correct. You have to give an example of "the values don't make complete sense". – Hoan Nguyen Sep 13 '13 at 18:35
  • It is tough to test. When I move my device in the direction of east, the output of A_W[0] should be high, and A_W[1] should be low. However, moving east causes similar values in A_W[0] and A_W[1]. What is a good way to test? – gregm Sep 13 '13 at 18:50
  • You should use TYPE_GRAVITY or low pass filter the accelerometer for the gravity parameter in getRotationMatrix. – Hoan Nguyen Sep 13 '13 at 18:58
  • What happens when the device is not in motion? are A_W[0] and A_W[1] approximately 0. – Hoan Nguyen Sep 13 '13 at 19:28
  • Yes, they are approximately 0 – gregm Sep 13 '13 at 19:30
  • You should test outside there maybe magnetic interference in the room. I take it for granted that when you say moving East, the direction is according to a compass. – Hoan Nguyen Sep 13 '13 at 19:34
  • Can you add source code for calibration relative to Earth positioning? – eyal May 10 '15 at 15:06