28

从我的 Android 设备中,我可以读取一组线性加速度值(在设备的坐标系中)和一组绝对方向值(在地球坐标系中)。我需要的是在后一个坐标中获得线性加速度值。系统。

我怎样才能转换它们?

在阿里回复评论后编辑:

好吧,所以如果我理解正确,当我测量线性加速度时,手机的位置完全无关紧要,因为读数是在地球坐标系中给出的。对?

但我只是做了一个测试,我将手机放在不同的位置并在不同的轴上获得加速度。有 3 对图片 - 第一张显示我是如何放置设备的(对不起我的 Paint “大师技能”),第二张显示来自线性 acc 提供的数据的读数。传感器:

  1. 设备放在左侧

第一位置 初读

  1. 仰卧装置

第二名 二读

  1. 设备站立

在此处输入图像描述 在此处输入图像描述

现在 - 为什么在第三种情况下加速度发生在 Z 轴(而不是 Y),因为设备位置无关紧要?

4

4 回答 4

44

我终于设法解决了!因此,要在地球坐标系中获得加速度矢量,您需要:

  1. 从(使用和传感器值作为参数)获取旋转矩阵(float[16]因此它可以在以后被android.opengl.Matrix类使用),SensorManager.getRotationMatrix()SENSOR.TYPE_GRAVITYSENSOR.TYPE_MAGNETIC_FIELD
  2. 在旋转矩阵上使用android.opengl.Matrix.invertM()来反转它(不是转置!),
  3. 使用Sensor.TYPE_LINEAR_ACCELERATION传感器获取线性加速度矢量(在设备的坐标系中),
  4. 用于android.opengl.Matrix.multiplyMV()将旋转矩阵乘以线性加速度向量。

你有它!我希望我能为别人节省一些宝贵的时间。

感谢 Edward Falk 和 Ali 的提示!!

于 2012-07-23T14:19:59.593 回答
18

根据@alex 的回答,这里是代码片段:

private float[] gravityValues = null;
private float[] magneticValues = null;

 @Override
    public void onSensorChanged(SensorEvent event) {
        if ((gravityValues != null) && (magneticValues != null) 
            && (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)) {

            float[] deviceRelativeAcceleration = new float[4];
            deviceRelativeAcceleration[0] = event.values[0];
            deviceRelativeAcceleration[1] = event.values[1];
            deviceRelativeAcceleration[2] = event.values[2];
            deviceRelativeAcceleration[3] = 0;

            // Change the device relative acceleration values to earth relative values
            // X axis -> East
            // Y axis -> North Pole
            // Z axis -> Sky

            float[] R = new float[16], I = new float[16], earthAcc = new float[16];

            SensorManager.getRotationMatrix(R, I, gravityValues, magneticValues);

            float[] inv = new float[16];

            android.opengl.Matrix.invertM(inv, 0, R, 0);
            android.opengl.Matrix.multiplyMV(earthAcc, 0, inv, 0, deviceRelativeAcceleration, 0);
           Log.d("Acceleration", "Values: (" + earthAcc[0] + ", " + earthAcc[1] + ", " + earthAcc[2] + ")");                

        } else if (event.sensor.getType() == Sensor.TYPE_GRAVITY) {
            gravityValues = event.values;
        } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
            magneticValues = event.values;
        } 
   }
于 2016-04-07T13:26:59.023 回答
4

根据文档,您可以获得手机坐标系中的线性加速度。

您可以通过将任何矢量与旋转矩阵相乘将其从手机坐标系转换为地球坐标系您可以从getRotationMatrix()获取旋转矩阵。

(也许已经有一个函数为你做这个乘法,但我不做 Android 编程,我不熟悉它的 API。)

关于旋转矩阵的一个很好的教程是方向余弦矩阵 IMU:理论手稿。祝你好运!

于 2012-07-20T11:53:34.723 回答
1

好的,首先,如果您想在 Android 上进行实际的惯性导航,那么您的工作已经完成。智能手机中使用的廉价小传感器不够精确。虽然,在小距离的内部导航方面已经完成了一些有趣的工作,例如在建筑物内。可能有关于你可以挖掘的主题的论文。谷歌“Motion Interface Developers Conference”,你可能会发现一些有用的东西——这是 Invensense 几个月前举办的一次会议。

其次,不,线性加速度在设备坐标中,而不是世界坐标中。您必须自己转换,这意味着知道设备的 3-d 方向。

您要做的是使用支持虚拟传感器 TYPE_GRAVITY 和 TYPE_LINEAR_ACCELERATION 的 Android 版本。您需要一个带有陀螺仪的设备才能获得相当准确和精确的读数。

在内部,系统结合了陀螺仪、加速度计和磁力计,以便为设备方向提供真实值。这有效地将加速度计设备拆分为其重力和加速度分量。

因此,您要做的是为 TYPE_GRAVITY、TYPE_LINEAR_ACCELERATION 和 TYPE_MAGNETOMETER 设置传感器侦听器。使用重力和磁力计数据作为 SensorManager 的输入。getRotationMatrix() 以获取将世界坐标转换为设备坐标的旋转矩阵,反之亦然。在这种情况下,您需要“反之”部分。也就是说,通过将线性加速度输入乘以方向矩阵的转置,将它们转换为世界坐标。

于 2012-07-21T17:09:42.353 回答