【问题标题】:android compass seems unreliableandroid compass 似乎不可靠
【发布时间】:2011-06-06 18:15:21
【问题描述】:

过去几天我一直在开发一个小型指南针应用程序,并且已经启动并运行了代码,但指南针读数似乎不准确。在校准了两部手机后,我的第一次测试发现我只是将手机靠在平坦的表面上看读数,然后将其水平翻转并将其放在同一个平坦的表面上(180* 转)并且值确实不改变 180* 它更接近 240*。

然后我用指南针测试了读数,有时读数似乎很接近,但在其他点上它超过了 50*。我什至试着把我的手机和指南针放在地板上,以使指南针远离任何磁场干扰,结果相同(注意我还保持指南针和手机分开,通过与书的边缘对齐来保持它们在同一个方向上) .

然后我将示例应用程序放在另一部手机上(首先是 nexus S,其次是摩托罗拉 droid 1)。两部手机之间的差异范围从在某些点相等,但在大多数点之间相差 50 到 15 度。

我查看了文档,还查看了许多不同的论坛帖子,但我没有看到任何人有相同的结果。我的代码中可能有一些小错误导致我的读数不正确,或者我没有看到一些记录在案的错误。

任何见解或建议将不胜感激!

这是我在 SensorEventListener 类中的传感器更改代码

public void onSensorChanged(SensorEvent event)
    {
        // If the sensor data is unreliable return
        if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)
        {
            Toast.makeText(main.this, "Sensor Status Unreliable",Toast.LENGTH_SHORT).show();
        }





        // Gets the value of the sensor that has been changed
        switch (event.sensor.getType())
        {
        case Sensor.TYPE_ACCELEROMETER:
            m_vfgravity = event.values.clone();
            break;
        case Sensor.TYPE_MAGNETIC_FIELD:
            m_vfgeomag = event.values.clone();
            break;
        }

        if (m_vfgravity != null && m_vfgeomag != null)
        {
            if(SensorManager.getRotationMatrix(m_vfinR, m_vfI, m_vfgravity, m_vfgeomag))
            {
                SensorManager.getOrientation(m_vfinR, m_vforientVals);

                m_fCompBearing = (float) Math.round((Math.toDegrees(m_vforientVals[0])) *2)/2;

                //convert to 0-360 from -180-180
                if(m_fCompBearing < 0.0)
                {
                    m_fCompBearing = 360 + m_fCompBearing;
                }


                mCompHead.setText("" + (int)m_fCompBearing);
            }

            calcOffset();   
            rotateCmp();
        }
    }

并在创建我的活动时输入代码

    mSMngr = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    mSListener = new cSensorListener();

    mSMngr.registerListener(mSListener,
            mSMngr.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
            SensorManager.SENSOR_DELAY_UI);
    mSMngr.registerListener(mSListener,
            mSMngr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
            SensorManager.SENSOR_DELAY_UI);

提前致谢!

编辑:还尝试了 droid X,结果最差...当手机滚动 45 度(围绕 z 轴旋转计算机坐标系)时,返回的指南针方向可以改变 180 度以上,事实上当以相同方向旋转时,航向值与其他手机的方向相反。这是唯一一款即使在设置中校准后仍能产生此结果的手机。他们也是我测试的指南针动态壁纸,没有相同的问题。所以我会假设我可以在软件中做一些事情来避免这种情况。

【问题讨论】:

  • 你确定问题是安卓而不是硬件吗?
  • 一个明显的差异来源是磁北与真北。 FWIW,如果您转一圈不动,我的基本 garmin gps 单元指向正前方。使用这些基本 gps 单位的唯一方法是将其指向行进方向并移动向前。这可能与您的问题无关,但是?
  • 首先感谢您的快速解答。好吧,传感器管理器总是应该返回磁北,gps 将返回真北,因为它使用基于真北的纬度/经度上的运动方向。至于这是一个硬件问题,这是有可能的,但是我看到应用程序会全面返回类似的结果,并且想知道他们将如何做到这一点。我也用 DroidX 进行了测试,结果在 Droid X 上大不相同,我的指南针图像甚至向相反的方向旋转?

标签: android compass-geolocation sensors android-sensors


【解决方案1】:

即使作者回答了他自己的问题,我也不得不在这里插话,以强调 Android 平台上任何类型的指南针功能几乎完全无用。

我得出的结论是,任何依赖 Android 指南针应用程序的人都是在自找麻烦,它们都不能可靠地工作,这不是开发人员的错。

Google 和制造商根本没有提供一种方法来从这些设备中获得可靠的准确性,甚至无法确定准确性是否可靠,这更糟糕,因为有时它们是可靠的,而很多时候它们不是,如果有人信任这些设备对于真正的定向运动,上帝帮助他们。

作者可能认为他获得更好结果的原因是他们在已弃用的方向传感器上使用了一个非常好的噪声过滤器(为什么他们不能在较新的方法上做到这一点超出了我的范围)并且在单一的有限测试中校准后的设备,这似乎可以工作,但是在使用许多设备的现场中,我发现在大多数情况下,可靠性总是存在问题。

首先,磁性和方向传感器产生的噪音非常可怕,是的,这可以通过适当的 DSP 技术来克服,并且使用 2.3 和启用陀螺仪的手机总体上会变得更好,但对于 Google 和制造商浪费这么多感到羞耻开发人员时间与硬件和软件输出的伪劣实现。

其次,我已经测试了至少 18 款配备适当 DSP 过滤的手机,虽然这可以消除噪音但对准确性没有帮助,即使是相同型号的手机也有不同的输出(尽管有些型号看起来比其他型号更好)

第三,您几乎无法确定传感器是否已校准,即使进行痉挛的 8 字形动作也可能会或可能不会校准手机,除非您有指南针,否则用户永远不会真正知道它是否正常工作验证,哪种失败不是重点吗?

注意:您可以将磁传感器相乘和相加,然后取该 sqrt(x*x+y*y+z*z) 的平方根,并确保它在 25 到 65 左右之间,这是一种可以用来检测异常场的指标,但它并不完全可靠,我猜总比没有好。

第四,很多手机完全不可靠,校准与否,不仅限于型号类型,而且可能是制造商的伪劣质检,我真的不知道为什么,但我可以说 3 HTC ARIA 的疯狂生产不同的结果(一个偏离 30 度,另一个 50 度,第三个几乎在同一位置)具有令人难以置信的联系等。

我测试了 18 部手机,如果您可以正确校准,许多手机都非常接近准确,但其中许多尝试了 2 到 10 次(我们在每次校准尝试后都使用高精度指南针进行了验证)并且不止几次他们会根本不校准。

注意:您必须考虑真正的北偏移量,如果您可以访问当前的 GPS 坐标、高度、一天中的时间等,您可以使用 android 中的 API 来执行此操作。问题不是偏角和如果您要与指南针进行比较,那无论如何都不是问题,因为它也会受到当地磁场的影响。

Fith,冷启动总是需要在我们测试的每部手机上执行校准步骤,其中包括 X、难以置信、Aria、Nexus 和 Thunderbolt。换句话说,当您第一次开始传感器侦听时,95% 的时间都需要校准步骤(即使是损坏的时钟一天两次正确),所以如果您坚持添加此功能,我只会告诉您的用户在每个侦听器事件的开始。

如果您让传感器保持运行(对电池不利),那么您可能需要也可能不需要重新校准,具体取决于它遇到的字段)上述方法适用于此。

最重要的是,它们在工作时看起来很酷,但您目前永远无法确定方位角的准确性,这使得它们对于任何实际工作都非常不可靠且无用。

就我个人而言,我会在移动时使用 GPS 方位,然后如果可能的话,使用旋转矢量方法,它可能并不完美,但它会比你在当前手机系列中所拥有的疯狂实现要好得多方位角。

对于冗长的回复感到抱歉,但我已经浪费了将近一个月的时间来尝试在专家 DSP 工程师的帮助下让它工作,我们已经写了很多关于 android 平台在这方面很有用的文章。

在我看来,应该在每个指南针应用程序中添加“有时有效,有时无效,除非您拥有真正的指南针,否则您永远无法确定”免责声明。

【讨论】:

  • 是的,我同意你的看法。我得出的结论是,您必须意识到,在我的大多数设备(仅使用 6 个测试)上,读数似乎会有大约 +-30 度的误差范围,它在 10 左右的范围内。至于为什么我说方向传感器是修复的,因为 droid X 根本不工作。当其他人以误差范围接近并且切换到方向使X工作与其他人相似时,读数并不接近正确。降噪效果很好,但在获得值后我已经在做自己的低通滤波器了。
  • @ocross 我发现如果传感器 cfg 文件被删除,偏移问题就会消失,重新校准问题就会消失。问题是需要root访问权限,而且只是暂时的。此外,卡住问题似乎与我测试的手机上的手动校准有关,lazy-8 手腕运动至少解决了这个问题。对于另一个我必须包括和偏移功能,可以“同步”到 gps 轴承(速度精度必须很好)或由用户手动。问题是漂移会随着时间的推移而发生
  • 这种帖子既是福也是祸:我打算依靠加速度计来确定航向(另一种不太可靠的方法),但想知道是否要关闭磁力计来确定航向从一开始,决心就不是一个更好的主意。由于我需要逐步准确地读取航向,加速度计不起作用,罗盘似乎也不起作用,那么还剩下什么? GPS足够可靠吗?即使有天际线干扰?
  • @ravemir 请记住,它正在变得更好。真正的问题是它不是通用的(有些手机很棒,有些很烂)才是真正的问题。如果您的移动速度超过几英里/小时,并且您有良好的信号,则 GPS 是可以的,但前提是您要考虑向前的方向(在向右移动的同时向左转当然是行不通的,除非您可以旋转矢量等)你需要像样的传感器和传感器融合来让这一切可靠地工作,它即将到来,但你不能指望它是他们的。
  • 方向确实是前进方向,但我不确定跑步是否构成“快于几英里/小时”。如果确实如此,我肯定浪费了很多时间在不值得的事情上 xD
【解决方案2】:

经过多次测试和调试。我得出的结论是,是的,因为你们中的一些人提到我的 droid 1 和 Nexus S 的差异纯粹是硬件差异和磁干扰。

但是 Droid X 是一个不同的问题,无论我尝试什么,我都无法通过 getRotationMatrix 和 getOrientation 的推荐方式获得正确的读数,即使添加了重新映射坐标功能也是如此。因此,经过一番修修补补但没有成功,我想我可以试一试方向传感器。

Google 说这种方式已被弃用,他们建议按照我开始时的方式进行操作,但是我尝试了所有类型的组合,但没有成功。所以我继续并忽略了他们的警告并使用了方向传感器......它工作了。为什么 ?我不知道,droid x 的操作系统比我的 droid 1 更新,所以它不应该与使用遗留代码有关。然而,为什么写到目标 1.6 的指南针应用程序可以工作,而我的应用程序执行“推荐方式”却不工作,这确实是有道理的。

如果有人有更好的方法,请告诉我,或者如果你知道一种使它与 getRotationMatrix 和 getOrientation 一起工作的方法,请告诉我。

否则,对于像我一样努力撞到这堵砖墙的其他人,这里的代码最终为我工作。

我的传感器改变了

        switch (event.sensor.getType())
        {
        case Sensor.TYPE_ORIENTATION:
            m_vforientVals = event.values.clone();
            break;
        }

        if(m_vforientVals != null)
        {
            m_fCompBearing = m_vforientVals[0];             


            mCompHead.setText("" + (int)m_fCompBearing);

            calcOffset();   
            rotateCmp();
        }

并初始化传感器监听器

    mSMngr.registerListener(mSListener,mSMngr.getDefaultSensor(Sensor.TYPE_ORIENTATION),
                            SensorManager.SENSOR_DELAY_NORMAL);

【讨论】:

    【解决方案3】:

    您的代码对我来说看起来不错,如果您的代码中有错误,我很确定这两种设备都会受到影响。我认为这是导致差异的设备中的硬件。 您是否通过以八字形移动手机来“校准”两个指南针?许多指南针应用程序都建议这样做,包括 symbian 设备附带的地图软件。这可以工作

    【讨论】:

    • 感谢您的回复,您在校准方面确实提出了一个很好的观点,这可以产生巨大的差异并使指南针不可靠。不幸的是,这是我忘记提及我在测试之前所做的一步(我现在编辑了它)。我会再试一次,这次也会校准更长的时间,看看我是否发现有更好的结果。
    猜你喜欢
    • 2016-08-12
    • 2014-09-04
    • 1970-01-01
    • 1970-01-01
    • 2015-03-16
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多