改变音高时方位角值会发生变化

时间:2014-04-01 18:31:29

标签: android orientation sensor

我需要设备的方位角和滚动值,以便我正在使用的增强现实应用。我使用加速度计和磁场从getRotationMatrix获得旋转矩阵。由于这是一个AR应用程序,我需要渲染的对象在移动设备时不会改变他们在现实世界中的位置(当通过相机看到时)。

问题是,当物理滚动设备时(试图观察音高值的变化),我可以观察到方位角方向值的变化,即使它应该保持稳定。此外,方位角仅在俯仰变化时偏离,并在滚动停止时返回其原始值。 因此,为了澄清,当我开始滚动时,方位角也开始变化,当滚动停止时,方位角慢慢返回到正确的值。我无法弄清楚为什么方位角表现如此。

这是获取传感器数据并计算旋转矩阵的代码。

@Override
public void onSensorChanged(SensorEvent sensorEvent) {
    switch (sensorEvent.sensor.getType()) {
    case Sensor.TYPE_ACCELEROMETER:
        accel = lowPass(sensorEvent.values.clone(), accel);
        break;

    case Sensor.TYPE_MAGNETIC_FIELD:
        magnet = lowPass(sensorEvent.values.clone(), magnet);
        break;
    }

    if (accel == null || magnet == null)
        return;

    if (!SensorManager.getRotationMatrix(rotationMatrix, null, accel, magnet))
        return;
    SensorManager.remapCoordinateSystem(rotationMatrix, SensorManager.AXIS_Z,
            SensorManager.AXIS_MINUS_X, outRotationMatrix); // Remapping because the device is held in landscape.
    SensorManager.getOrientation(outRotationMatrix, orientationValues);

    currentOrientation = (float) (Math.toDegrees(orientationValues[0]) + this.getDeclination()); //Azimuth; (Degrees);
    eyeLevelInclination = (float) Math.toDegrees(orientationValues[1]); //Pitch; (Degrees); down is 90 , up is -90.
    deviceOrientation = (float) Math.toDegrees(orientationValues[2]);

    sendSensorBroadcast(); 
}

因此,在上面的代码中,currentOrientation(负责水平稳定渲染的AR对象)在设备滚动期间发生变化,此时只有eyeLevelInclination应该更改(负责垂直稳定渲染的AR对象)。
我还使用低通滤波器来稳定传感器数据。虽然我不相信这是方位角变化的原因,但无论如何我都会把它的代码放在这里 -

static final float ALPHA = 0.15f;

/**
 * @see Adapted from http://blog.thomnichols.org/2011/08/smoothing-sensor-data-with-a-low-pass-filter
 */
protected float[] lowPass( float[] input, float[] output ) {
    if ( output == null ) return input;

    for ( int i=0; i<input.length; i++ ) {
        output[i] = output[i] + ALPHA * (input[i] - output[i]);
    }
    return output;
}

如果问题不是很清楚,请道歉。要解释这个问题有点难。

编辑:我尝试过使用原始值,而不是通过低通滤波器,方位角仍会改变。我注意到,当改变音高时,渲染的物体沿着对角线走,当它应该垂直向上或向下时。当我物理地改变设备的音高时,它会随着方位角和音高的变化而对角移动,导致对角线移动。也许我的轴出了问题?

2 个答案:

答案 0 :(得分:2)

设备的方向(纵向或横向及其变体)无关紧要,如果您对后置摄像头方向感兴趣,则必须致电

SensorManager.remapCoordinateSystem(rotationMatrix, SensorManager.AXIS_X,
        SensorManager.AXIS_Z, outRotationMatrix);

以上呼叫与getOrientation一起给出了后置摄像头相对于磁北的方向,与设备的方向无关(纵向,横向或其间的任何东西)。

答案 1 :(得分:2)

看到我怎么找不到这个问题的解决方案,我开始研究处理传感器的其他可能方法。 我发现了一种更好的处理传感器数据的方法,它不仅消除了方位角的摇摆,而且还需要一个滤波器来平滑传感器值:
我没有使用Sensor.TYPE_ACCELEROMETERSensor.TYPE_MAGNETIC_FIELD值来计算旋转矩阵,而是使用了Sensor.TYPE_ROTATION_VECTOR传感器。然后,从中获取旋转矩阵,并且如前所述,从中获取方向数组。

@Override
public void onSensorChanged(SensorEvent sensorEvent) {
    switch (sensorEvent.sensor.getType()) {

    case Sensor.TYPE_ROTATION_VECTOR:
        rotationMatrix=new float[16];
        SensorManager.getRotationMatrixFromVector(rotationMatrix, sensorEvent.values);
    }

    SensorManager.remapCoordinateSystem(rotationMatrix, SensorManager.AXIS_X,
            SensorManager.AXIS_Z, outRotationMatrix);   // Remap coordinate System to compensate for the landscape position of device
    SensorManager.getOrientation(outRotationMatrix, orientationValues);

    currentOrientation = (float) (Math.toDegrees(orientationValues[0]) + this.getDeclination()); //Azimuth; (Degrees);
    eyeLevelInclination = (float) Math.toDegrees(orientationValues[1]); //Pitch; (Degrees); down is 90 , up is -90.
    deviceOrientation = (float) Math.toDegrees(orientationValues[2]); // Roll;

    sendSensorBroadcast();  // Let other classes know of update to sensor data.

正如您在上面的问题中所看到的,我使用低通滤波器来平滑方位角和音高值,但这不再需要了,因为这些值非常平滑而没有任何滤波。此外,方位角摇摆现在几乎消失了。我说几乎是因为你可能仍然可以看到它发生了一些,但它几乎没有引人注意,也许大约半度。

我在这个问题上遇到了很长一段时间,希望这对其他人也有帮助。