android – Explain about the interaction of the accelerometer and the magnetic field sensor in a smartphone

Question:

In general, what's the point: I'm picking the Studio to make an application that will show the angle of rotation of the device, I will give two codes below. In the first case, a gyroscope is used. I turn my smartphone – I get the angle to which I turned it. But there is a very big error here, if I may say so. If you turn the phone very slowly, the angle will not be counted at all. In the second case, an accelerometer and a magnetic field are used. And he counts very accurately – it doesn't matter how quickly I turn the smartphone or not. As for the first case, everything is extremely simple from the point of view of the code (although I don’t understand why he thinks so crookedly), and in the second code I cannot figure it out. I've already read everything line by line several times, but I still can't understand this interaction. Can someone chew or direct where to go to study info. It is possible to overseas

A snippet of code with a gyroscope

public class MainActivity extends AppCompatActivity implements 
SensorEventListener {

private float rotateY = 0f;
private SensorManager sensorManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
}

@Override
protected void onResume() {
super.onResume();

sensorManager.registerListener(this, 
sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
        SensorManager.SENSOR_DELAY_GAME);
}

@Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}

@Override
public void onSensorChanged(SensorEvent event) {

float degree = Math.round(event.values[1]);
rotateY += degree;
Log.d("TAG", "rotateY: " + rotateY);
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}

Fragment of code with accelerometer and magnetic field

public class MainActivity extends Activity {

TextView tvText;
SensorManager sensorManager;
Sensor sensorAccel;
Sensor sensorMagnet;

StringBuilder sb = new StringBuilder();

Timer timer;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    tvText = (TextView) findViewById(R.id.tvText);
    sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    sensorAccel = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    sensorMagnet = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}

@Override
protected void onResume() {
    super.onResume();
    sensorManager.registerListener(listener, sensorAccel, SensorManager.SENSOR_DELAY_NORMAL);
    sensorManager.registerListener(listener, sensorMagnet, SensorManager.SENSOR_DELAY_NORMAL);

    timer = new Timer();
    TimerTask task = new TimerTask() {
        @Override
        public void run() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    getDeviceOrientation();
                    showInfo();
                }
            });
        }
    };
    timer.schedule(task, 0, 10);

}

@Override
protected void onPause() {
    super.onPause();
    sensorManager.unregisterListener(listener);
    timer.cancel();
}

String format(float values[]) {
    return String.format("%1$.1f\t\t%2$.1f\t\t%3$.1f", values[0], values[1], values[2]);
}

void showInfo() {
    sb.setLength(0);
    sb.append("Orientation : " + format(valuesResult));
    tvText.setText(sb);
}

float[] r = new float[9];

void getDeviceOrientation() {
    SensorManager.getRotationMatrix(r, null, valuesAccel, valuesMagnet);
    SensorManager.getOrientation(r, valuesResult);

    valuesResult[0] = (float) Math.toDegrees(valuesResult[0]);
    valuesResult[1] = (float) Math.toDegrees(valuesResult[1]);
    valuesResult[2] = (float) Math.toDegrees(valuesResult[2]);
    return;
}


float[] valuesAccel = new float[3];
float[] valuesMagnet = new float[3];
float[] valuesResult = new float[3];



SensorEventListener listener = new SensorEventListener() {

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }

    @Override
    public void onSensorChanged(SensorEvent event) {



        switch (event.sensor.getType()) {
            case Sensor.TYPE_ACCELEROMETER:
                for (int i=0; i < 3; i++){
                    valuesAccel[i] = event.values[i];
                }
                break;
            case Sensor.TYPE_MAGNETIC_FIELD:
                for (int i=0; i < 3; i++){
                    valuesMagnet[i] = event.values[i];
                }
                break;
        }
    }
};

}

The second code was taken from this article

Answer:

Found the chemistry of this relationship here . getRotationMatrix paragraph. And the code with the gyroscope works so crookedly, because this is the rotational speed in rad / s, I did not catch it right away

Scroll to Top