Pull to refresh

Использование Cardboard SDK для определения ориентации устройства

Получения текущих углов наклона устройстве с помощью сенсоров — интересная задача. Но проблема заключается не в том, как получить значения, а как их отфильтровать. Дело все в том, что показания акселерометра очень неточные, гироскоп имеет проблему «дрифта», то есть его значения постоянно уменьшаются при неподвижном состоянии, а магнитный сенсор зависит от окружающего его магнитного поля.

image

Решением этой проблемы является совмещение показаний гироскопа и акселерометра и их фильтрация с помощью алгоритма Калмана, как это делают здесь.

В поисках найти код на Java для всего этого наткнулся на статью «Android sensor fusion tutorial». Их программа показала себя не лучшим образом при измерении с помощью акселерометра + магнитного сенсора + гироскопа: значения сильно колебались и зависели от магнитного поля (при поднесении магнита).

Лучшим вариантом стало решение от Google для Cardboard. Этот API дает показания высокой точности почти без колебаний и значения не зависят от магнитного поля, так как для измерений используются только гироскоп и акселерометр.

Здесь рассказано о том, как использовать лишь часть API для отслеживания поворота головы (проект пишу в Android Studio):

1. Скачать библиотеки cardboard.jar и libprotobuf-java-2.6-nano.jar отсюда или отсюда;

2. Поместить их в папку lib проекта;

3. Связать проект с этими библиотеками: File > Project Structure > Dependencies > (+) > Выбрать нужные файлы. Должно получиться вот так:

image

4. Класс HeadTransform скачиваем и кладем вместе со своими классами. (API не позволяет пользоваться некоторыми методами этого класса, поэтому мы положим его копию в свой пакет. HeadTransform отвечает только за некоторые математические преобразования, поэтому может использоваться отдельно);

5. В нужной Activity объявляем:

HeadTracker track;
float [] angles = new float[3];

6. В onCreate:

track = HeadTracker.createFromContext(this);

7. В onResume:

track.startTracking();

8. В onStop:

track.stopTracking();


9. Для получения текущих углов пишем:

HeadTransform trans = new HeadTransform();
track.getLastHeadView(trans.getHeadView(), 0);
trans.getEulerAngles(angles, 0);

10. Теперь в массиве angles будут углы:

• Pitch (X axis): [-pi/2, pi/2]
• Yaw (Y axis): [-pi, pi]
• Roll (Z axis): [-pi, pi]

Подробнее:https://developers.google.com/cardboard/android/latest/reference/com/google/vrtoolkit/cardboard/HeadTransform#getEulerAngles

11. Получать эти значения можно в каком-либо Thread с небольшой задержкой;

12. Значения углов очень точные, так как используются и акселерометр и гироскоп. Благодаря коррекции отклонений гироскопа, решена проблема «дрифта» показаний;

13. Для графических игр лучше использовать матрицу переноса как сказано здесь. Пример: https://github.com/googlesamples/cardboard-java;

14. Подробнее про Cardboard API:https://developers.google.com/cardboard/;

15. Почитать исходный код cardboard.jar можно здесь или здесь (декомпилированые старые версии 0.5.1);

16. Мой пример;

17. Готово!
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.