Я в настоящее время программирую приложение камеры Android (на моем Samsung S9, работающем на Android 9), и я замечаю проблему с выходным значением азимута, когда устройство наклонено (не плоское). Разница в градусах относительно того, когда устройство начинает с плоской поверхности и поднимается, например, до угла около 90 градусов, может варьироваться от 10 до 20 градусов.
Я просматривал различные потоки StackOverflow, но, похоже, ни один из них не имел решение, которое включает в себя устройство, потенциально использующее все возможные вращения в сочетании с датчиком ROTATION_VECTOR. Причина, по которой я остановился на ROTATION_VECTOR, заключается главным образом в том, что из одного из прочитанных мной тем пользователи упоминали об этом, принимая во внимание потенциальные изменения высоты тона / наклона при расчете азимута, но это явно не относится к моей проблеме.
Я также понимаю, что этот датчик требует, чтобы на устройствах был доступен датчик гироскопа, но для моих целей это всегда будет иметь место.
Выводимое значение азимута представляется правильным, когда устройство параллельно к земле (лежал ровно на полу), но как только он наклонился, но остался в том же направлении, азимут начинает постепенно увеличиваться / уменьшаться. Это одинаково для любого случая поворота, независимо от того, находится ли телефон в портретном или ландшафтном режиме.
Метод ниже вызывается внутри события onSensorChanged:
private float[] calculateOrientation(float[] values) {
float[] rotationMatrix = new float[9];
float[] remappedMatrix = new float[9];
float[] orientation = new float[3];
// Determine the rotation matrix
SensorManager.getRotationMatrixFromVector(rotationMatrix, values);
// Remap the coordinates based on the natural device orientation.
int x_axis = SensorManager.AXIS_X;
int y_axis = SensorManager.AXIS_Y;
switch (screenRotation) {
case (Surface.ROTATION_90):
x_axis = SensorManager.AXIS_Y;
y_axis = SensorManager.AXIS_MINUS_X;
break;
case (Surface.ROTATION_180):
y_axis = SensorManager.AXIS_MINUS_Y;
break;
case (Surface.ROTATION_270):
x_axis = SensorManager.AXIS_MINUS_Y;
y_axis = SensorManager.AXIS_X;
break;
default: break;
}
SensorManager.remapCoordinateSystem(rotationMatrix, x_axis, y_axis, remappedMatrix);
// Obtain the current, corrected orientation.
SensorManager.getOrientation(remappedMatrix, orientation);
angleLowPassFilter.add(orientation[0]);
// Convert from Radians to Degrees.
values[0] = (float) Math.toDegrees(orientation[0]);
values[1] = (float) Math.toDegrees(orientation[1]);
values[2] = (float) Math.toDegrees(orientation[2]);
int correctedAzimuth = (int) ((values[0] + 360) % 360);
TextView textView = findViewById(R.id.textView);
textView.setText(String.format(Locale.US, "Azimuth: [%s]", correctedAzimuth));
return values;
}