经过测试和观察,螺旋传感器启动监控时的角度为0度,因此我认为角度值可以在每次转向后回复到零度角度,解决了上一篇文章中误差大的问题;
angle[2] = sensorEvent.values[2] * dT;
// 将弧度转化为角度
anglez = (float) Math.toDegrees(angle[2]);
data = anglez;
灵敏度问题:1.设置灵敏度SensorManager.SENSOR_DELAY_GAME 一般益智游戏水平
2.直接设置两个临界值
data > 80 左转,angle[2] = 0;
data < -80 右转,angle[2] = 0;
在一定时间内连续两次左转左转头,右转头
理论上不存在直接跳出角度判断区间的情况;
3.:有一种不合理的情况:先左转75度,再右转75度,实际角度偏差150度,但不会触发转向代码;
代码:
package com.zznode.sensor; import androidx.appcompat.app.AppCompatActivity; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity implements SensorEventListener { private TextView souce_z; private TextView data_z; private TextView orientation_z; private SensorManager mSensorManager; private Sensor gyroscopeSensor; private float data; private Button clear; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); souce_z = findViewById(R.id.souce_z); data_z = findViewById(R.id.data_z); clear = findViewById(R.id.clear); clear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { sb.setLength(0); } }); orientation_z = findViewById(R.id.orientation_z); mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); gyroscopeSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); /** * 注册陀螺仪传感器,将传感器输出到应用程序中的时间间隔类型设置为SensorManager.SENSOR_DELAY_GAME(20000微秒) * SensorManager.SENSOR_DELAY_FASTEST(0微秒):最快。最低延迟,一般不是特别敏感的处理不推荐使用,该模式可能会消耗大量的手机功率,因为传输原始数据,诉讼处理不当会影响游戏逻辑UI的性能 * SensorManager.SENSOR_DELAY_GAME(2万微秒):游戏。游戏延迟,一般绝大多数实时游戏都使用这个级别 * SensorManager.SENSOR_DELAY_NORMAL(2万微秒):普通。标准延时,对于一般的益智类或EASY水平游戏可以使用,但采样率过低可能会导致一些赛车游戏跳帧 * SensorManager.SENSOR_DELAY_UI(6万微秒):用户界面。一般来说,屏幕方向自动旋转使用相对节省电能和逻辑处理,一般游戏开发不使用 */ } @Override protected void onResume() { super.onResume(); mSensorManager.registerListener(this, gyroscopeSensor, SensorManager.SENSOR_DELAY_GAME); } @Override protected void onPause() { super.onPause(); mSensorManager.unregisterListener(this); } // 将纳秒转化为秒 private static final float NS2S = 1.0f / 1000000000.0f; private float timestamp; private float angle[] = new float[3]; StringBuilder sb = new StringBuilder(); private float oldTime; ///记录上次转弯的时间 private int oldTurn;//记录上次转向的方向,右转,2左转,0初始值 @Override public void onSensorChanged(SensorEvent sensorEvent) { synchronized (this){ float anglex; float angley; float anglez; if (timestamp != 0) { // 两次检测到手机旋转的时差(纳秒),并将其转化为秒 final float dT = (sensorEvent.timestamp - timestamp) * NS2S; // 在每个轴上添加手机的旋转角度,与初始位置相比,当前位置的旋转弧可以得到 angle[0] = sensorEvent.values[0] * dT; angle[1] = sensorEvent.values[1] * dT; angle[2] = sensorEvent.values[2] * dT; // 将弧度转化为角度 anglex = (float) Math.toDegrees(angle[0]); angley = (float) Math.toDegrees(angle[1]); anglez = (float) Math.toDegrees(angle[2]); data = anglez; System.out.println("Z=========" anglez); if (data > 80 ) { if ((sensorEvent.timestamp - oldTime) * NS2S < 1.5 && oldTurn == 2){ sb.append("左转调头,"); oldTurn = 0; }else { sb.append("左转,"); oldTurn = 2; } angle[2] = 0; oldTime = sensorEvent.timestamp; } else if (data < -80 ) { if ((sensorEvent.timestamp - oldTime) * NS2S < 1.5 && oldTurn ==1){ sb.append("右转调头了,"); oldTurn = 0; }else { sb.append("右转,"); oldTurn = 1; } angle[2] = 0; oldTime = sensorEvent.timestamp; }else if (data > 180 || data < -180){//容错,以防角度超过+-180度后转向无法触发 sb.append("方向异常,"); oldTurn = 0; angle[2] = 0; oldTime = sensorEvent.timestamp; } gyroscopeSensor.getMinDelay(); } //将当前时间赋值给timestamp timestamp = sensorEvent.timestamp; souce_z.setText(angle[2]+""); data_z.setText(data+""); orientation_z.setText(sb.toString()); } } @Override public void onAccuracyChanged(Sensor sensor, int i) { } }