Подтвердить что ты не робот

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

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

Проблема в том, что значения меняются при вращении устройства, поэтому я думаю, что ось 3 относится к устройству. Мне нужно компенсировать вращение устройства, чтобы получить те же 3 значения, независимо от того, как устройство повернуто.

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

Так кто-нибудь знает, как это сделать правильно? Предпочтительно с кодом, потому что я читал много вещей, вроде "ну, тогда вам придется компенсировать это с помощью матрицы вращения", но не нашел ни одного конкретного рабочего примера.

4b9b3361

Ответ 1

Сделайте это

private static final int TEST_GRAV = Sensor.TYPE_ACCELEROMETER;
private static final int TEST_MAG = Sensor.TYPE_MAGNETIC_FIELD;
private final float alpha = (float) 0.8;
private float gravity[] = new float[3];
private float magnetic[] = new float[3];

public void onSensorChanged(SensorEvent event) {
    Sensor sensor = event.sensor;
    if (sensor.getType() == TEST_GRAV) {
            // Isolate the force of gravity with the low-pass filter.
              gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
              gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
              gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];
    } else if (sensor.getType() == TEST_MAG) {

            magnetic[0] = event.values[0];
            magnetic[1] = event.values[1];
            magnetic[2] = event.values[2];

            float[] R = new float[9];
            float[] I = new float[9];
            SensorManager.getRotationMatrix(R, I, gravity, magnetic);
            float [] A_D = event.values.clone();
            float [] A_W = new float[3];
            A_W[0] = R[0] * A_D[0] + R[1] * A_D[1] + R[2] * A_D[2];
            A_W[1] = R[3] * A_D[0] + R[4] * A_D[1] + R[5] * A_D[2];
            A_W[2] = R[6] * A_D[0] + R[7] * A_D[1] + R[8] * A_D[2];

            Log.d("Field","\nX :"+A_W[0]+"\nY :"+A_W[1]+"\nZ :"+A_W[2]);

        }
    }

Ответ 2

Решение:

Возможность 1:

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

если вы хотите, чтобы что-то полагалось и совместимо на многих устройствах, вам нужно забыть вычислить MAGNETIC_FIELD с вращением, но просто принудительно ориентируйте свое приложение. Сила "портрет" режим ориентации

Возможность 2:

Вы говорили о "magnetic fingerprint" of a location., если только об определении местоположения без GPS у вас есть много другой информации для работы. сначала "Wi-Fi SSID", затем "Ячейки мобильных сетей", также "Connected Wifi" и т.д., если это интересно, я могу дать вам код для этого.

Возможность 3:

Если вам абсолютно необходимо вычислить MAGNETIC_FIELD для вашего местоположения и не хотите форсировать вращение... вы можете поймать как пейзаж, так и портрет вместо того, чтобы вычислять их. затем, когда вы сравниваете только сравнение с обоими значениями.

Кроме того, если вы хотите найти место, где у вас магнит или магнитное местоположение, вы можете работать с процентным доходом hi, чтобы определить, присутствует ли магнит или нет,

Примечание:

Если вы придерживаетесь математики, не забывайте, что функция будет отличаться почти на каждом устройстве... не стесняйтесь давать больше информации о своем вопросе, я с удовольствием адаптирую свой ответ;)

Ответ 3

чтобы получить силу магнитного поля, вы должны получить значения x, y, z магнитного поля (от Sensor.TYPE_MAGNETIC_FIELD) и применить следующую формулу:

double magnetic_field_strength = Math.sqrt( (Xvalue*Xvalue) + (Yvalue*Yvalue) + (Zvalue*Zvalue) );

magnet_field_strength выражается в microtesla (μT)
Можно отметить, что средняя напряженность магнитного поля Земли составляет 50 мкТ, согласно этот сайт.


Таким образом, возможный код:

private SensorEventListener sensorEventListener = new SensorEventListener() {   
    @Override
    public void onSensorChanged(SensorEvent event) {

        switch (event.sensor.getType()) {
        case Sensor.TYPE_MAGNETIC_FIELD:                        
            magnetic_field_strength = Math.sqrt((event.values[0]*event.values[0])+(event.values[1]*event.values[1])+(event.values[2]*event.values[2]));
            break;                      
        default: 
            return;
        }                
    }
}

Ответ 4

Координаты вектора магнитного поля задаются относительно мобильного телефона, как на этом рисунке:

enter image description here

Чтобы получить вектор магнитного поля в системе координат следующего изображения:

enter image description here

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

Если вы также умножите его с наклоном I, вектор будет повернут вокруг оси X полностью на оси Y:

[0 m 0] = я * R * геомагнитный (m = величина геомагнитного поля)

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