Преобразование трехосевого магнитометра в Градусы

magnetometer

Я не знаю, является ли здесь лучшим местом для публикации этого вопроса. У меня есть датчик 9-DOF (MPU 9150), и я хочу использовать его магнитометр для определения угла поворота от 0 до 359. Однако его библиотека возвращает три значения: x, y и z.

Я не знаю, как преобразовать это в одно значение. Есть ли какой-нибудь способ сделать это?

, 👍11

Обсуждение

Он дает вам вектор, который проходит вдоль локального магнитного поля - в идеале он указывает на магнитный север. Отображение вращения между измерением и магнитным севером должно дать вам ваш курс., @BrettAM

Чтение таблицы данных может быть очень поучительным. Вы пробовали это сделать?, @Majenko

@Majenko Да, но ничего действительно полезного., @Guilherme

Итак, возможно ли вычислить курс (с компенсацией наклона) только с помощью магнитометра (без гирометра или акселерометра)?, @Max


4 ответа


Лучший ответ:

19

Ответ, данный Дэйвом Икс, а именно

az=90-atan(y/x)*180/pi

находится на правильном пути. Однако он не может работать как есть по двум причинам:

  1. Формула плохо работает всякий раз,когда x = 0,

  2. Он дает один и тот же азимут для x = y = 1 и для x = y = -1. Другими словами, он не может провести различие между северо-востоком и юго-западом.

Формула может быть исправлена путем замены atan(y/x) функцией, которая возвращает:

  • atan(y/x), если x > 0
  • π/2, если x = 0 и y > 0
  • −π/2, если x = 0 и y < 0
  • atan(y/x) + π, если x < 0 и y ≥ 0
  • atan(y/x) − π, если x < 0 и y < 0

Это была бы, по существу, двух аргументная, “квадрантно-ориентированная” версия арктангенса, дающая результаты в (-π, π] вместо (−π/2, π/2).

К счастью, такая функция уже существует. Это очень стандартная функция библиотеки C и называется atan2(). Таким образом, правильная формула такова:

az = 90 - atan2(y, x) * 180 / M_PI;

Теперь, поскольку atan(y/x) = π/2 − atan(x/y), приведенную выше формулу можно упростить до

az = atan2(x, y) * 180 / M_PI;

Эта формула дает направление вектора (x, y), отсчитываемого по часовой стрелке от оси y. Вполне вероятно, что ОП хочет вместо этого узнать курс какого-то транспортного средства. Правильная формула зависит от того, как магнитометр установлен относительно автомобиля. Если предположить , что ось x магнитометра направлена вперед, а ось y -влево, то:

  • транспортное средство движется на север (магнитный курс 0°), когда горизонтальная составляющая магнитного поля находится вдоль +x
  • транспортное средство движется на восток (магнитный курс 90°), когда горизонтальная составляющая магнитного поля находится вдоль +y

Отсюда следует, что курс транспортного средства

heading = atan2(y, x) * 180 / M_PI;

Очевидно, что магнитное склонение должно быть добавлено, если вас интересует истинный (а не магнитный) курс.


Edit: Все это предполагает, что плоскость XY горизонтальна. Если это не так (из-за тангажа и крена автомобиля), обратитесь к ответу Tails86, чтобы узнать, как справиться с этим.

,

3

Это элементарная математическая задача.

az=90-atan(y/x)*180/pi

"atan()" является арктангенсом и преобразует из переменных координат угол в радианах, *180/pi преобразует из радианов в градусы, а 90 - преобразует из градусов математические углы (градусы CCW от оси x) в азимут (градусы CW от севера).

Калибровка датчика-более сложная проблема.

,

5

Сначала вам нужна калибровка (либо с помощью метода калибровки устройства, либо вращая его по полному кругу, чтобы определить полную напряженность поля).

Затем вы можете использовать показания X, Y и Z для вычисления местоположения "севера" относительно того, куда вы указываете (имея в виду, что "север" меняется на 30 градусов в зависимости от того, где вы находитесь на земле (так называемое склонение - см. http://www.magnetic-declination.com/), и что это также не горизонтально к земле (смутно называемое "наклоном" - см. https://physics.stackexchange.com/questions/283761/if-you-hold-a-compass-needle-vertical-does-it-point-down-or-up-differently-on-wh/283782 )

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

Плохая новость - нет простого способа сделать то, что вы хотите точно, и определенно не тот, который будет работать без тригонометрической математики на всех 3 чтениях (вы не можете просто использовать X и/или Y в одиночку).

Хорошая новость - вам, вероятно, на самом деле не нужно знать фактический "заголовок" - большинству приложений просто нужно некоторое локальное относительное направление по сравнению с тем, что вы уже знаете.

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

,

4

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

Во-первых, полезно знать, что означает вектор магнитного поля. Мне нравится этот источник, потому что он дает изображение, показывающее, куда указывают магнитные векторы при движении вверх и вниз по земле. Она указывает вниз в северном полушарии и вверх в южном. В остальном текст не имеет отношения к делу, поскольку он более или менее просто объясняет, как вы можете аппроксимировать положение laitudinal из этих данных - угол горизонтальной составляющей-это все, что нам нужно знать, чтобы получить заголовок.

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

Я проецировал вектор магнитного поля на вектор ускорения, а затем вычитал его из вектора магнитного поля, чтобы получить вектор горизонтальной компоненты. Тогда я мог бы получить вектор угла на плоскости X/Y точно так же, как описано другими.

// Облегченное определение 3D-вектора, поэтому я не завишу от внешних библиотек
class Vector3D
{
public:
    Vector3D() : mArr{} {}

    Vector3D(double x, double y, double z)
    {
        mArr[0] = x;
        mArr[1] = y;
        mArr[2] = z;
    }

    double dot(const Vector3D& rhs) const
    {
        double out = 0;
        for (int i = 0; i < NUM_DIMENSIONS; ++i)
        {
            out = out + mArr[i] * rhs.mArr[i];
        }
        return out;
    }

    Vector3D operator* (double x) const
    {
        Vector3D out;
        for (int i = 0; i < NUM_DIMENSIONS; ++i)
        {
            out.mArr[i] = mArr[i] * x;
        }
        return out;
    }

    Vector3D operator- (const Vector3D& x) const
    {
        Vector3D out;
        for (int i = 0; i < NUM_DIMENSIONS; ++i)
        {
            out.mArr[i] = mArr[i] - x.mArr[i];
        }
        return out;
    }
    
    double getX() const {return mArr[0];}
    double getY() const {return mArr[1];}
    double getZ() const {return mArr[2];}

private:
    static const int NUM_DIMENSIONS = 3;
    double mArr[NUM_DIMENSIONS];
};

Vector3D operator* (double x, const Vector3D& y)
{
    return (y * x);
}

// mag: магнитный вектор
// accel: вектор ускорения (под действием силы тяжести)
double computeYaw(double mag_x, double mag_y, double mag_z, double accel_x, double accel_y, double accel_z)
{
    const Vector3D vector_mag(mag_x, mag_y, mag_z);
    const Vector3D vector_down(accel_x, accel_y, accel_z);
    const Vector3D vector_north = vector_mag - ((vector_mag.dot(vector_down) / vector_down.dot(vector_down)) * vector_down);
    return atan2(vector_north.getX(), vector_north.getY()) * 180 / M_PI;
}

EDIT: я изменил код, чтобы здесь были определены необходимые элементы вектора, чтобы не было путаницы.

,

tf2/LinearMath/Vector3.h: Такого файла или каталога нет. Есть ссылка на библиотеку?, @VE7JRO

Очень хорошая мысль! Обратите внимание, что: 1. Если платформа движется, мы можем получить лучшую оценку вертикали, объединив данные акселерометра с данными гироскопа. 2. Для повышения точности atan2() следует подавать компонентами намагниченности в горизонтальной плоскости, а не в плоскости XY платформы., @Edgar Bonet

Эдгар - Это действительно большая проблема с этой реализацией. Любые небольшие движения исказят результат. Я обнаружил, что усреднения результата по 20 образцам было достаточно, чтобы сгладить его для моих собственных нужд, поскольку я имею дело с медленно движущимся устройством., @Tails86

Есть ли какая-нибудь библиотека с открытым исходным кодом, которая реализует всю математику статьи, связанной во втором редактировании?, @Guilherme