【问题标题】:How can i get device tilt?我怎样才能获得设备倾斜?
【发布时间】:2014-06-16 11:46:00
【问题描述】:

我正在尝试让设备倾斜(设备沿 y 轴旋转,但不幸的是我无法实现我的目标。我尝试了很多使用 TYPE_ACCELEROMETER 和 TYPE_MAGNETIC_FIELD 作为组合传感器(传感器融合)的东西。我也有关注Motion Sensors

我想要什么?

我想获得安装在车辆上的设备(手机)的倾斜度。比方说,我在汽车上安装了一个设备,而汽车是静止的。所以倾角是0度。Lator on,当车辆通过下通道或天桥时,倾角应该是相应的。 我试图计算这个,这是我的代码:

...
...
    private static float ALPHA = 0.005f
    TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        tv = (TextView) findViewById(R.id.tv);
        edtAlpha = (EditText) findViewById(R.id.alpha);
        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        accelerometer = mSensorManager
                .getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        magnetometer = mSensorManager
                .getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        if (accelerometer == null) {
            Toast.makeText(this, "Oh  not found", Toast.LENGTH_SHORT).show();
        }
        if (magnetometer == null) {
            Toast.makeText(this, "Oh magnetometer not found",
                    Toast.LENGTH_SHORT).show();
        }

    }

    protected float[] lowPass(float[] input, float[] output) {
        if (output == null)
            return input;
        String s = edtAlpha.getText().toString();
        if (s != null && s.length() > 0) {
            try {
                ALPHA = Float.valueOf(s);
            } catch (NumberFormatException e) {
                ALPHA = 0.005f;
            }
        } else {
            ALPHA = 0.005f;
        }
        for (int i = 0; i < input.length; i++) {
            output[i] = output[i] + ALPHA * (input[i] - output[i]);
        }
        return output;
    }

    public int getRotation(final Activity activity) {
        int result = 1;
        Method mDefaultDisplay_getRotation;
        try {
            mDefaultDisplay_getRotation = Display.class.getMethod(
                    "getRotation", new Class[] {});
            Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
                    .getDefaultDisplay();

            Object retObj = mDefaultDisplay_getRotation.invoke(display);
            if (retObj != null) {
                result = (Integer) retObj;
            }
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return result;
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        Log.d(tag, "onSensorChanged");

        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            gravSensorVals = lowPass(event.values.clone(), gravSensorVals);

        } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
            magSensorVals = lowPass(event.values.clone(), magSensorVals);
        }

        if (gravSensorVals != null && magSensorVals != null) {
            SensorManager.getRotationMatrix(RTmp, I, gravSensorVals,
                    magSensorVals);

            int rotation = getRotation(this);

            if (rotation == 1) {
                SensorManager.remapCoordinateSystem(RTmp, SensorManager.AXIS_X,
                        SensorManager.AXIS_MINUS_Z, Rot);
            } else {
                SensorManager.remapCoordinateSystem(RTmp, SensorManager.AXIS_Y,
                        SensorManager.AXIS_MINUS_Z, Rot);
            }

            SensorManager.getOrientation(Rot, results);

            float azimuth = (float) (((results[0] * 180) / Math.PI) + 180);
            float pitch = (float) (((results[1] * 180 / Math.PI)) + 90);
            float roll = (float) (((results[2] * 180 / Math.PI)));

            tv.setText("Azimuth : " + df.format(azimuth) + "\nPitch : "
                    + df.format(pitch) + "\nRoll : " + df.format(roll));
        }

        Log.d(tag, "Sensor type : " + event.sensor.getType());

    }

    @Override
    protected void onResume() {
        super.onResume();
        mSensorManager.registerListener(this, accelerometer,
                SensorManager.SENSOR_DELAY_UI);
        mSensorManager.registerListener(this, magnetometer,
                SensorManager.SENSOR_DELAY_UI);
    }
...
...

我的代码有什么问题?

当我快速加速/减速我的汽车时,角度会迅速增加/减少,但它不应该。换句话说,当我加速/减速车辆时,不应该对角度有任何影响。 我也尝试遵循这些教程: Link 1 Link 2

【问题讨论】:

    标签: android rotation sensors android-sensors sensor-fusion


    【解决方案1】:

    首先,您应该避免直接使用加速度计或磁力计数据,除非您真的知道其中的含义以及您从这些传感器收到的数据。

    我个人建议您使用预定义的ROTATION_VECTOR 传感器,它将加速度计、磁力计和陀螺仪融合到卡尔曼滤波器中。 (请参阅this 如何从 ROTATION_VECTOR 传感器获取数据和this 如何使用数据。

    当您从this 项目开始时,您可以访问四元数并使用它或使用旋转矩阵并应用相应的conversion 来获取设备的欧拉角(名称并不总是一致的但你很可能对银行或态度感兴趣)。 最后一点:注意欧拉角受到gimbal lock(又名“跳跃”值)的影响。

    【讨论】:

    • 首先感谢您回答我的问题。我在我的示例应用程序中使用了你的代码。我从你的代码中使用了 ImprovementOrientationSensor1Provider 和 ImprovementOrientationSensor2Provider (包括必要的类)。但是我得到了可变的结果(角度),即使我的设备(LG-Nexus 4)静止在桌子上。这是,我如何使用您的代码: Quaternion q = currentOrientationProvider.getQuaternion();浮动角度 = (float) (2.0f * Math.acos(q.getW()) * 180.0f / Math.PI); Log.d("角度", String.valueOf(角度));你能告诉我我做错了什么吗?
    • 以下是输出:132.06401,132.06432,132.06334,132.06345,132.06252,132.06252,132.06168,132.06107,132.06134,132.06215,132.06207,132.06268,132.06332,132.06416,132.06346,132.06425,132.06326,132.06314,227.93698, 227.93661,227.9361,227.93614,227.93663,227.93794,227.93845,227.9378,132.06181,227.93822,227.93892,132.06259,204.06075,204.06076,204.06076,204.06076,204.06076,204.06078,225.64037,225.64124,225.64375 跨度>
    【解决方案2】:

    只要你使用加速度计和磁力计而不是陀螺仪,当设备进行快速加速/减速时,你的方法就会失败。您可以尝试过分聪明,并进行一些临时破解,似乎可以排除您发现的这种特定故障模式,但我什至不会尝试。

    真正的解决方案是也使用陀螺仪。以我的经验,这非常有效。

    TYPE_ROTATION_VECTOR 有什么问题?

    【讨论】:

    • 感谢阿里,陀螺仪只提供了一个变化。它不提供连续变化,例如车辆通过地下通道,然后陀螺仪会给你一个突然变化的价值。而且大多数设备都没有陀螺仪。 ROTATION_VACTOR : ROTATION_VACTOR 与设备旋转有关。对加速/减速的旋转传感器有什么影响吗?我想,它会有同样的效果
    • @MohammadImran 请重新阅读我的回答。我是说你也应该使用陀螺仪所以像以前一样使用加速度计和磁力计,但要增加陀螺仪。这是可靠地获得方向的唯一方法。是的,加速和减速会稍微影响结果,希望你甚至不会注意到它,这要归功于陀螺仪。所以,总而言之,我是说应该使用方向传感器(大概使用加速度计、磁力计和陀螺仪)。
    • 再次感谢,您能否在此处显示您的答案中的示例代码?非常感谢您的回复。
    • @MohammadImran 不,我自己不做 Android 编程。我在 Shimmer2 平台上用 C++ 实现了传感器融合和方向跟踪。但是,我不熟悉 Android API。我在回答中试图说明的一点是:我需要一个带有陀螺仪的设备,你需要使用方向传感器;然后,根据您对倾斜的定义,您可以推导出倾斜的数学公式。
    • 你能在这里分享数学公式吗?
    猜你喜欢
    • 1970-01-01
    • 2011-06-04
    • 2012-12-16
    • 1970-01-01
    • 2017-05-25
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 2023-03-21
    相关资源
    最近更新 更多