11

我正在尝试构建一个简单的增强现实应用程序,所以我开始使用传感器数据。

根据此线程(Android compass example)和示例(http://www.codingforandroid.com/2011/01/using-orientation-sensors-simple.html),使用Sensor.TYPE_ACCELEROMETERSensor 计算方向。 TYPE_MAGNETIC_FIELD不太适合。

所以我无法获得“好”的价值。方位角值根本没有任何意义,所以如果我只是将电话向上移动,值会发生极大的变化。即使我只是旋转手机,这些值也不代表手机的方向。

有没有人知道根据给定的例子谁来提高价值质量?

4

5 回答 5

24

您以何种方式使用此示例应用程序?从所写的是这段代码,唯一支持的方向是纵向或平放在桌子上,这取决于设备。“好”是什么意思?

旋转设备时该值不是“好”是正常的,设备坐标系应该是纵向工作,或者我不知道是平坦的(Y轴垂直沿着屏幕指向,Z轴指向外面屏幕来自屏幕中心,X 轴垂直于 Y 轴,沿屏幕向右)。有了这个,旋转设备不会旋转设备坐标系,你必须重新映射它。

但是,如果您希望设备的标题是纵向的,这里有一段对我有用的代码:

@Override
public void onSensorChanged(SensorEvent event)
{
    // It is good practice to check that we received the proper sensor event
    if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR)
    {
        // Convert the rotation-vector to a 4x4 matrix.
        SensorManager.getRotationMatrixFromVector(mRotationMatrix,
                event.values);
        SensorManager
                .remapCoordinateSystem(mRotationMatrix,
                        SensorManager.AXIS_X, SensorManager.AXIS_Z,
                        mRotationMatrix);
        SensorManager.getOrientation(mRotationMatrix, orientationVals);

        // Optionally convert the result from radians to degrees
        orientationVals[0] = (float) Math.toDegrees(orientationVals[0]);
        orientationVals[1] = (float) Math.toDegrees(orientationVals[1]);
        orientationVals[2] = (float) Math.toDegrees(orientationVals[2]);

        tv.setText(" Yaw: " + orientationVals[0] + "\n Pitch: "
                + orientationVals[1] + "\n Roll (not used): "
                + orientationVals[2]);

    }
}

您将在以下位置获得航向(或方位角):

orientationVals[0]
于 2013-02-11T15:49:36.913 回答
15

Tíbó 的回答很好,但如果你记录滚动值,你会看到不规则的数字。(滚动对 AR 浏览器很重要)

这是因为

SensorManager.remapCoordinateSystem(mRotationMatrix,
                    SensorManager.AXIS_X, SensorManager.AXIS_Z,
                    mRotationMatrix);

您必须使用不同的矩阵进出重映射。以下代码适用于我的正确滚动值:

@Override
public void onSensorChanged(SensorEvent event)
{
    // It is good practice to check that we received the proper sensor event
    if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR)
    {
        // Convert the rotation-vector to a 4x4 matrix.
        SensorManager.getRotationMatrixFromVector(mRotationMatrixFromVector, event.values);
        SensorManager.remapCoordinateSystem(mRotationMatrixFromVector,
                    SensorManager.AXIS_X, SensorManager.AXIS_Z,
                    mRotationMatrix);
        SensorManager.getOrientation(mRotationMatrix, orientationVals);

        // Optionally convert the result from radians to degrees
        orientationVals[0] = (float) Math.toDegrees(orientationVals[0]);
        orientationVals[1] = (float) Math.toDegrees(orientationVals[1]);
        orientationVals[2] = (float) Math.toDegrees(orientationVals[2]);

        tv.setText(" Yaw: " + orientationVals[0] + "\n Pitch: "
                + orientationVals[1] + "\n Roll (not used): "
                + orientationVals[2]);

    }
}
于 2014-02-28T10:53:12.980 回答
8

可能迟到了。无论如何,这就是我如何获得方位角

private final int sensorType =  Sensor.TYPE_ROTATION_VECTOR;
float[] rotMat = new float[9];
float[] vals = new float[3];

@Override
public void onSensorChanged(SensorEvent event) {
    sensorHasChanged = false;
    if (event.sensor.getType() == sensorType){
        SensorManager.getRotationMatrixFromVector(rotMat,
                event.values);
        SensorManager
                .remapCoordinateSystem(rotMat,
                        SensorManager.AXIS_X, SensorManager.AXIS_Y,
                        rotMat);
        SensorManager.getOrientation(rotMat, vals);
        azimuth = deg(vals[0]); // in degrees [-180, +180]
        pitch = deg(vals[1]);
        roll = deg(vals[2]);
        sensorHasChanged = true;
    }
}

希望能帮助到你

于 2013-09-13T14:29:07.763 回答
0

您是否尝试过组合(传感器融合)类型 Sensor.TYPE_ROTATION_VECTOR。这可能会产生更好的结果:转到https://developer.android.com/reference/android/hardware/SensorEvent.html并搜索“rotation_vector”。

于 2013-02-06T23:47:55.580 回答
0

这是一种包含所有必要矩阵的 Kotlin 方法(由于某种原因,前面的答案忽略了数组大小,这很重要)

// This is determined from the deprecated Sensor.TYPE_ORIENTATION
var lastOrientation: FloatArray = FloatArray(3)
var lastHeading: Float = 0f
var currentHeading: Float = 0f

// This is from the non deprecated Sensor.TYPE_ROTATION_VECTOR
var lastVectorOrientation: FloatArray = FloatArray(5)
var lastVectorHeading: Float = 0f
var currentVectorHeading: Float = 0f

override fun onSensorChanged(event: SensorEvent) {
    when(event.sensor?.type) {
        null -> return
        Sensor.TYPE_ORIENTATION -> {
            lastOrientation = event.values
            lastHeading = currentHeading
            currentHeading = abs(event.values[0].roundToInt().toFloat())
        }
        Sensor.TYPE_ROTATION_VECTOR -> {
            lastVectorOrientation = event.values
            lastVectorHeading = currentVectorHeading

            val tempRotationMatrix = FloatArray(9)
            val tempOrientationMatrix = FloatArray(3)
            getRotationMatrixFromVector(tempRotationMatrix, event.values)
            remapCoordinateSystem(tempRotationMatrix, AXIS_X, AXIS_Z, tempRotationMatrix)
            getOrientation(tempRotationMatrix, tempOrientationMatrix)
            currentVectorHeading = Math.toDegrees(tempOrientationMatrix[0].toDouble()).toFloat()
            
            if(currentVectorHeading < 0) {
                currentVectorHeading += 360f//heading = 360 - abs(neg heading), which is really 360 + (-heading)
            }
        }
        else -> return
    }
}

对于任何想要了解这两种方法之间差异的人,我还包含了已弃用的 Sensor.TYPE_ORIENTATION。使用不推荐使用的方法与使用更新的方法时存在若干程度的差异。

于 2021-11-15T01:18:25.913 回答