Получение значений магнитного поля в глобальных координатах

Для приложения Android мне нужно получить измерения магнитного поля по оси глобальной (мировой) системы координат. Вот как я собираюсь (догадываться) реализовать это. Пожалуйста, поправьте меня при необходимости. Также обратите внимание, что речь идет об алгоритмической части задачи, а не об Android API для датчиков - у меня есть опыт работы с последними.

Первый шаг - получить TYPE_MAGNETIC_FIELD данные датчика (M) а также TYPE_ACCELEROMETER данные датчика (G). Второй предполагается использовать в соответствии с документацией Android, но я не уверен, что это не должно быть TYPE_GRAVITY вместо (снова как G), потому что акселерометр, кажется, обеспечивает не чистую гравитацию.

Следующий шаг - получить матрицы вращения через getRotationMatrix(R, I, G, M), где R а также I являются матрицей вращения и наклона соответственно.

А теперь перейдем к самой сомнительной части: чтобы перевести M вектор в мировую систему координат, я полагаю, умножить [R * I] * M,

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

Если существует какой-либо исходный код, который уже выполняет эту задачу, я был бы признателен за публикацию ссылки, но я не хочу использовать большие библиотеки общего назначения (например, для поддержки дополненной реальности) для этой конкретной задачи, потому что я бы хотел бы сделать это как можно более простым.

PS

Я пришел к идее добавить некоторую информацию в исходный пост для ясности.

Предположим, что устройство лежит на столе и непрерывно считывает данные со своего магнитного датчика. Каждое измерение содержит 3 значения, представляющих магнитное поле по осям X, Y, Z, которые являются локальной системой координат устройства. Я полагаю, что я могу пренебречь флуктуациями поля окружающей среды (сглаживаются фильтром нижних частот), поэтому эти 3 значения должны оставаться почти одинаковыми все время, пока устройство остается на месте. Если мы вращаем устройство вокруг любой оси, значения меняются, потому что мы меняем локальную систему координат. Но само поле на самом деле не изменилось. Поэтому я хочу перевести измерения локального поля X, Y, Z в такие X', Y', Z', чтобы они сохраняли свои соответствующие значения независимо от поворота устройства, при условии, что устройство не перемещено из своего местоположения (только повернуто).

Я реализовал алгоритм, описанный выше, и получил регулярные и заметные изменения значений X', Y', Z', полученные с помощью предложенных преобразований, так что в этом что-то не так.

PPS

Время от времени я находил точную копию моего вопроса на SO - Как я могу получить вектор магнитного поля, независимо от вращения устройства? - но, к сожалению, ответ содержит мои предложения, и ОП этого вопроса подтверждает, что они не работают.

2 ответа

Решение

Координаты M относительно слова координата - это просто умножение R * M.

Матрица вращения R является математически изменением базисной матрицы от координаты устройства к координате слова. Пусть X, Y, Z будет базисом координат устройства, а W_1, W_2, W_3 будет базисом координат слова
M = m_1 X + m_2 Y + m_3
а также
M = c_1 W_1 + c_2 W_2 + c_3 W_3
где R * (m_1, m_2, m_3) = (c_1, c_2, c_3) транспонировать.

Фильтр низких частот используется только для фильтрации ускорений в направлениях X, Y. RemapCoordinateSystem используется для изменения порядка базиса, т.е. изменения с W_1, W_2, W_3 на W_1, W_3, W_2.

Датчик магнитометра на вашем устройстве возвращает 3-вектор в координатах устройства. Вы можете использовать getRotationMatrix(), чтобы получить матрицу, которую можно использовать для преобразования этого вектора координат устройства в мировые координаты. Вы также можете узнать о Quaternions и использовать TYPE_ROTATION_VECTOR напрямую. Однако в Android нет библиотеки Quaternion (о которой я знаю), и это обсуждение выходит за рамки этого вопроса.

Однако ничто из этого не принесет вам пользы, поскольку информация об ориентации устройства частично основана на значении магнитометров. Другими словами, устройство всегда скажет вам, что магнитный вектор направлен точно на север.

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

Наконец, ваш последний вариант - построить таблицу уровня, на которой есть стрелка, указывающая истинный север. (Вам придется выравнивать его по звездам ночью или около того.) Затем положите устройство на стол, чтобы верхняя часть устройства была направлена ​​на север. В этом случае координаты устройства будут такими же, как мировые координаты, и датчик магнитометра выдаст нужные вам значения.

Ваши комментарии показывают, что вы заинтересованы в местных вариациях. Просто нет способа получить истинный север с вашим Android-устройством. Теоретически, вы могли бы построить стол, как я описал, а затем обойти, удерживая устройство в строго той же ориентации, что и раньше, следя за столом для справки. Но я сомневаюсь, что ты справишься.

Вы можете попробовать использовать гироскопы в своем приложении, чтобы всегда поддерживать ориентацию устройства одинаково, но гироскопы на любом устройстве Android, которое вы используете, могут слишком сильно дрейфовать, чтобы это работало.

Или, возможно, мы до сих пор не понимаем, что вы пытаетесь сделать. Суть в том, что вы просто не можете получить глобальную систему координат только с устройством Android - все, что вы получите, всегда будет выровнено с локальным магнитным полем в этом точном месте.

Другие вопросы по тегам