【问题标题】:Compass direction is different depending on phone orientation指南针方向因手机方向而异
【发布时间】:2011-12-24 16:59:17
【问题描述】:

我的增强现实应用需要相机视图的指南针方位,并且有很多从传感器管理器获取方向的示例。

但是,我发现结果值因手机方向而异 - 向右旋转的横向与向左旋转的横向相差约 10 度(ROTATION_0 和 ROTATION_180 之间的差异较小,但仍然不同)。这种差异足以破坏任何 AR 效果。

和校准有关吗? (我不相信我正确地做 8 的数字 - 我已经尝试了我在 youtube 上找到的各种方法)。

任何想法为什么会有所不同?我搞砸了旋转矩阵的东西吗?我可以选择将应用程序限制为单一方向,但我仍然担心指南针读数仍然不是很准确(即使过滤后它相当稳定)

public void onSensorChanged(SensorEvent event) {
        if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) {
            return;
        }

        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)  mGravity = event.values;
        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) mGeomagnetic = event.values;

        if (mGravity != null && mGeomagnetic != null) {

            float[] rotationMatrixA = mRotationMatrixA;
            if (SensorManager.getRotationMatrix(rotationMatrixA, null, mGravity, mGeomagnetic)) {

                float[] rotationMatrixB = mRotationMatrixB;

                Display display = getWindowManager().getDefaultDisplay(); 
                int deviceRot = display.getRotation();

                switch (deviceRot)
                {
                // portrait - normal
                case Surface.ROTATION_0: SensorManager.remapCoordinateSystem(rotationMatrixA,
                        SensorManager.AXIS_X, SensorManager.AXIS_Z,
                        rotationMatrixB);
                break;
                // rotated left (landscape - keys to bottom)
                case Surface.ROTATION_90: SensorManager.remapCoordinateSystem(rotationMatrixA,
                        SensorManager.AXIS_Z, SensorManager.AXIS_MINUS_X,
                        rotationMatrixB); 
                break;
                // upside down
                case Surface.ROTATION_180: SensorManager.remapCoordinateSystem(rotationMatrixA,
                        SensorManager.AXIS_X, SensorManager.AXIS_Z,
                        rotationMatrixB); 
                break;
                // rotated right
                case Surface.ROTATION_270: SensorManager.remapCoordinateSystem(rotationMatrixA,
                        SensorManager.AXIS_MINUS_Z, SensorManager.AXIS_X,
                        rotationMatrixB); 
                break;

                default:  break;
                }

                float[] dv = new float[3]; 
                SensorManager.getOrientation(rotationMatrixB, dv);
                // add to smoothing filter
                fd.AddLatest((double)dv[0]); 
            }
            mDraw.invalidate();     
        }
    }

【问题讨论】:

    标签: android orientation augmented-reality compass-geolocation android-sensors


    【解决方案1】:

    试试这个

    public void onSensorChanged(SensorEvent event) {
        if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) {
            return;
        }
    
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)  mGravity = event.values.clone ();
        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) mGeomagnetic =  event.values.clone ();
    
        if (mGravity != null && mGeomagnetic != null) {
    
            float[] rotationMatrixA = mRotationMatrixA;
            if (SensorManager.getRotationMatrix(rotationMatrixA, null, mGravity, mGeomagnetic)) {
    
                float[] rotationMatrixB = mRotationMatrixB;
                SensorManager.remapCoordinateSystem(rotationMatrixA,
                        SensorManager.AXIS_X, SensorManager.AXIS_Z,
                        rotationMatrixB);
                float[] dv = new float[3]; 
                SensorManager.getOrientation(rotationMatrixB, dv);
                // add to smoothing filter
                fd.AddLatest((double)dv[0]); 
            }
            mDraw.invalidate();     
        }
    }
    

    你不需要 switch 语句,stackoverflow 问题中关于 getRotationMatrix、remapCoordinateSystem 和 getOrientation 似乎有很多混淆。
    我可能会在不久的将来写一个详细的解释。

    【讨论】:

    • 男人!我已经搜索了两个多小时,并且有很多错误的答案。你的是第一个真正适合我的。谢谢你。
    • 我复制并编辑了这篇文章。我没有意识到 Mush 有 mGravity = event.values,它应该是 event.values.clone()。与 mGeomagnetic 相同
    • SensorManager.remapCoordinateSystem 是解决方案。谢谢。
    • @Mark Kranzler 的回答是错误的。该问题询问相机视图的方向,即设备-z轴的方向。 getOrientation 返回方位角作为 y 轴的方向。因此,您需要 remapCoordinateSystem。设备 z 轴指向相同的方向,与设备的方向无关。无论设备是纵向、横向还是介于两者之间的任何设备,z 轴都指向同一方向。因此无需考虑设备的方向。
    • 如果您的手机处于横向并且设备屏幕指向您,则此答案是正确的(横向方向的 AR 工作正常)。如果您的手机横放在桌子上,则无法使用。 Hoan Nyugen,我还阅读了您几乎所有关于指南针的帖子,并查看了“dsensor”代码,这真的很有教育意义。你能分享一下当设备平放或屏幕垂直于地面时如何实现纵向和横向?
    【解决方案2】:

    Hoan 的回答实际上是不正确的,因为它没有考虑显示旋转。 This 是正确答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-07
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      相关资源
      最近更新 更多