从设备的坐标系加速到绝对坐标系

ale*_*lex 26 android vector accelerometer coordinate-systems coordinate-transformation

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

我该怎么转换它们?

在Ali回复评论后编辑:

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

但我刚做了一个测试,我把手机放在不同的位置,并在不同的轴上加速.有3对图片 - 第一部分显示我如何放置设备(对不起我的Paint"掌握技能"),第二部分显示线性acc提供的数据读数.传感器:

  1. 装置放在左侧

第一个位置 初读

  1. 设备躺在背上

第二个位置 二读

  1. 设备站立

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

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

ale*_*lex 42

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

  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提示!

  • 在步骤4中,您不能直接使用传感器数据,因为它的长度为3并且您需要长度4.您是在末尾还是在开始时添加0或1? (2认同)
  • @NinovanHooff在第4位(数组[3])应该有0值 (2认同)
  • 进行反演可能是因为旋转矩阵是根据世界轴而不是电话轴计算的,如此处所述(http://gentlenav.googlecode.com/files/DCMDraft2.pdf).这是一篇科学论文,描述了第III.A部分中的相同方法(http://www.ece.nus.edu.sg/stfpage/elesohws/PerCom_Pedestrian_Tracking.pdf) (2认同)
  • @alex你可以发布将linear_acceleration更正为世界坐标的代码吗?我的传感器监听器正在使用Sensor.TYPE_ROTATION_VECTOR创建一个旋转矩阵,它工作得很好,但我似乎无法按照你描述的方式纠正linear_acceleration ..代码示例会很棒 (2认同)
  • 为什么在“SensorManager.getRotationMatrix()”中使用了“SENSOR.TYPE_GRAVITY”?文档(http://developer.android.com/reference/android/hardware/SensorManager.html#getRotationMatrix(float[], float[], float[], float[]))说要使用` TYPE_加速度计` (2认同)

ora*_*rak 15

根据@ 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;
        } 
   }
Run Code Online (Sandbox Code Playgroud)

  • 有效!谢谢@orak!我没有重力传感器类型,所以我只是使用低通滤波器来获取它。 (2认同)

Ali*_*Ali 5

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

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

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

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