Search code examples
androidandroid-sensors

azimuth wrong values


below you will see my sensor manager class.. I have it working with a virtual compass just fine, but on click i am trying to get the azimuth value which according to google documentation should return 0=North, 90=east, 180 = south,and 270 = west...

my app is set to landscape mode only..

funny thing is if

my phone is held in PORTRAIT i get: 90 for North, 180 for east, -90 for south, and 0 for west

if i hold it in lanscape mode: -40 to -60 for North around 30 for east -12 for south -156 for west

the same code is rotating a matrix openGl Compass that is visible which is how i am comparing the numbers with what the magnetometer actually thinks magnetic north is.. i am so confused.. someone please oh please help.

my sensor class:

public void start(Context context,final int displayOrientation) {
            listener = new SensorEventListener() {
            private int displayOri = displayOrientation;

            public void onAccuracyChanged(Sensor arg0, int arg1){}

            public void onSensorChanged(SensorEvent evt) {
                int type=evt.sensor.getType();

                if (type == Sensor.TYPE_MAGNETIC_FIELD) {
                    orientation[0]=(orientation[0]*1+evt.values[0])*0.5f;
                    orientation[1]=(orientation[1]*1+evt.values[1])*0.5f;
                    orientation[2]=(orientation[2]*1+evt.values[2])*0.5f;
                } else if (type == Sensor.TYPE_ACCELEROMETER) {
                    acceleration[0]=(acceleration[0]*2+evt.values[0])*0.33334f;
                    acceleration[1]=(acceleration[1]*2+evt.values[1])*0.33334f;
                    acceleration[2]=(acceleration[2]*2+evt.values[2])*0.33334f;
                }
                if ((type==Sensor.TYPE_MAGNETIC_FIELD) || (type==Sensor.TYPE_ACCELEROMETER)) {
                    float newMat[]=new float[16];

                    //Toast toast = Toast.makeText(ctx.getApplicationContext(), "accel", Toast.LENGTH_SHORT);
                    //toast.show();
                    SensorManager.getRotationMatrix(newMat, null, acceleration, orientation);
                    if(displayOri==0||displayOri==2){
                        SensorManager.remapCoordinateSystem(newMat,SensorManager.AXIS_X*-1, SensorManager.AXIS_MINUS_Y*-1,newMat);
                    }else{
                        SensorManager.remapCoordinateSystem(newMat,SensorManager.AXIS_Y, SensorManager.AXIS_MINUS_X,newMat);
                    }

                    matrix=newMat;
                    SensorManager.getOrientation (newMat, orientationValues); 
                }
            }
        };

        sensorMan = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
        sensorAcce = sensorMan.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
        sensorMagn = sensorMan.getSensorList(Sensor.TYPE_MAGNETIC_FIELD).get(0);
        //sensorOri = sensorMan.getSensorList(Sensor.TYPE_ORIENTATION).get(0);

        sensorMan.registerListener(listener, sensorAcce, SensorManager.SENSOR_DELAY_UI);
        sensorMan.registerListener(listener, sensorMagn, SensorManager.SENSOR_DELAY_UI);    
        //sensorMan.registerListener(listener, sensorOri, SensorManager.SENSOR_DELAY_UI);   
    }

    public float[] getMatrix() {
        return matrix;
    }
    public float getRoll(){
        return roll;
    }
    public float[] getACC(){
        return acceleration;
    }
    public float[] getORI(){
        return orientationValues;

    }
    public float getIncline(){
        return sensorMan.getInclination(matrix);
    }
    public void finish() {
        sensorMan.unregisterListener(listener);
    }
    public void onPause() {
        sensorMan.unregisterListener(listener);
    }
    public void onResume(){
        sensorMan.registerListener(listener, sensorAcce, SensorManager.SENSOR_DELAY_UI);
        sensorMan.registerListener(listener, sensorMagn, SensorManager.SENSOR_DELAY_UI);
        //sensorMan.registerListener(listener, sensorOri, SensorManager.SENSOR_DELAY_UI);   
    }
}

google Documentation:

*SENSOR_ORIENTATION, SENSOR_ORIENTATION_RAW: All values are angles in degrees. values[0]: Azimuth, rotation around the Z axis (0<=azimuth<360). 0 = North, 90 = East, 180 = South, 270 = West values[1]: Pitch, rotation around X axis (-180<=pitch<=180), with positive values when the z-axis moves toward the y-axis. values[2]: Roll, rotation around Y axis (-90<=roll<=90), with positive values when the z-axis moves toward the x-axis. Note that this definition of yaw, pitch and roll is different from the traditional definition used in aviation where the X axis is along the long side of the plane (tail to nose). note i am not using sensor.orientation now as it says the method im using now is more accurate*

I am also including the openGL class that creates an accurate compass using the same sensor data with a long press function called newTAg that throws the sensor data at me in a toast..

the toast looks like this:

   Toast.makeText(getContext(), "INLCINE:"+phoneOri.getIncline()+" azimuth:"+Math.toDegrees(tagOri[0])+" pitch:"+Math.toDegrees(tagOri[1])+" roll:"+Math.toDegrees(tagOri[2]),Toast.LENGTH_LONG).show();

public GLLayer(Context context, int orientation) {
        super(context);

        this.context = context;
        //this.square = new Square();
        this.cRing = new Circle();
        this.cNeedle = new CompassNeedle();

        this.mNorth = new MarkerNorth();
        this.mEast = new MarkerEast();
        this.mSouth = new MarkerSouth();
        this.mWest = new MarkerWest();

        this.mSWest = new MarkerSouthWest();
        this.mSEast = new MarkerSouthEast();
        this.mNWest = new MarkerNorthWest();
        this.mNEast = new MarkerNorthEast();
        this.mtag = new tagImage();
        phoneOri=new PhoneOrientation(context); // sensor manager and interpreter

        // settings for translucent glView
        this.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
        this.getHolder().setFormat(PixelFormat.TRANSLUCENT);

        // set render to inline 
        this.setRenderer(this);
        phoneOri.start(context, orientation);

    }

    @Override
    public void onDrawFrame(GL10 gl) {
        gl.glEnable(GL10.GL_TEXTURE_2D);


        // clear Screen and Depth Buffer
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

        // Reset the Modelview Matrix
        gl.glLoadIdentity();

        //GLU.gluLookAt(gl, eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
        GLU.gluLookAt(gl,0, 0, 0, 0, 0, 0, 0, 0, 0);
        //GLU.gluLookAt(gl, 90.0f, 1.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0, 1.0f, 0);

        float floatMat[]=phoneOri.getMatrix();

        gl.glMatrixMode(GL10.GL_MODELVIEW);


        //
        //gl.glTranslatef(0,0,-200.0f);
        //cRing.draw(gl);
        //DrawCompass Needle and Markers


        gl.glLoadMatrixf(floatMat, 0);

        for(int i=0;i<tags.size();i++){
            gl.glPushMatrix();

            //GLU.gluLookAt(gl,0, 0, 0, 0, 0, 0, 0, 0, 0);
            //float angle = phoneOri.sensorMan,getAngleChange();
            gl.glRotatef(90,2, 0,0);
            mtag.draw(gl);
            gl.glLoadMatrixf(floatMat,0);
        }

        gl.glPushMatrix();
        gl.glTranslatef(0,0,-10.0f);
        cNeedle.draw(gl);
        gl.glLoadMatrixf(floatMat,0);
        //Draw compass ring
        //gl.glPushMatrix();
        gl.glTranslatef(0,0,10.0f);
        cRing.draw(gl);


        //Draw South
        gl.glTranslatef(0.0f,-150.0f,-10.0f);
        mSouth.draw(gl); 

        //Draw West
        gl.glTranslatef(-150.0f,150.0f,0.0f);
        mWest.draw(gl);

        //DrawNorth
        gl.glTranslatef(150.0f,150.0f,0.0f);
        mNorth.draw(gl); 

        //DrawEast
        gl.glTranslatef(150.0f,-150.0f,0.0f);
        mEast.draw(gl);

        //SW
        gl.glTranslatef(-225.0f, -75.0f, 0.0f);
        mSWest.draw(gl);

        // NW
        gl.glTranslatef(0.0f,150.f,0);
        mNWest.draw(gl);

        gl.glTranslatef(150.0f, 0f, 0f);
        mNEast.draw(gl);

        gl.glTranslatef(0.0f,-150.0f,0.0f);
        mSEast.draw(gl);


        // Drawing
        //gl.glNormal3f(0,0,1);
        //gl.glTranslatef(0.0f,-150.0f,0.0f);     // move 5 units INTO the screen
        //square.draw(gl);                       // Draw the square

         gl.glPushMatrix();

    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        if(height == 0) {                    //Prevent A Divide By Zero By
        height = 1;                         //Making Height Equal One
        }
        float ratio = (float) width / height;
        gl.glViewport(0, 0, width, height);     //Reset The Current Viewport
        gl.glMatrixMode(GL10.GL_PROJECTION);    //Select The Projection Matrix
        gl.glLoadIdentity();                    //Reset The Projection Matrix
                                                //Calculate The Aspect Ratio Of The Window

        //gl.glFrustumf(-ratio, ratio, -1, 1, 1, 100);
        GLU.gluPerspective(gl, 35.0f, (float)width / (float)height, 5.0f, 200.0f);
        gl.glMatrixMode(GL10.GL_MODELVIEW);     //Select The Modelview Matrix
        gl.glLoadIdentity();                    //Reset The Modelview Matrix

        GLU.gluLookAt(gl, 0, 1.0f, 5.0f, 0, 0, 0, 0, 1.0f, 0);


    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig arg1) {
        // Load the texture for the square
        //square.loadGLTexture(gl, this.context);
        cRing.loadGLTexture(gl, this.context);
        cNeedle.loadGLTexture(gl, this.context);
        mNorth.loadGLTexture(gl, this.context);
        mEast.loadGLTexture(gl, this.context);
        mSouth.loadGLTexture(gl, this.context);
        mWest.loadGLTexture(gl, this.context);
        mSWest.loadGLTexture(gl, this.context);
        mNWest.loadGLTexture(gl, this.context);
        mSEast.loadGLTexture(gl, this.context);
        mNEast.loadGLTexture(gl, this.context);

        gl.glEnable(GL10.GL_TEXTURE_2D);            //Enable Texture Mapping ( NEW )
        gl.glShadeModel(GL10.GL_SMOOTH);            //Enable Smooth Shading
        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);    //Black Background
        gl.glClearDepthf(1.0f);                     //Depth Buffer Setup
        gl.glEnable(GL10.GL_DEPTH_TEST);            //Enables Depth Testing
        gl.glDepthFunc(GL10.GL_LEQUAL);             //The Type Of Depth Testing To Do

        //Really Nice Perspective Calculations
        //gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_SMOOTH);

    }

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        // TODO Auto-generated method stub

    }
    public void newTag(){
        float tagOri[] = new float[3];
        tagOri = phoneOri.getORI();
        tags.add(phoneOri.getMatrix());
        Toast.makeText(getContext(), "INLCINE:"+phoneOri.getIncline()+" azimuth:"+Math.toDegrees(tagOri[0])+" pitch:"+Math.toDegrees(tagOri[1])+" roll:"+Math.toDegrees(tagOri[2]),Toast.LENGTH_LONG).show();

    }

}

Solution

  • Problem solved.. I resorted back to using yaw or azimuth from the orientation sensor. I was doing this before and getting the same issue but figured out that my problem was that I was casting it as float instead of a double.. will update the code later. If someone can explain to me why that would be helpful. I thought that the only difference between floats and doubles was total bits.. and was casting as a float thinking I wouldn't need that extra 32 bits