Как я должен рассчитать Азимут, шаг, ориентацию, когда мое устройство Android не плоское?
Я использую датчики гравитации и магнитного поля Android для вычисления ориентации через SensorManager.getRotationMatrix и SensorManager.getOrientation. Это дает мне Азимут, высоту и ориентацию. Результаты выглядят разумными, когда устройство лежит на столе.
однако я отключил переключатели между портретом и пейзажем в манифесте, так что getWindowManager().getDefaultDisplay().getRotation() всегда равен нулю. Когда я поверните устройство на 90 Градусы так, что он стоит вертикально, я сталкиваюсь с проблемами. Иногда цифры кажутся совершенно неправильными, и я понял, что это относится к блокировка вращения. Однако, другие приложения не имеют этой проблемы. Например, я сравнил свое приложение с двумя бесплатными приложениями для тестирования датчиков (Тестер Датчиков (Dicotomica) и контроль датчика (программное обеспечение R)). Мое приложение согласуется с этими приложениями, когда устройство плоское, но когда я поворачиваю устройство по вертикали позиция может быть существенной. Два приложения, похоже, согласны друг с другом, так как они обходят эту проблему?
2 ответов
Я думаю, что лучший способ определить ваши углы ориентации, когда устройство не плоское, - использовать более подходящую угловую систему координат, которую вы получаете от стандартных углов Эйлера SensorManager.getOrientation(...)
. Я предлагаю тот, который я описываю здесь на math.stackexchange.com. Я также поместил некоторый код, который реализует его в ответ тут. Помимо хорошего определения азимута, он также имеет определение угла тангажа, который является точно заданным углом by Math.acos(rotationMatrix[8])
это упоминается в другом ответе здесь.
Вы можете получить полную информацию из двух ссылок, которые я дал в первом абзаце. Однако, в общем, ваша матрица вращения R из SensorManager.getRotationMatrix(...) is
где (Ex, Ey, Ez), (Nx, Ny, Nz) и (Gx, Gy, Gz) - векторы, указывающие на Восток, Север и в направлении силы тяжести. Тогда азимутальный угол, который вы хотите, задается
когда устройство не плоское, вы должны позвонить remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);
перед вызовом getOrientation
.
на azimuth
возвращает getOrientation
получается ортогонально проектировать блок устройства Y axis
в мире East-North plane
а затем вычислить угол между результирующим вектором проекции и Северной осью.
теперь мы обычно думаем о направлении как направлении, куда указывает задняя камера. Это направление -Z
здесь Z
- это устройство оси указывая на экран. Когда устройство плоское, мы не думаем о направлении и принимаем то, что когда-либо дано. Но когда он не плоский, мы ожидаем, что это направление -Z
. Но!--2-- > вычислить направление Y axis
, таким образом, нам нужно поменять Y and Z axes
перед вызовом getOrientation
. Это именно то, что remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR)
делает, он держит X axis
в целости и карте Z to Y
.
теперь, как вы знаете, когда remap
или нет. Вы можете сделать это, проверив
float inclination = (float) Math.acos(rotationMatrix[8]);
if (result.inclination < TWENTY_FIVE_DEGREE_IN_RADIAN
|| result.inclination > ONE_FIFTY_FIVE_DEGREE_IN_RADIAN)
{
// device is flat just call getOrientation
}
else
{
// call remap
}
наклон выше-это угол между экраном устройства и плоскостью Восток-Север. Он показывает, насколько устройство наклоняется.