неправильные значения азимута

ниже вы увидите мой класс диспетчера датчиков. У меня он отлично работает с виртуальным компасом, но при нажатии я пытаюсь получить значение азимута, которое, согласно документации Google, должно возвращать 0 = север, 90 = восток, 180 = юг , а 270 = запад...

мое приложение настроено только на ландшафтный режим..

забавно, если

мой телефон держится в ПОРТРЕТ я получаю: 90 для севера, 180 для востока, -90 для юга и 0 для запада

если я держу его в режиме lanscape: от -40 до -60 для севера около 30 для востока -12 для юга -156 для запада

тот же код вращает матричный компас openGl, который виден, и именно так я сравниваю числа с тем, что магнитометр на самом деле считает магнитным севером .. я так запутался .. кто-нибудь, пожалуйста, помогите.

мой класс датчиков:

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);   
    }
}

Документация гугла:

*SENSOR_ORIENTATION, SENSOR_ORIENTATION_RAW: все значения представляют собой углы в градусах. values[0]: Азимут, вращение вокруг оси Z (0‹=азимут‹360). 0 = север, 90 = восток, 180 = юг, 270 = запад значения[1]: шаг, вращение вокруг оси X (-180‹=шаг‹=180), с положительными значениями, когда ось z движется к оси y- ось. values[2]: Roll, вращение вокруг оси Y (-90‹=roll‹=90), с положительными значениями, когда ось z движется к оси x. Обратите внимание, что это определение рыскания, тангажа и крена отличается от традиционного определения, используемого в авиации, где ось X проходит вдоль длинной стороны самолета (от хвоста к носу). обратите внимание, что я не использую sensor.orientation сейчас, так как он говорит, что метод, который я использую сейчас, более точен*

Я также включаю класс openGL, который создает точный компас, используя те же данные датчика, с функцией длительного нажатия, называемой newTAg, которая выдает мне данные датчика в тосте.

тост выглядит так:

   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();

    }

}

person erik    schedule 12.07.2012    source источник


Ответы (1)


Проблема решена. Я вернулся к использованию рыскания или азимута от датчика ориентации. Я делал это раньше и сталкивался с той же проблемой, но понял, что моя проблема заключалась в том, что я использовал его как число с плавающей запятой, а не как двойное... позже обновлю код. Если кто-то может объяснить мне, почему это было бы полезно. Я думал, что единственная разница между числами с плавающей запятой и числами с двойным числом заключается в общем количестве битов.

person erik    schedule 13.07.2012