How can I get the tilt of the device?

I am trying to get the device tilted (turning the device on the Y axis, but unfortunately I canโ€™t achieve my goal. I tried many things using TYPE_ACCELEROMETER and TYPE_MAGNETIC_FIELD as a combined sensor (merging sensors). After Motion sensors

What I want?

I want to get the tilt of a device (cell phone) attached to a vehicle. Say I attached a device in a car and the car is stationary. Thus, the slope is 0 degrees. When the vehicle is switched on through walkways or overpasses, the slope should be appropriate. I tried to calculate this, here is my code:

... ... private static float ALPHA = 0.005f TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); tv = (TextView) findViewById(R.id.tv); edtAlpha = (EditText) findViewById(R.id.alpha); mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); accelerometer = mSensorManager .getDefaultSensor(Sensor.TYPE_ACCELEROMETER); magnetometer = mSensorManager .getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); if (accelerometer == null) { Toast.makeText(this, "Oh not found", Toast.LENGTH_SHORT).show(); } if (magnetometer == null) { Toast.makeText(this, "Oh magnetometer not found", Toast.LENGTH_SHORT).show(); } } protected float[] lowPass(float[] input, float[] output) { if (output == null) return input; String s = edtAlpha.getText().toString(); if (s != null && s.length() > 0) { try { ALPHA = Float.valueOf(s); } catch (NumberFormatException e) { ALPHA = 0.005f; } } else { ALPHA = 0.005f; } for (int i = 0; i < input.length; i++) { output[i] = output[i] + ALPHA * (input[i] - output[i]); } return output; } public int getRotation(final Activity activity) { int result = 1; Method mDefaultDisplay_getRotation; try { mDefaultDisplay_getRotation = Display.class.getMethod( "getRotation", new Class[] {}); Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay(); Object retObj = mDefaultDisplay_getRotation.invoke(display); if (retObj != null) { result = (Integer) retObj; } } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } return result; } @Override public void onSensorChanged(SensorEvent event) { Log.d(tag, "onSensorChanged"); if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { gravSensorVals = lowPass(event.values.clone(), gravSensorVals); } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { magSensorVals = lowPass(event.values.clone(), magSensorVals); } if (gravSensorVals != null && magSensorVals != null) { SensorManager.getRotationMatrix(RTmp, I, gravSensorVals, magSensorVals); int rotation = getRotation(this); if (rotation == 1) { SensorManager.remapCoordinateSystem(RTmp, SensorManager.AXIS_X, SensorManager.AXIS_MINUS_Z, Rot); } else { SensorManager.remapCoordinateSystem(RTmp, SensorManager.AXIS_Y, SensorManager.AXIS_MINUS_Z, Rot); } SensorManager.getOrientation(Rot, results); float azimuth = (float) (((results[0] * 180) / Math.PI) + 180); float pitch = (float) (((results[1] * 180 / Math.PI)) + 90); float roll = (float) (((results[2] * 180 / Math.PI))); tv.setText("Azimuth : " + df.format(azimuth) + "\nPitch : " + df.format(pitch) + "\nRoll : " + df.format(roll)); } Log.d(tag, "Sensor type : " + event.sensor.getType()); } @Override protected void onResume() { super.onResume(); mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_UI); mSensorManager.registerListener(this, magnetometer, SensorManager.SENSOR_DELAY_UI); } ... ... 

What is the problem with my code?

When I quickly accelerate / de-sphere my car, the angle quickly increases / decreases, but this should not. In other words, when I accelerate / decaf a car, there should be no effect on the angle. I also tried following these tutorials: Link 1 Link 2 , etc.

+1
source share
2 answers

First of all, you should avoid the direct use of accelerometer or magnetometer data unless you REALLY know what consequences and what data you get from these sensors.

I personally recommend you use the predefined ROTATION_VECTOR sensor, which compresses the Accelerometer, Magnetometer and Gyroscope in Kalman-Filter. (see this , how to get data from the ROTATION_VECTOR sensor and this how to use data).

When you start with this project, you can simply access the quaternion and play with it or using the rotation matrix and apply the appropriate conversion to get the angles of your deviceโ€™s eulers (names are not always consistent, but you are most likely interested in the bank or attitude ), Last note: note that Euler angles suffer from gimbal lock (in other words, "jumping" values).

+2
source

While you are using an accelerometer and magnetometer, but not gyroscopes, your method does not work when the device goes through fast acceleration / deceleration. You can try to be too smart and make some kind of hacked hack that may seem to rule out this particular failure mode that you found, but I would not even try it.

The true solution is to use gyroscopes. In my experience, this works very well.

What happened to TYPE_ROTATION_VECTOR ?

0
source

Source: https://habr.com/ru/post/1500254/


All Articles