问题在于,当我旋转设备时,这些值会改变,所以我猜测这3个轴相对于设备。我需要补偿设备旋转,以便获得相同的3个值,无论设备如何旋转。
我尝试过用旋转矩阵(我知道如何获得它)相乘,尝试过用倾斜矩阵相乘等等,但什么都不起作用。无论我尝试什么,设备旋转时值仍然会改变。
那么有人知道如何正确地做吗?最好附带代码,因为我读到了很多类似“那么你就必须使用旋转矩阵来进行补偿”的东西,但没有找到一个具体的、可行的例子。
可能性1:
MAGNETIC_FIELD在旋转方面非常不稳定,你无法仅依靠一些数学来转换横屏和竖屏值,主要原因是硬件使用不同的传感器来处理不同的轴线,当发生旋转时,你会使用不同的硬件传感器,该值将永远不会相同,在某些高端设备上它可能相同,但大多数设备上不同。
如果你想要可靠并且兼容许多设备的东西,你需要忘记使用旋转计算MAGNETIC_FIELD,而只需强制使用应用程序的方向。强制“纵向”方向模式
可能性2:
你谈到了一个地点的“磁指纹”。如果只是为了识别没有GPS的位置,你有很多其他信息可以使用。首先是“Wifi SSID”,然后是“移动网络单元”和“连接的Wifi”等等。如果你对此感兴趣,我可以给你代码。
可能性3:
如果你绝对需要计算MAGNETIC_FIELD以获取你的位置,并且不想强制旋转...你可以捕捉横屏和竖屏两个值而不是计算它们。然后当你进行比较时,只需将两个值进行比较。
此外,如果你正在寻找磁铁或高磁性位置,请使用高容差百分比来检测是否存在磁铁等。
注意:
如果你坚持使用数学计算,请不要忘记几乎每个设备上的函数都会有所不同...不要犹豫,提供更多关于你问题的信息,我将很乐意适应我的答案;)
请执行这个操作
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]);
}
}
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;
}
}
}
磁场向量的坐标是相对于移动电话给出的,就像这张图片中所示:
您需要将磁向量m
与从getRotationMatrix()获取的旋转矩阵R
相乘,如R * m
。这个向量将指向地球到磁北极的方向。
如果您还将其乘以倾角I
,则该向量将绕X轴旋转,完全位于Y轴上:
[0 m 0] = I * R * geomagnetic (m = 地磁场的大小)
对于地球上的每个位置,此向量应保持不变。但是,在旋转设备时,必须非常小心,以免改变传感器的位置,因此您的手机上的结果可能会显示轻微偏差。