Android: проблемы расчета ориентации устройства

Я пытаюсь создать простое приложение дополненной реальности , поэтому я начинаю работать с данными датчиков.

Согласно этой теме ( пример компаса Android ) и примера ( http://www.codingforandroid.com/2011/01/using-orientation-sensors-simple.html ), расчет ориентации с помощью Sensor.TYPE_ACCELEROMETER и Sensor. TYPE_MAGNETIC_FIELD не подходит.

Поэтому я не могу получить «хорошие» ценности. Значения azimut не имеют никакого смысла, поэтому, если я просто переместим Phone upside, значение сильно изменится. Даже если я просто вращаю телефон, значения не соответствуют ориентации телефона.

Есть ли у кого-нибудь идея, кто для улучшения качества ценностей в соответствии с данным примером?

В какой ориентации вы используете это приложение-образец? Из того, что написано в этом коде, единственная поддерживаемая ориентация – портрет или квартира на столе, это зависит от устройств. Что вы подразумеваете под «хорошим»?

Нормально, что при вращении устройства значение не является «хорошим», предполагается, что система координат устройства работает в портрете или плоская, я не знаю (вертикальная ось Y по экрану вверх, ось Z, указывающая из Экран, идущий от центра экрана, ось X перпендикулярна оси Y, идущей справа вдоль экрана). При этом вращение устройства не приведет к вращению системы координат устройства, вам придется переназначить его.

Но если вы хотите, чтобы заголовок устройства находился в портретной ориентации, вот фрагмент кода, который хорошо работает для меня:

@Override public void onSensorChanged(SensorEvent event) { // It is good practice to check that we received the proper sensor event if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) { // Convert the rotation-vector to a 4x4 matrix. SensorManager.getRotationMatrixFromVector(mRotationMatrix, event.values); SensorManager .remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_X, SensorManager.AXIS_Z, mRotationMatrix); SensorManager.getOrientation(mRotationMatrix, orientationVals); // Optionally convert the result from radians to degrees orientationVals[0] = (float) Math.toDegrees(orientationVals[0]); orientationVals[1] = (float) Math.toDegrees(orientationVals[1]); orientationVals[2] = (float) Math.toDegrees(orientationVals[2]); tv.setText(" Yaw: " + orientationVals[0] + "\n Pitch: " + orientationVals[1] + "\n Roll (not used): " + orientationVals[2]); } } 

Вы получите заголовок (или азимут) в:

 orientationVals[0] 

Ответ от Tíbó хорош, но если вы регистрируете значение рулона, вы будете ожидать нерегулярные цифры. (Бросок важен для браузеров AR)

Это связано с

 SensorManager.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_X, SensorManager.AXIS_Z, mRotationMatrix); 

Вы должны использовать другую матрицу для внутри и снаружи переназначения. Этот следующий код работает для меня с правильным значением крена:

 @Override public void onSensorChanged(SensorEvent event) { // It is good practice to check that we received the proper sensor event if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) { // Convert the rotation-vector to a 4x4 matrix. SensorManager.getRotationMatrixFromVector(mRotationMatrixFromVector, event.values); SensorManager.remapCoordinateSystem(mRotationMatrixFromVector, SensorManager.AXIS_X, SensorManager.AXIS_Z, mRotationMatrix); SensorManager.getOrientation(mRotationMatrix, orientationVals); // Optionally convert the result from radians to degrees orientationVals[0] = (float) Math.toDegrees(orientationVals[0]); orientationVals[1] = (float) Math.toDegrees(orientationVals[1]); orientationVals[2] = (float) Math.toDegrees(orientationVals[2]); tv.setText(" Yaw: " + orientationVals[0] + "\n Pitch: " + orientationVals[1] + "\n Roll (not used): " + orientationVals[2]); } } 

Наверное, поздно на вечеринку. В любом случае, вот как я получил азимут

 private final int sensorType = Sensor.TYPE_ROTATION_VECTOR; float[] rotMat = new float[9]; float[] vals = new float[3]; @Override public void onSensorChanged(SensorEvent event) { sensorHasChanged = false; if (event.sensor.getType() == sensorType){ SensorManager.getRotationMatrixFromVector(rotMat, event.values); SensorManager .remapCoordinateSystem(rotMat, SensorManager.AXIS_X, SensorManager.AXIS_Y, rotMat); SensorManager.getOrientation(rotMat, vals); azimuth = deg(vals[0]); // in degrees [-180, +180] pitch = deg(vals[1]); roll = deg(vals[2]); sensorHasChanged = true; } } 

Надеюсь, поможет

Пробовали ли вы комбинированный (сенсорный) тип Sensor.TYPE_ROTATION_VECTOR. Это может дать лучшие результаты. Перейдите на страницу https://developer.android.com/reference/android/hardware/SensorEvent.html и найдите «rotation_vector».