views:

735

answers:

3

I need to calculate a rotation vector out of the data i get from Sensor.TYPE_ORIENTATION.

The sensor data is defined like this:

  • the values have to be recalculated to become a correct 3d position: values[0]: Azimuth, angle between the magnetic north direction and the Y axis, around the Z axis (0 to 359). 0=North, 90=East, 180=South, 270=West
  • values[1]: Pitch, rotation around X axis (-180 to 180), with positive values when the z-axis moves toward the y-axis.
  • values[2]: Roll, rotation around Y axis (-90 to 90), with positive values when the x-axis moves away from the z-axis

I need all three values like the Z axis value (from 0 to 360 degree). I tried a lot but cant figure out how to do this :/

i also tried to use Sensor.TYPE_ACCELEROMETER and Sensor.TYPE_MAGNETIC_FIELD to calculate this 3d vector on my own. here is the code:

final float[] inR = new float[16];
// load inR matrix from current sensor data:
SensorManager.getRotationMatrix(inR, null, gravityValues, geomagneticValues);
float[] orientation = new float[3];
SensorManager.getOrientation(inR, orientation);
mapMagAndAcclDataToVector(orientation); //here i do some *360 stuff
orientetionChanged(orientation); //then the correct values are passed (in theorie)

But this didn't work and i think it is much to complicated. So i bet there is a simple solution how to recalc the values of ensor.TYPE_ORIENTATION to make them a 3d rotation vector, but i just dont know how to do it. If you know the answer please tell me.

EDIT: i should add that i want to pass there values to OpenGL to align it to the axis like this:

gl.glRotatef(values[1], 1, 0, 0);
gl.glRotatef(values[2], 0, 1, 0);
gl.glRotatef(values[0], 0, 0, 1);

but because of the strange value ranges i obviously cant do this. the same problem with the values from SensorManager.getOrientation because they flip too when you pass the horizon line..

another solution would be to calculate the angles using the inR matrix but i think there must be an easier solution (?)

+3  A: 

This should work (using Sensor.TYPE_MAGNETIC_FIELD and Sensor.TYPE_ACCELEROMETER inputs)

switch (event.sensor.getType()) {
    case Sensor.TYPE_MAGNETIC_FIELD:
        magnitude_values = event.values.clone();
        sensorReady = true;
        break;
    case Sensor.TYPE_ACCELEROMETER:
        accelerometer_values = event.values.clone();
    }   

    if (magnitude_values != null && accelerometer_values != null && sensorReady) {
        sensorReady = false;

        float[] R = new float[16];
        float[] I = new float[16];

        SensorManager.getRotationMatrix(R, I, this.accelerometer_values, this.magnitude_values);

        float[] actual_orientation = new float[3];
        SensorManager.getOrientation(R, actual_orientation);
 }

Put this conde in your onSensorChanged. In actual_orientation you will have the vector that points to north respect to your actual position.

if you want to detect the north from the camera point of view you have to change the last line of code like this

float[] outR = new float[16];
SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_X, SensorManager.AXIS_Z, outR);
SensorManager.getOrientation(outR, actual_vals); 
hara
ok thanks alot for the code, as you can see in my post its nearly the same i did. the actual_orientation values that are returned from getOrientation have some strange range of values, they are not degree or from -1 to +1 or something like that. and i think there is still a value-flip when you are are rotating the device (somewhere at the horizon level).did you do anything with the actual_vals after this code snippets?
Sponge
yes..getOrientation returns values in radians. If you want degree's value you have to covert actual_vals..you welcome
hara
A: 

ok i thought i had a solution by doing the steps from this site backwards http://www.songho.ca/opengl/gl_anglestoaxes.html#anglestoaxes

but i was wrong and it still wont work :/ if anyone has an idea what to try next please tell me

EDIT: i created i community wiki entry to work on that problem, its also a good start if you want to use the sensor data with opengl es. some of the "transfair" methods are working so far. here is the link: http://stackoverflow.com/questions/2881128/how-to-use-onsensorchanged-sensor-data-in-combination-with-opengl

Sponge
A: 

ok now i got a solution, you have to do the openGl rotation in this order:

gl.glRotatef(values[2], 0, 1, 0);
gl.glRotatef(values[1], 1, 0, 0);
gl.glRotatef(values[0], 0, 0, 1);

use this in combination with SensorManager.getOrientation and it will work. if someone knows how to do this with the Sensor.TYPE_ORIENTATION data, please let me know.

Sponge