如何获取磁场向量,与设备旋转无关?

10
我想要实现的是一种位置的“磁指纹”。我使用磁场传感器,在事件中获取3个值,分别对应(不幸的是没有进一步解释的)X、Y和Z轴。
问题在于,当我旋转设备时,这些值会改变,所以我猜测这3个轴相对于设备。我需要补偿设备旋转,以便获得相同的3个值,无论设备如何旋转。
我尝试过用旋转矩阵(我知道如何获得它)相乘,尝试过用倾斜矩阵相乘等等,但什么都不起作用。无论我尝试什么,设备旋转时值仍然会改变。
那么有人知道如何正确地做吗?最好附带代码,因为我读到了很多类似“那么你就必须使用旋转矩阵来进行补偿”的东西,但没有找到一个具体的、可行的例子。

那么,你找到解决方案了吗? - Wops
请查看我在 https://dev59.com/_uo6XIcBkEYKwwoYORoV#15317814 的回答。 - Hoan Nguyen
你有没有找到解决这个问题的办法? - Motheus
不好意思,不行 :-/ - Ridcully
4个回答

3

解决方案:

可能性1:

MAGNETIC_FIELD在旋转方面非常不稳定,你无法仅依靠一些数学来转换横屏和竖屏值,主要原因是硬件使用不同的传感器来处理不同的轴线,当发生旋转时,你会使用不同的硬件传感器,该值将永远不会相同,在某些高端设备上它可能相同,但大多数设备上不同。

如果你想要可靠并且兼容许多设备的东西,你需要忘记使用旋转计算MAGNETIC_FIELD,而只需强制使用应用程序的方向。强制“纵向”方向模式

可能性2:

你谈到了一个地点的“磁指纹”。如果只是为了识别没有GPS的位置,你有很多其他信息可以使用。首先是“Wifi SSID”,然后是“移动网络单元”和“连接的Wifi”等等。如果你对此感兴趣,我可以给你代码。

可能性3:

如果你绝对需要计算MAGNETIC_FIELD以获取你的位置,并且不想强制旋转...你可以捕捉横屏和竖屏两个值而不是计算它们。然后当你进行比较时,只需将两个值进行比较。

此外,如果你正在寻找磁铁或高磁性位置,请使用高容差百分比来检测是否存在磁铁等。

注意:

如果你坚持使用数学计算,请不要忘记几乎每个设备上的函数都会有所不同...不要犹豫,提供更多关于你问题的信息,我将很乐意适应我的答案;)


3

请执行这个操作

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]);

        }
    }

这看起来非常有前途。我已经或多或少地放弃了这个项目,但是当我有时间时,我一定会测试你的解决方案。在此期间,我给你加一分。 - Ridcully

-1
要获取磁场强度,您需要获取磁场(来自Sensor.TYPE_MAGNETIC_FIELD)的x、y、z值,并应用以下公式:
double magnetic_field_strength = Math.sqrt( (Xvalue*Xvalue) + (Yvalue*Yvalue) + (Zvalue*Zvalue) );

magnetic_field_strength以微特斯拉(µT)表示。
根据这个网站,地球的平均磁场强度为50 µT。


因此,可能的代码如下:

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;
        }                
    }
}

是的,那给了我力量,但没有方向。我正在寻找的是力量和方向,但与设备当前的方向无关。但无论如何,我放弃了它。 - Ridcully

-1

磁场向量的坐标是相对于移动电话给出的,就像这张图片中所示:

enter image description here

要在以下图片的坐标系中获得磁场向量:

enter image description here

您需要将磁向量m与从getRotationMatrix()获取的旋转矩阵R相乘,如R * m。这个向量将指向地球到磁北极的方向。

如果您还将其乘以倾角I,则该向量将绕X轴旋转,完全位于Y轴上:

[0 m 0] = I * R * geomagnetic (m = 地磁场的大小)

对于地球上的每个位置,此向量应保持不变。但是,在旋转设备时,必须非常小心,以免改变传感器的位置,因此您的手机上的结果可能会显示轻微偏差。


抱歉,这个例子展示了如何获取设备的方向-但这不是我所需要的。 - Ridcully
1
是的,我找到了这个I * R *地磁线并尝试了一下,但值不是恒定的。当我旋转设备时,由于传感器位置的变化,它们可能会略微变化,但在我的情况下,它们变化了20倍以上,这是不正确的。此外,如果我理解正确,I * R *地磁的结果将是一个x和z始终为0的向量? - Ridcully
是的,这可能不是你想要的。你可能只想要 Rm。从 IR*m 得到的 y 轴值实际上是磁场强度,它是你从传感器读取的向量的绝对值(“长度”)。你得到如此大的偏差很奇怪。 - Ben Ruijl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接