Android phone orientation overview including compass

前端 未结 4 1389
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-28 01:08

I\'ve been trying to get my head around the Android orientation sensors for a while. I thought I understood it. Then I realised I didn\'t. Now I think (hope) I have a better

4条回答
  •  迷失自我
    2020-11-28 01:21

    You might want to check out the One Screen Turn Deserves Another article. It explains why you need the rotation matrix.

    In a nutshell, the phone's sensors always use the same coordinate system, even when the device is rotated.

    In applications that are not locked to a single orientation, the screen coordinate system changes when you rotate the device. Thus, when the device is rotated from its default view mode, the sensor coordinate system is no longer the same as the screen coordinate system. The rotation matrix in this case is used to transform A to C (B always remains fixed).

    Here's a code snippet to show you how it can be used.

    SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE);
    
    // Register this class as a listener for the accelerometer sensor
    sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
                        SensorManager.SENSOR_DELAY_NORMAL);
    // ...and the orientation sensor
    sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
                        SensorManager.SENSOR_DELAY_NORMAL);
    
    //...
    // The following code inside a class implementing a SensorEventListener
    // ...
    
    float[] inR = new float[16];
    float[] I = new float[16];
    float[] gravity = new float[3];
    float[] geomag = new float[3];
    float[] orientVals = new float[3];
    
    double azimuth = 0;
    double pitch = 0;
    double roll = 0;
    
    public void onSensorChanged(SensorEvent sensorEvent) {
        // If the sensor data is unreliable return
        if (sensorEvent.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)
            return;
    
        // Gets the value of the sensor that has been changed
        switch (sensorEvent.sensor.getType()) {  
            case Sensor.TYPE_ACCELEROMETER:
                gravity = sensorEvent.values.clone();
                break;
            case Sensor.TYPE_MAGNETIC_FIELD:
                geomag = sensorEvent.values.clone();
                break;
        }
    
        // If gravity and geomag have values then find rotation matrix
        if (gravity != null && geomag != null) {
    
            // checks that the rotation matrix is found
            boolean success = SensorManager.getRotationMatrix(inR, I,
                                                              gravity, geomag);
            if (success) {
                SensorManager.getOrientation(inR, orientVals);
                azimuth = Math.toDegrees(orientVals[0]);
                pitch = Math.toDegrees(orientVals[1]);
                roll = Math.toDegrees(orientVals[2]);
            }
        }
    }
    

提交回复
热议问题