【问题标题】:How can I get the magnetic field vector, independent of the device rotation?如何获得与设备旋转无关的磁场矢量?
【发布时间】:2012-08-02 07:32:27
【问题描述】:

我想要归档的是一种位置的“磁性指纹”。我使用 MAGNETIC_FIELD 传感器,如果我得到了 X、Y 和 Z 轴的3 values(不幸的是没有进一步解释)。

问题是,当我旋转设备时,值会发生变化,所以我猜 3 轴是相对于设备的。我需要的是补偿设备旋转,以便我得到相同的 3 个值,无论设备如何旋转。

我尝试与旋转矩阵相乘(我知道如何获得),尝试与倾斜矩阵相乘等等,但没有任何效果。无论我尝试什么,当我旋转设备时,值仍然会发生变化。

那么有谁知道怎么做对吗?最好使用代码,因为我读了很多诸如“那么你将不得不使用旋转矩阵来补偿”之类的东西,但没有找到一个具体的工作示例。

【问题讨论】:

标签: android android-sensors


【解决方案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]);

        }
    }

【讨论】:

  • 这看起来很有希望。我已经或多或少地放弃了这个项目,但当我找到时间时,我一定会测试你的解决方案。同时我给你+1。
【解决方案2】:

解决方案:

可能性一:

MAGNETIC_FIELD 在旋转方面非常不稳定,您无法仅通过一些数学运算来转换横向和纵向值,主要原因是硬件对不同的轴使用不同的捕捉器,然后当旋转发生时,您使用不同的硬件捕捉器,该值将永远不会相同,在某些高端设备上是相同的,但在大多数设备上不同。

如果您想在许多设备上依赖和兼容某些东西,您需要忘记使用旋转计算 MAGNETIC_FIELD,而只需使用您的应用程序强制定向。 Force "portrait" orientation mode

可能性2:

您谈到了"magnetic fingerprint" of a location.,如果它只是关于在没有 GPS 的情况下识别位置,那么您还有很多其他信息可以使用。首先是“Wifi SSID”,然后是“Mobile Networks Cells”,还有“Connected Wifi”等。如果你有兴趣,我可以给你代码。

可能性 3:

如果您绝对需要为您的位置计算 MAGNETIC_FIELD,并且不想强制旋转...您可以同时捕获横向和纵向值,而不是计算它们。那么当你比较时,只需比较两个值。

此外,如果您正在寻找有磁铁或高磁性位置的地方,您可以使用高容差百分比来检测是否存在磁铁,

注意:

如果您坚持数学,请不要忘记几乎每台设备上的功能都会有所不同... 不要犹豫,提供有关您的问题的更多信息,我很乐意调整我的答案;)

【讨论】:

    【解决方案3】:

    要获得磁场强度,您必须获得磁场的 x、y、z 值(来自 Sensor.TYPE_MAGNETIC_FIELD),并应用以下公式:

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

    磁场强度以微特斯拉 (µT) 表示
    可以注意到,根据this website,地球的平均磁场强度为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;
            }                
        }
    }
    

    【讨论】:

    • 是的,这给了我力量,但没有方向。我所寻找的是强度和方向,但与设备的当前方向无关。但我还是放弃了。
    【解决方案4】:

    磁场矢量的坐标是相对于手机给出的,如下图:

    得到下图坐标系下的磁场矢量:

    您必须将磁矢量m 与从getRotationMatrix() 检索到的旋转矩阵R 相乘,例如R * m。这个矢量将穿过地球指向磁北极。

    如果你也乘以倾角I,向量将围绕X轴旋转以完全在Y轴上:

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

    对于地球上的每个位置,这个向量应该是恒定的。但是,您的手机上的结果可能会略有偏差,因为您必须非常小心,不要在旋转设备时改变传感器的位置。

    【讨论】:

    • 对不起,没有。此示例展示了如何获取设备的方向 - 但这不是我需要的。
    • 是的,我找到了这条 I * R * 地磁线并尝试了它,但值不是恒定的。当然,由于传感器的位置变化,当我旋转设备时它们可能会有所不同,但在我的情况下,它们的变化幅度为 20 或更多,这是不正确的。另外,如果我理解正确,I * R * 地磁的结果将是一个 x 和 z 始终为 0 的向量?
    • 是的,这可能不是您想要的。你可能只想要 Rm。您在 y 轴上从 IR*m 获得的值实际上是磁场强度,它是您从传感器读取的矢量的绝对值(“长度”)。你得到这么大的偏差很奇怪。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多