Handy Orientierung auslesen

  • Antworten:12
  • OffenNicht stickyBentwortet
  • Forum-Beiträge: 407

08.11.2020, 17:09:50 via Website

Hallo zusammen

Ich möchte die Orientierung von meinem Handy auslesen. Ich habe ein Beispiel mit

magnetfeld = sensor.getDefaultSensor(Sensor.TYPE_ORIENTATION);

Doch ist TYPE_ORIENTATION veraltet. In der Doku steht man soll es mit

sensor = manager.getOrientation(R, values);

ersetzen. Aber ich mache was falsch. Es funktioniert nicht. Irgend wie verstehe ich es nicht.

image

Nach der Doku gibt es als Rückgabe ein Array. Aber ich sollte den Zugriff auf den Sensor erhalten. Oder verstehe ich da was ganz falsch. Wie muss ich die Orientierung auslesen. Was mache ich falsch?
Kann mir jemand zeigen wie es geht.

Zum Schluss mein Code:

package ch.robbisoft.accelerometer;

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.widget.TextView;

public class MainActivity extends AppCompatActivity implements SensorEventListener {

private TextView obj_x;
private TextView obj_y;
private TextView obj_z;

private SensorManager manager = null;
private float[] sensor = null;
private Context ctx;

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

    ctx = getApplicationContext();

    obj_x = findViewById(R.id.txt_x_wert);
    obj_y = findViewById(R.id.txt_y_wert);
    obj_z = findViewById(R.id.txt_z_wert);

    float[] R = new float[4];
    float[] values = new float[3];

    manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

// magnetfeld = sensor.getDefaultSensor(Sensor.TYPE_ORIENTATION);
sensor = manager.getOrientation(R, values);
}

@Override
protected void onResume() {
    super.onResume();
    manager.registerListener(ctx, sensor, SensorManager.SENSOR_DELAY_GAME);
}

@Override
protected void onPause() {
    manager.unregisterListener(ctx);
    super.onPause();
}

@Override
public void onSensorChanged(SensorEvent sensorEvent) {

}

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

}

}

Gruss Renato

Diskutiere mit!
Beste Antwort
  • Forum-Beiträge: 3.645

08.11.2020, 18:06:36 via Website

Hallo,

soweit mir bekannt ist , musst du in die benötigten Werte umrechnen .

Siehe Beispiel
https://www.ssaurel.com/blog/get-android-device-rotation-angles-with-accelerometer-and-geomagnetic-sensors/

— geändert am 08.11.2020, 18:07:53

Liebe Grüße - Stefan
[ App - Entwicklung ]

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 407

08.11.2020, 17:56:47 via Website

Hallo zusammen

Ist das vielleicht was?

package ch.robbisoft.accelerometer;

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.widget.TextView;

public class MainActivity extends AppCompatActivity implements SensorEventListener {

private TextView obj_x;
private TextView obj_y;
private TextView obj_z;

private SensorManager manager = null;
private Sensor sensor = null;

private final float[] accelerometerReading = new float[3];
private final float[] magnetometerReading = new float[3];

private final float[] rotationMatrix = new float[9];
private final float[] orientationAngles = new float[3];

private Context ctx;

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

    ctx = getApplicationContext();

    obj_x = findViewById(R.id.txt_x_wert);
    obj_y = findViewById(R.id.txt_y_wert);
    obj_z = findViewById(R.id.txt_z_wert);

    manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    sensor = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}

@Override
protected void onResume() {
    super.onResume();
    manager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);
}

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

@Override
public void onSensorChanged(SensorEvent event) {
    obj_x.setText(Float.toString( event.values[0] ));
    obj_y.setText(Float.toString( event.values[1] ));
    obj_z.setText(Float.toString( event.values[2] ));
}

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

}

}

Funktionieren tut es. Aber sind es auch die richtigen Werte die angezeigt werden?

Gruss Renato

Hilfreich?
Diskutiere mit!
Beste Antwort
  • Forum-Beiträge: 3.645

08.11.2020, 18:06:36 via Website

Hallo,

soweit mir bekannt ist , musst du in die benötigten Werte umrechnen .

Siehe Beispiel
https://www.ssaurel.com/blog/get-android-device-rotation-angles-with-accelerometer-and-geomagnetic-sensors/

— geändert am 08.11.2020, 18:07:53

Liebe Grüße - Stefan
[ App - Entwicklung ]

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 407

08.11.2020, 18:18:19 via Website

Ciao Stefan

Herzlichen Dank für die Hilfe.
Dachte ich es mir. Wenn ich die Zahlen die raus kommen anschauen, da kann schon was nicht stimmen.

Gruss Renato

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 407

09.11.2020, 10:46:47 via Website

Hallo zusammen

Bei mir kommen immer nur dieselben Werte raus.

SensorManager.getOrientation(outGravity, f_werte);

-180
0.0
-0.0

Sieht Jemand was ich falsch mache?

package ch.robbisoft.accelerometer;

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.widget.TextView;

public class MainActivity extends AppCompatActivity implements SensorEventListener {

private TextView obj_x;
private TextView obj_y;
private TextView obj_z;
private TextView obj_x_calc;
private TextView obj_y_calc;
private TextView obj_z_calc;

private SensorManager manager = null;
private Sensor sensor = null;

private final float[] accelerometerReading = new float[3];
private final float[] magnetometerReading = new float[3];

private final float[] rotationMatrix = new float[9];
private final float[] orientationAngles = new float[3];

private float accels[] = new float[3];
private float mags[] = new float[3];
private float[] f_werte = new float[3];

private float f_x_alt = 0.0f;
private float f_y_alt = 0.0f;
private float f_z_alt = 0.0f;

private Context ctx;

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

    ctx = getApplicationContext();

    obj_x = findViewById(R.id.txt_x_wert);
    obj_y = findViewById(R.id.txt_y_wert);
    obj_z = findViewById(R.id.txt_z_wert);

    obj_x_calc = findViewById(R.id.txt_x_calc);
    obj_y_calc = findViewById(R.id.txt_y_calc);
    obj_z_calc = findViewById(R.id.txt_z_calc);

    manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    sensor = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}

@Override
protected void onResume() {
    super.onResume();
    manager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);
}

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

@Override
public void onSensorChanged(SensorEvent event) {
    float f_x = event.values[0];
    float f_y = event.values[1];
    float f_z = event.values[2];

    if( Math.abs(f_x_alt - f_x) > 1 ){
        f_x_alt = f_x;
    }

    if( Math.abs(f_y_alt - f_y) > 1 ){
        f_y_alt = f_y;
    }

    if( Math.abs(f_z_alt - f_z) > 1 ){
        f_z_alt = f_z;
    }

    obj_x.setText(Float.toString( f_x_alt ));
    obj_y.setText(Float.toString( f_y_alt ));
    obj_z.setText(Float.toString( f_z_alt ));

    mags = event.values.clone();
    accels = event.values.clone();

    float[] gravity = new float[9];
    float[] magnetic = new float[9];
    SensorManager.getRotationMatrix(gravity, magnetic, accels, mags);
    float[] outGravity = new float[9];
    SensorManager.remapCoordinateSystem(gravity, SensorManager.AXIS_X,SensorManager.AXIS_Z, outGravity);
    SensorManager.getOrientation(outGravity, f_werte);

    float azimuth = f_werte[0] * 57.2957795f;
    float pitch = f_werte[1] * 57.2957795f;
    float roll = f_werte[2] * 57.2957795f;

    obj_x_calc.setText(Float.toString( azimuth ));
    obj_y_calc.setText(Float.toString( pitch ));
    obj_z_calc.setText(Float.toString( roll ));
}

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

}

}

Gruss Renato

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 407

09.11.2020, 10:59:01 via Website

Was mich besonders irritiert

bei der Variable "event" ändert sich der Inhalt. Hingegen "f_werte" bleiben konstant.

Irgendwas mache ich falsch. Aber was?
Gruss Renato

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 1.433

09.11.2020, 19:03:37 via Website

Hallo

Innerhalb des „onSensorChanged“ Listener ist es eigentlich nicht möglich auf dem Sensormanager zuzugreifen.

Nur ob das abfragen im Listener in der Form so geht darüber bin ich mir nicht sicher.

— geändert am 10.11.2020, 07:23:07

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 407

09.11.2020, 20:44:14 via Website

Ciao Jokel

Herzlichen Dank für deine Hilfe.

Innerhalb des „onSensorChanged“ Listener ist es eigentlich nicht möglich auf dem Sensormanager zuzugreifen.

Aha, und wie soll das gehen? Ich habe ein Beispiel welches es genau so macht.

private SensorEventListener mySensorEventListener = new SensorEventListener() {

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

public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_MAGNETIC_FIELD:
mags = event.values.clone();
break;
case Sensor.TYPE_ACCELEROMETER:
accels = event.values.clone();
break;
}

  if (mags != null && accels != null) {
     gravity = new float[9];
     magnetic = new float[9];
     SensorManager.getRotationMatrix(gravity, magnetic, accels, mags);
     float[] outGravity = new float[9];
     SensorManager.remapCoordinateSystem(gravity, SensorManager.AXIS_X,SensorManager.AXIS_Z, outGravity);
     SensorManager.getOrientation(outGravity, values);

     azimuth = values[0] * 57.2957795f;
     pitch =values[1] * 57.2957795f;
     roll = values[2] * 57.2957795f;
     mags = null;
     accels = null;
  }

}

Oder verstehe ich da was Falsch?
Wie sollte es richtig lauten. Hast du mir eventuell ein Beispiel das läuft.

Gruss Renato

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 407

09.11.2020, 21:14:15 via Website

Ciao Jokel

Du hast recht. Daten vom Magnetfeld werden ausgegeben. Aber von der Rotation nicht!
Reicht das Magnetfeld um die Position von meinem Handy zu ermitteln? Ich möchte wissen, in welche Richtung schaut mein Handy.

Gruss Renato

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 1.433

09.11.2020, 21:14:29 via Website

Beispiel habe ich jetzt nicht bei der Hand.

Schaue dir doch mal den link von swa00 genauer und richtig an.
In dem link werden auch zwei Listener auf die gleiche Methode gesetzt. Machst du nicht.

Dann wird in dem Listener, in der switch unterschieden von welchen Sensor er ausgelöst wurde. machst du zwar in deinem letzen Code.

Aber du setzt in deiner onResume nur einen Listener für den TYPE_ACCELEROMETER.
Für den TYPE_MAGNETIC_FIELD setzt du keinen.

Somit ist es eigentlich logisch das du keine Werte bekommst.

— geändert am 10.11.2020, 07:19:19

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 407

12.11.2020, 10:46:50 via Website

Ciao Jokel

Aber in einem Handler sollte der SensorManager verfügbar sein?

Gruss Renato

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 1.433

12.11.2020, 13:40:35 via Website

Ja du kannst in dem listener Methoden von der Manager Klasse benutzen um Berechnungen durchzuführen.

Aber du hast keinen listener auf die Methode gesetzt somit kommen auch keine Werte an wenn die sich ändern.

Du bekommst keine Werte magnetic field. Somit wir auch nie dein if Zweig ausgeführt werden. Da keine Werte im der Variablen mags sind.

— geändert am 12.11.2020, 15:53:30

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 407

12.11.2020, 18:10:55 via Website

Ciao Jokel

Danke für die Hilfe. Ich habe es nun wie folgt gelöst.

package ch.robbisoft.accelerometer;

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.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements SensorEventListener, Runnable {

private TextView obj_x;
private TextView obj_y;
private TextView obj_z;
private TextView obj_x_calc;
private TextView obj_y_calc;
private TextView obj_z_calc;
private TextView obj_azimut;
private TextView obj_pitch;
private TextView obj_roll;
private Button obj_pos;

private SensorManager manager = null;
private Sensor sensor_accels = null;
private Sensor sensor_magnet = null;
private Handler macher = new Handler();

private final float[] accelerometerReading = new float[3];
private final float[] magnetometerReading = new float[3];

private final float[] rotationMatrix = new float[9];
private final float[] orientationAngles = new float[3];

private float accels[] = new float[3];
private float mags[] = new float[3];
private float[] f_werte = new float[3];
private float azimuth = 0.0f;
private float pitch = 0.0f;
private float roll = 0.0f;

private float f_x_alt = 0.0f;
private float f_y_alt = 0.0f;
private float f_z_alt = 0.0f;
private float f_x_alt_m = 0.0f;
private float f_y_alt_m = 0.0f;
private float f_z_alt_m = 0.0f;

private Context ctx;

private static final float DIV = .5f;
private static final float DIVm = 10f;

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

    ctx = getApplicationContext();

    obj_x = (TextView) findViewById(R.id.txt_x_wert);
    obj_y = (TextView) findViewById(R.id.txt_y_wert);
    obj_z = (TextView) findViewById(R.id.txt_z_wert);

    obj_x_calc = (TextView) findViewById(R.id.txt_x_calc);
    obj_y_calc = (TextView) findViewById(R.id.txt_y_calc);
    obj_z_calc = (TextView) findViewById(R.id.txt_z_calc);

    obj_azimut = (TextView) findViewById(R.id.txt_azimut);
    obj_pitch = (TextView) findViewById(R.id.txt_pitch);
    obj_roll = (TextView) findViewById(R.id.txt_roll);

    obj_pos = (Button) findViewById(R.id.btn_pos);
    obj_pos.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            calc_pos();
        }
    });

    manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    sensor_accels = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    sensor_magnet = manager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

    macher.post(new Runnable() {
        @Override
        public void run() {
            calc_pos();
            macher.postDelayed(this, 1000L);
        }
    });
}

@Override
protected void onResume() {
    super.onResume();
    manager.registerListener(this, sensor_accels, SensorManager.SENSOR_DELAY_GAME);
    manager.registerListener(this, sensor_magnet, SensorManager.SENSOR_DELAY_GAME);
    macher.postDelayed(this, 1000L);
}

@Override
protected void onPause() {
    manager.unregisterListener(this);
    macher.removeCallbacks(this);
    super.onPause();
}

@Override
public void onSensorChanged(SensorEvent event) {

    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
        float f_x = event.values[0];
        float f_y = event.values[1];
        float f_z = event.values[2];

        accels = event.values.clone();

        if (Math.abs(f_x_alt - f_x) > DIV) {
            f_x_alt = f_x;
        }

        if (Math.abs(f_y_alt - f_y) > DIV) {
            f_y_alt = f_y;
        }

        if (Math.abs(f_z_alt - f_z) > DIV) {
            f_z_alt = f_z;
        }
        obj_x.setText(Float.toString( f_x_alt ));
        obj_y.setText(Float.toString( f_y_alt ));
        obj_z.setText(Float.toString( f_z_alt ));
    }

    if(event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD){
        float f_x_m = event.values[0];
        float f_y_m = event.values[1];
        float f_z_m = event.values[2];

        mags = event.values.clone();

        if (Math.abs(f_x_alt_m - f_x_m) > DIVm) {
            f_x_alt_m = f_x_m;
        }

        if (Math.abs(f_y_alt_m - f_y_m) > DIVm) {
            f_y_alt_m = f_y_m;
        }

        if (Math.abs(f_z_alt_m - f_z_m) > DIVm) {
            f_z_alt_m = f_z_m;
        }

        obj_x_calc.setText(Float.toString(f_x_alt_m));
        obj_y_calc.setText(Float.toString(f_y_alt_m));
        obj_z_calc.setText(Float.toString(f_z_alt_m));
    }
}

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

}

private void calc_pos(){
    if (mags != null && accels != null) {
        float[] gravity = new float[9];
        float[] magnetic = new float[9];
        manager.getRotationMatrix(gravity, magnetic, accels, mags);
        float[] outGravity = new float[9];
        manager.remapCoordinateSystem(gravity, SensorManager.AXIS_X, SensorManager.AXIS_Z, outGravity);
        manager.getOrientation(outGravity, f_werte);

        azimuth = f_werte[0] * 57.2957795f;
        pitch = f_werte[1] * 57.2957795f;
        roll = f_werte[2] * 57.2957795f;

        mags = null;
        accels = null;
    }
    obj_azimut.setText(Float.toString(azimuth));
    obj_pitch.setText(Float.toString(pitch));
    obj_roll.setText(Float.toString(roll));
}

@Override
public void run() {

}

}

Bestimmt kann man den Code noch verbessern. Aber es handelt sich nur um einen Versuch.

Noch eine letzt Frage: Weiss Jemand wie sich die Zahl "57.2957795f" zusammen setzt?

Gruss Renato

Hilfreich?
Diskutiere mit!