【Android Getting Started to Project Combat -- 9.4】—— A detailed tutorial on the use of the orientation sensor

Table of contents

1. Basic knowledge

2. Practical use


1. Basic knowledge

        The orientation sensor of Android returns the angle data of the three axes, and the unit of the orientation data is angle.

        Provide three data: azimuth, pitch and roll.

        azimuth: azimuth, the angle between the magnetic north pole and the Y axis when returning to the horizontal, the range is 0° to 360°; 0°=north, 90°=east, 180°=south, 270°=west.

        Pitch: The angle between the x-axis and the horizontal plane, ranging from -180° to 180°; when the z-axis rotates along the y-axis, the angle is a positive value.

        roll: The angle between the y-axis and the horizontal plane, ranging from -90° to 90°; when the x-axis moves along the z-axis, the angle is a positive value.

Use SensorManager.getOrientation() in the application to get the raw data.

public static float[] getOrientation (float[] R, float[] values)

The first parameter is the data used by R to save the magnetic field and acceleration, and the azimuth angle is obtained through this function.

The second parameter is the function output, the data is automatically populated.

  • values[0]: direction angle, but the data range obtained by (magnetic field + acceleration) is (-180~180), that is to say, 0 means true north, 90 means true east, 180/-180 means true south, - 90 means due west. The data range directly through the direction sensor is (0~359) 360/0 means true north, 90 means true east, 180 means true south, and 270 means true west.
  • values[1]: The pitch tilt angle starts from a static state, flips back and forth, lifts the top of the phone up (0~-90), and lifts the tail of the phone up (0~90)
  • values[2]: The roll rotation angle starts from a static state, flips left and right, lifts the left side of the phone (0~90), and lifts the right side of the phone (0~-90)

Get R through the function getRotationMatrix

public static boolean getRotationMatrix (float[] R, float[] I, float[] gravity, float[] geomagnetic)

register listener

sensorManager.registerListener(this, acc_sensor, SensorManager.SENSOR_DELAY_GAME); 
sensorManager.registerListener(this, mag_sensor,SensorManager.SENSOR_DELAY_GAME); 

 

2. Practical use

 As shown in the figure below: the simple detection with the following functions is realized below.

Can detect if pointing northeast, when the top of the phone is lifted, and if the right side of the phone is lifted.

Create a new project and modify the activity_main.xml code

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/textViewx"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/textViewy"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/textViewz"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

Modify the MainActivity code as follows:

public class MainActivity extends AppCompatActivity implements SensorEventListener {
    private SensorManager sm;
    TextView textViewx;
    TextView textViewy;
    TextView textViewz;
    //加速度传感器数据
    float accValues[] = new float[3];
    //地磁传感器数据
    float magValues[] = new float[3];
    //旋转矩阵,用来保存磁场和加速度的数据
    float r[] = new float[9];
    //模拟方向传感器的数据(原始数据为弧度)
    float values[] = new float[3];
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textViewx = (TextView) findViewById(R.id.textViewx);
        textViewy = (TextView) findViewById(R.id.textViewy);
        textViewz = (TextView) findViewById(R.id.textViewz);

//        获取传感器管理器
        sm = (SensorManager)getSystemService(SENSOR_SERVICE);
//        调用方法获得需要的传感器
        Sensor mSensorOrientation = sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        Sensor nSensorOrientation = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
//        注册监听器
//        SENSOR_DELAY_FASTEST最灵敏

//        SENSOR_DELAY_GAME 游戏的时候,不过一般用这个就够了

//        SENSOR_DELAY_NORMAL 比较慢。

//        SENSOR_DELAY_UI 最慢的
        sm.registerListener(this, mSensorOrientation, android.hardware.SensorManager.SENSOR_DELAY_UI);
        sm.registerListener(this, nSensorOrientation, android.hardware.SensorManager.SENSOR_DELAY_UI);

    }

    //    该方法在传感器的值发生改变的时候调用
    @Override
    public void onSensorChanged(SensorEvent event) {
        if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
            accValues = event.values.clone();
        }
        else if(event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD){
            magValues = event.values.clone();
        }

        /**
         * r:要填充的旋转数组
         * I: 将磁场数据转换进实际的重力坐标中,一般默认情况下可以设置为null
         * gravity: 加速度传感器数据
         * geomagnetic:地磁传感器数据
         */
        SensorManager.getRotationMatrix(r, null, accValues, magValues);

        /**
         * R:旋转数组
         * values:模拟方向传感器的数据
         */
        SensorManager.getOrientation(r, values);
        //将弧度转化为角度后输出
        float azimuth = (float) Math.toDegrees(values[0]);
        float pitch = (float) Math.toDegrees(values[1]);
        float roll = (float) Math.toDegrees(values[2]);
        if(azimuth >= 0 && azimuth <= 90){
            textViewx.setText(azimuth+"   "+"正指向东北方向");
        }else{
            textViewx.setText(azimuth+"");
        }
        if(pitch <=0 && pitch >= -90){
            textViewy.setText(pitch+"   "+"手机顶部正往上抬起");
        }else{
            textViewy.setText(pitch+"");
        }
        if(roll <=0 && pitch >= -90){
            textViewz.setText(roll+"   "+"手机右侧正往上抬起");
        }else{
            textViewz.setText(roll+"");
        }

    }

    //    当传感器的进度发生改变时会回调
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }
    //    在activity变为不可见的时候,传感器依然在工作,这样很耗电,所以我们根据需求可以在onPause方法里面停掉传感器的工作
    @Override
    public void onPause() {
        sm.unregisterListener(this);
        super.onPause();
    }
}

Guess you like

Origin blog.csdn.net/Tir_zhang/article/details/130544235