getRotationMatrix和getOrientation教程

时间:2011-08-12 21:40:21

标签: android orientation

我一直在努力使用getOrientation获取设备的实际方向。通过TYPE_ACCELEROMETER和TYPE_MAGNETIC_FIELD获取加速度计和磁场读数非常简单,通过TYPE_ORIENTATION获取方向也是如此。但是使用getOrientation根据世界坐标系获取方向。有许多好的教程herehere,但我还没有把它们放在一起。为此,我正在开发一个应用程序,它只是从getOrientation中吐出Accelerometer,Magnetic Field,原始Orientation数据和Orientation数据。我已经附加了代码,但它在我的手机上经常出现故障。有什么建议吗?

package com.sensorall;


import com.sensorall.R;
import android.hardware.*;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;



public class OrientationAccelerometer extends Activity {

    SensorManager sensorManager;
    float[] mGravs = new float[3];
    float[] mGeoMags = new float[3];
    float[] mRotationM = new float[16];
    float[] mInclinationM = new float[16];
    float[] mOrientation = new float[3];
    float[] mOldOreintation = new float[3];
    String[] mAccelerometer =  new String[3];
    String[] mMagnetic =  new String[3];    
    String[] mRotation =  new String[16];
    String[] mInclination =  new String[16];
    String[] mOrientationString =  new String[3];
    String[] mOldOreintationString =  new String[3];


    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.orientationaccelerometer);
        sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);

    } /* End onCreate activity */

    private SensorEventListener sensorEventListener = new SensorEventListener() {

        public void onAccuracyChanged(Sensor sensor, int accuracy) {

        }


        /* Get the Sensors */
        public void onSensorChanged(SensorEvent event) {

              switch (event.sensor.getType()) {
                     case Sensor.TYPE_ACCELEROMETER:
                              System.arraycopy(event.values, 0, mGravs, 0, 3);
                              break;
                     case Sensor.TYPE_MAGNETIC_FIELD:
                              System.arraycopy(event.values, 0, mGeoMags, 0, 3);
                              break;
                     case Sensor.TYPE_ORIENTATION:
                            System.arraycopy(event.values, 0, mOldOreintation, 0, 3);
                      break;

                     default:
                              return;
            }

                // If mGravs and mGeoMags have values then find rotation matrix
                if (mGravs != null && mGeoMags != null) {

                    // checks that the rotation matrix is found
                    boolean success = SensorManager.getRotationMatrix(mRotationM, mInclinationM, mGravs, mGeoMags);
                    if (success) {
                        /* getOrientation Values */   
                        SensorManager.getOrientation(mRotationM, mOrientation);

                          for(int i=0; i<2; i++){
                              mAccelerometer[i] = Float.toString(mGravs[i]);
                              mMagnetic[i] = Float.toString(mGeoMags[i]);
                              mOrientationString[i] = Float.toString(mOrientation[i]);
                              mOldOreintationString[i] = Float.toString(mOldOreintation[i]);
                          }

                          /* Make everything text to show on device */
                          TextView xaxisAccelerometerText = (TextView)findViewById(R.id.xaxisAccelerometer);
                          xaxisAccelerometerText.setText(mAccelerometer[0]);      
                          TextView yaxisAccelerometerText = (TextView)findViewById(R.id.yaxisAccelerometer);
                          yaxisAccelerometerText.setText(mAccelerometer[1]);
                          TextView zaxisAccelerometerText = (TextView)findViewById(R.id.zaxisAccelerometer);
                          zaxisAccelerometerText.setText(mAccelerometer[2]);    
                          TextView xaxisMagneticText = (TextView)findViewById(R.id.xaxisMagnetic);
                          xaxisMagneticText.setText(mMagnetic[0]);    
                          TextView yaxisMagneticText = (TextView)findViewById(R.id.yaxisMagnetic);
                          yaxisMagneticText.setText(mMagnetic[1]);
                          TextView zaxisMagneticText = (TextView)findViewById(R.id.zaxisMagnetic);
                          zaxisMagneticText.setText(mMagnetic[2]);
                          TextView xaxisOrientationText = (TextView)findViewById(R.id.xaxisOrientation);
                          xaxisOrientationText.setText(mOrientationString[0]);    
                          TextView yaxisOrientationText = (TextView)findViewById(R.id.yaxisOrientation);
                          yaxisOrientationText.setText(mOrientationString[1]);
                          TextView zaxisOrientationText = (TextView)findViewById(R.id.zaxisOrientation);
                          zaxisOrientationText.setText(mOrientationString[2]);
                          TextView xaxisOldOrientationText = (TextView)findViewById(R.id.xaxisOldOrientation);
                          xaxisOldOrientationText.setText(mOldOreintationString[0]);      
                          TextView yaxisOldOrientationText = (TextView)findViewById(R.id.yaxisOldOrientation);
                          yaxisOldOrientationText.setText(mOldOreintationString[1]);
                          TextView zaxisOldOrientationText = (TextView)findViewById(R.id.zaxisOldOrientation);
                          zaxisOldOrientationText.setText(mOldOreintationString[2]);

                    }else{

                         /* Make everything text to show on device even if getRotationMatrix fails*/
                          String matrixFailed = "Rotation Matrix Failed";
                          TextView xaxisAccelerometerText = (TextView)findViewById(R.id.xaxisAccelerometer);
                          xaxisAccelerometerText.setText(mAccelerometer[0]);      
                          TextView yaxisAccelerometerText = (TextView)findViewById(R.id.yaxisAccelerometer);
                          yaxisAccelerometerText.setText(mAccelerometer[1]);
                          TextView zaxisAccelerometerText = (TextView)findViewById(R.id.zaxisAccelerometer);
                          zaxisAccelerometerText.setText(mAccelerometer[2]);    
                          TextView xaxisMagneticText = (TextView)findViewById(R.id.xaxisMagnetic);
                          xaxisMagneticText.setText(mMagnetic[0]);    
                          TextView yaxisMagneticText = (TextView)findViewById(R.id.yaxisMagnetic);
                          yaxisMagneticText.setText(mMagnetic[1]);
                          TextView zaxisMagneticText = (TextView)findViewById(R.id.zaxisMagnetic);
                          zaxisMagneticText.setText(mMagnetic[2]);
                          TextView xaxisOrientationText = (TextView)findViewById(R.id.xaxisOrientation);
                          xaxisOrientationText.setText(matrixFailed);     
                          TextView yaxisOrientationText = (TextView)findViewById(R.id.yaxisOrientation);
                          yaxisOrientationText.setText(matrixFailed);
                          TextView zaxisOrientationText = (TextView)findViewById(R.id.zaxisOrientation);
                          zaxisOrientationText.setText(matrixFailed);
                          TextView xaxisOldOrientationText = (TextView)findViewById(R.id.xaxisOldOrientation);
                          xaxisOldOrientationText.setText(mOldOreintationString[0]);      
                          TextView yaxisOldOrientationText = (TextView)findViewById(R.id.yaxisOldOrientation);
                          yaxisOldOrientationText.setText(mOldOreintationString[1]);
                          TextView zaxisOldOrientationText = (TextView)findViewById(R.id.zaxisOldOrientation);
                          zaxisOldOrientationText.setText(mOldOreintationString[2]);





                    }
                }


        }
    };


    @Override
     protected void onResume() {
        super.onResume();
        sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
        sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_NORMAL);
        sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_NORMAL);
     }


    protected void onPause() {
        super.onPause();
        sensorManager.unregisterListener(sensorEventListener);
    }    

}

4 个答案:

答案 0 :(得分:3)

以下内容与我合作:

float[] r = new float[**16**];

对我

使用 null
float[] mOrientation = new float[4];  

4 而非 3 。但是你只使用3。

SensorManager.getRotationMatrix(rotationMatrix, null, accelVals, magVals); 

This code为我工作。

答案 1 :(得分:2)

这可能不适用于您的代码,但就使用getRotationMatrix()而言,它可能会解决其他问题。

我不确定这是否是我身上的版本问题,但我查看了getRotationMatrix()方法的源代码,与文档中有关R[]和{{的内容不同1}}参数, CAN NOT 为空。在声明我的I[]R之后:

I

float[] r = new float[9];

方法操作正确。

float[] i = new float[9]; - &gt; SensorManager.getRotationMatrix(r,i,gravity,geomagnetic)

......奇怪的文档错误。

答案 2 :(得分:0)

在回答需要关闭力量的应用时,听起来像是你经常在UI线程上做太多。您正在接收来自3个不同传感器的数据,延迟为SENSOR_DELAY_NORMAL。虽然这应该是大约5读数/秒,但我已经看到它每秒可以超过20个读数(因为传感器延迟只是建议的延迟)。因此,对于所有3个传感器,您每秒可以接收超过60个读数。对于每次阅读,您正在更新12 TextView,因此您每秒可以执行超过720次UI更新。这也导致我的手机崩溃。尝试在UI更新之间设置最短时间:

long currentTime = System.currentTimeMillis();
if ((currentTime - lastUpdateTime) >= MIN_TIME_BETWEEN_UPDATES) {
    // Update UI
    lastUpdateTime = currentTime;
}

如果需要,您可以快速存储数据以供使用,但会降低UI更新速度。

答案 3 :(得分:-2)

事件的接收不遵循线性程序执行流程。 为避免出现问题,建议将与传感器事件接收相关的代码放在互斥模块中。

我的意思是:

public void onSensorChanged(SensorEvent event) {
    synchronized (this) {
        ...
    }
}

希望这有帮助。