Intereting Posts
Проблемы с отображением недостающих стилей после каждого обновления Как создать resizeable ImageView в Android Как изменить цвет пузырька (под курсором) на EditView (ПРОГРАММА)? Как реализовать пользовательский вид AlertDialog Как получить символ валюты по названию валюты? Как повторно запустить неудачный тест в Espresso? – мозговой штурм Android Alarm Manager с широковещательным приемником, зарегистрированным в коде, а не манифестацией Stream and Play .m4a stream (Itunes preview Url) в android Не удалось получить информацию о подписке из API разработчика Google Play для Android Попытка понять поля в LinearLayout внутри ScrollView Android намерен открыть предпочтительный браузер пользователя Сбой в ListView в AbsListView.obtainView для ListActivity Библиотека разрешает путь без файла project.properties Что отличается от @ + id / android: list и @ id / android: list? Автоматическое масштабирование на Google Картах в java? (В зависимости от разрешения экрана Android)

Как нарисовать вектор направления в Android

Как я могу получить вектор направления, указывающий направление, которое обратная сторона устройства указывает на координаты земли?

Например, если место на столе (экран вверх), оно должно читать [0,0, -1], и если оно удерживается вертикально на север, оно должно читать [1,0,0] и т. Д.

Я знаю, как вычислить его из заголовка, тона и рулона, если они относятся к земным координатам. Чтобы быть ясным здесь, я не ищу угловой скорости, но фактический угол тока относительно плоскости, касательной к земле. Поэтому, если устройство удерживается вертикально и обращено на север, угол «альфа» должен быть равен 0 или 360, угол «бета» должен быть равен 90, а «гамма» должна быть равна 0. Я не могу понять, как получить эти значения или.

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

public void onSensorChanged(SensorEvent event) { // ? } 

Спасибо за любые идеи.

Solutions Collecting From Web of "Как нарисовать вектор направления в Android"

SensorManager.getRotationMatrix() делает то, что описано ниже, написанное до того, как я это выяснил. Я оставлю дополнительное объяснение, потому что, если вы хотите исправить разницу между магнитным и истинным севером, вам все равно понадобится.

Грубый алгоритм состоит в том, чтобы получить матрицу вращения, умножить на нее вектор [0,0,-1] , а затем скорректировать это на вашу систему координат. Зачем? Android docs предоставляют системы координат для устройства и мира

устройствоМир

Обратите внимание, что [0,0,-1] в устройствах Android-устройств точки перпендикулярны назад от экрана. Если вы умножите матрицу вращения R на этот вектор, вы получите [0,0,-1] в мировых коордах, когда устройство окажется на столе вверх, как вам хочется. Когда он вертикально обращен на север, вы получите [0,-1,0] , что означает, что вы выбрали систему координат, где x и y меняются местами по отношению к системе Android, но это просто изменение условностей.

Примечание R * [0,0,-1]^T – это только третий столбец R отрицательный. Отсюда я получаю псевдокод:

 getRotationMatrix(R); Let v = first three elements of third column of R. swap v[0] and v[1] 

Это должно получить то, что вы хотите.

getRotationMatrix() следует дополнительная информация о том, что getRotationMatrix() .


Вам нужны данные аксерометра, чтобы определить направление «вниз» и данные магнитометра, чтобы определить направление «север». Вам придется предположить, что акселерометры воспринимают только гравитацию (устройство неподвижно или движется с постоянной скоростью). Затем вам нужно проецировать вектор магнитометра на плоскость, перпендикулярную гравитационному вектору (поскольку магнитное поле обычно не касается земной поверхности). Это дает вам две оси. Третий ортогонален, поэтому его можно вычислить с помощью перекрестного произведения. Это дает вам координаты координат земли в системе устройства. Похоже, вы хотите, чтобы координаты обратного: устройства в координатах земли. Для этого просто построим матрицу направляющих косинусов и инвертируем.

Я добавлю, что приведенное выше обсуждение предполагает, что вектор магнитометра указывает на север. Я думаю (из вузовской науки!) Это на самом деле к магнитному югу, но у него нет устройства, поэтому не можете его попробовать. Разумеется, магнитный север / юг отличается от истинного на ноль до 180 градусов в зависимости от того, где вы находитесь на земле. Вы можете получить GPS-координаты и вычислить фактическое смещение.

Если вы не знакомы с математикой, необходимой для этого, я могу объяснить дальше, но это должно быть позже.

Читайте эту страницу: http://developer.android.com/reference/android/hardware/Sensor.html

В API 8 и выше существуют «виртуальные» датчики, которые генерируются путем объединения входов всех доступных датчиков и соответствующих фильтров. Датчик «TYPE_ORIENTATION» дает вам всю ориентацию вашего устройства, но этот интерфейс устарел из-за состояний отказа при определенных ориентациях. Новый датчик – TYPE_ROTATION_VECTOR (API 9 и выше), который дает ориентацию вашего устройства как кватернион. Это действительно лучший датчик для использования, но математика за ним немного тяжелая.

В противном случае вы вызываете SensorManager.getRotationMatrix (), передавая последние данные о гравитации и магнитометре. Это вернет матрицу поворота, которая может быть использована для преобразования вектора из координат устройства в мировые координаты или наоборот (просто транспонируйте матрицу, чтобы инвертировать ее).

Функция getOrientation () может дать вам заголовок, шаг и рулон, но они имеют те же самые состояния отказа, что и датчик TYPE_ORIENTATION.

 Examples: Device flat on a table, top facing north: 1 0 0 0 1 0 0 0 1 Tilted up 30 degrees (rotated about X axis) 1 0 0 0 0.86 -0.5 0 0.5 0.86 Device vertical (rotated about X axis), facing north: 1 0 0 0 0 -1 0 1 0 Device flat on a table, top facing west: 0 -1 0 1 0 0 0 0 1 Device rotated about its Y axis, onto its left side, top facing north: 0 0 -1 0 1 0 1 0 0 

Вот пример кода, который может оказаться полезным:

 public void onSensorChanged(SensorEvent event) { long now = event.timestamp; // ns switch( event.sensor.getType() ) { case Sensor.TYPE_ACCELEROMETER: gData[0] = event.values[0]; gData[1] = event.values[1]; gData[2] = event.values[2]; break; case Sensor.TYPE_MAGNETIC_FIELD: mData[0] = event.values[0]; mData[1] = event.values[1]; mData[2] = event.values[2]; haveData = true; break; } if( haveData ) { double dt = (now - last_time) * .000000001; SensorManager.getRotationMatrix(R1, Imat, gData, mData); getOrientation(R1, orientation); pfdView.newOrientation(orientation[2], (float)dt); Log.d(TAG, "yaw: " + (int)(orientation[0]*DEG)); Log.d(TAG, "pitch: " + (int)(orientation[1]*DEG)); Log.d(TAG, "roll: " + (int)(orientation[2]*DEG)); acft.compass = orientation[0]; last_time = now; } }