Android 上的方位角/偏航角和滚转方向传感器值不一致 [英] Inconsistent orientation sensor values on Android for azimuth/yaw and roll

查看:34
本文介绍了Android 上的方位角/偏航角和滚转方向传感器值不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法获得良好的方向传感器读数.传感器读数似乎不可靠,因此我针对两个免费的传感器测试应用程序测试了我的代码(传感器测试仪 (Dicotomica)传感器监测 (R's软件)).我发现虽然我的读数通常与传感器测试应用程序一致,但有时方位角/偏航角和滚转的值差异高达 40 度,尽管俯仰读数大多一致.这两个免费应用似乎总是彼此一致.

I’m having trouble getting good orientation sensor readings. The sensor readings seemed unreliable, so I tested my code against two free sensor test apps (Sensor Tester (Dicotomica) and Sensor Monitoring (R's Software)). I found that while my readings often agreed with the sensor test apps, occasionally the values for azimuth/yaw, and roll differed by up to 40 degrees, although the pitch reading mostly agreed. The two free apps always seemed to agree with each other.

我将我的代码放入一个很小的 ​​Android Activity 中并得到了同样的不一致.代码如下:

I put my code into a tiny Android activity and got the same inconsistency. The code is as follows:

public class MainActivity extends Activity implements  SensorEventListener {

    private SensorManager mSensorManager;
    private float[] AccelerometerValues;
    private float[] MagneticFieldValues;
    private float[] RotationMatrix;
    private long nextRefreshTime;           // used to ensure dump to LogCat occurs no more than 4 times a second
    private DecimalFormat df;               // used for dumping sensors to LogCat

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mSensorManager = (SensorManager)getSystemService(android.content.Context.SENSOR_SERVICE);
        Sensor SensorAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mSensorManager.registerListener(this, SensorAccelerometer, SensorManager.SENSOR_DELAY_UI);  
        Sensor SensorMagField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        mSensorManager.registerListener(this, SensorMagField, SensorManager.SENSOR_DELAY_UI);
        AccelerometerValues = new float[3];
        MagneticFieldValues = new float[3];
        RotationMatrix = new float[9];
        nextRefreshTime = 0;
        df = new DecimalFormat("#.00");
    }

    @Override
    public void onSensorChanged(SensorEvent event) {

        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
            System.arraycopy(event.values, 0, AccelerometerValues, 0, AccelerometerValues.length);
        else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
                System.arraycopy(event.values, 0, MagneticFieldValues, 0, MagneticFieldValues.length);

        if (AccelerometerValues != null && MagneticFieldValues != null) {
            if(SensorManager.getRotationMatrix(RotationMatrix, null, AccelerometerValues, MagneticFieldValues)) {
                float[] OrientationValues = new float[3];
                SensorManager.getOrientation(RotationMatrix, OrientationValues);

                // chance conventions to match sample apps
                if (OrientationValues[0] < 0) OrientationValues[0] += 2*(float)Math.PI;
                OrientationValues[2] *= -1;

                // dump to logcat 4 times a second
                long currentTimeMillis = System.currentTimeMillis();
                if (currentTimeMillis > nextRefreshTime) {
                    nextRefreshTime = currentTimeMillis+250;
                    Log.i("Sensors",    // arrange output so that numbers line up in columns :-)
                            "(" + AngleToStr(OrientationValues[0]) + "," + AngleToStr(OrientationValues[1]) + "," + AngleToStr(OrientationValues[2])
                            + ") ("+FloatToStr(AccelerometerValues[0]) + "," + FloatToStr(AccelerometerValues[1]) + "," + FloatToStr(AccelerometerValues[2])
                            + ") ("+FloatToStr(MagneticFieldValues[0]) + "," + FloatToStr(MagneticFieldValues[1]) + "," + FloatToStr(MagneticFieldValues[2])+")");
                }               
            }
        }               
    }

    private String AngleToStr(double AngleInRadians) {
        String Str = "   "+Integer.toString((int)Math.toDegrees(AngleInRadians));
        return Str.substring(Str.length() - 3);
    }
    private String FloatToStr(float flt) {
        String Str = "      "+df.format(flt);
        return Str.substring(Str.length() - 6);
    }   

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mSensorManager.unregisterListener(this);
    }

    @Override
    public void onAccuracyChanged(Sensor arg0, int arg1) { }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

}

我使用的是运行 Jelly Bean 4.1.1 的 Galaxy Note 2.谁能告诉我我做错了什么?

I’m using a Galaxy Note 2 running Jelly Bean 4.1.1. Can anyone tell me what I’m doing wrong?

2013 年 3 月 24 日更新:更多信息.(1) 我在清单中禁用了纵向和横向之间的切换,因此 getWindowManager().getDefaultDisplay().getRotation() 始终为零.因此,我认为 remapCoordSystem 在这里没有帮助,因为那是为了切换轴,而我看到的错误并不是大错误,它们要微妙得多.(2) 我已经检查了精度灵敏度,当两个传感器都声称具有高精度时出现不一致.

Update 24-Mar-2013: More information. (1) I've disabled switches between portrait and landscape in the manifest, so getWindowManager().getDefaultDisplay().getRotation() is always zero. Hence I don't think remapCoordSystem would help here, because that's for switching axes, whereas the errors that I'm seeing aren't big errors, they're much more subtle. (2) I've checked the accuracy sensitivity, and the inconsistencies occur when both sensors claim to have high accuracy.

作为我看到的不一致的一个例子,当上面的代码给我 (azimuth,pitch,roll) = (235,-52,-11) 时,两个免费应用程序显示相似的值.但是当我看到 (278, -58, -52) 应用程序显示 (256, -58, -26) 时,方位角和横滚角的差异如此之大,尽管俯仰角似乎没问题.

As an example of the inconsistencies that I'm seeing, when the code above give me (azimuth,pitch,roll) = (235,-52,-11) then the two free apps show similar values. But when I see (278, -58, -52) the apps show (256, -58, -26), so big differences in both Azimuth and roll, although pitch seems OK.

推荐答案

我认为在设备不平坦时定义方向角的最佳方法是使用比标准欧拉角更合适的角坐标系你从 SensorManager.getOrientation(...) 得到的.我建议我描述的那个 在 math.stackexchange.com 上.我还在 这里的答案.除了方位角的良好定义外,它还对俯仰角进行了更好的定义,该方法将其定义为从水平面旋转,而不管旋转沿哪个轴发生.

I think the best way of defining your orientation angles when the device isn't flat is to use a more appropriate angular co-ordinate system that the standard Euler angles that you get from SensorManager.getOrientation(...). I suggest the one that I describe here on math.stackexchange.com. I've also put some code that does implements it in an answer here. Apart from a good definition of azimuth, it also has a better definition of the pitch angle, which this methodology defines as rotation out of the horizontal plane irrespective of which axis the rotation occurs along.

您可以从我在第一段中提供的两个链接中获得完整的详细信息.但是,总而言之,来自 SensorManager.getRotationMatrix(...) 的旋转矩阵 R

You can get full details from the two links that I've given in the first paragraph. However, in summary, your rotation matrix R from SensorManager.getRotationMatrix(...) is

where (Ex, Ey, Ez), (Nx, Ny, Nz) 和 (Gx, Gy, Gz) 是矢量指向正东、正北和重力方向.然后你想要的方位角由

where (Ex, Ey, Ez), (Nx, Ny, Nz) and (Gx, Gy, Gz) are vectors pointing due East, North, and in the direction of Gravity. Then the azimuth angle that you want is given by

这篇关于Android 上的方位角/偏航角和滚转方向传感器值不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆