将加速度计矢量从设备转换为地球坐标

时间:2019-03-26 18:29:50

标签: android rotation accelerometer coordinate-transformation rotational-matrices

我在Internet和StackOverflow上进行了搜索,以找到一种将Android加速度计矢量从设备坐标系转换为地球坐标系的方法。我正在使用Sensor.TYPE_ROTATION_VECTOR来执行此操作。我正在使用NativeScript和MathJS进行矩阵计算来访问传感器。

  1. 我使用Sensor.TYPE_ROTATION_VECTOR获取旋转矢量
  2. 我根据https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/hardware/SensorManager.java中给出的getRotationMatrixFromVector()的Android代码来计算旋转矩阵。
    --- 2.1我计算q0,q1 = acceleration.x,q2 = acceleration.y,q3 = acceleration.z --- 2.2我尝试使用float [9]和float [16]矩阵大小来计算旋转矩阵,但是我都无法使用它们。 --- 2.3我尝试将这两个旋转矩阵求逆并转置。
  3. 我现在将旋转矩阵(尝试正常,反转和转置)乘以矩阵[[accel.x],[accel.y],[accel.z],[0.0]](4x1矩阵)
  4. 当我查看新转换的加速度值时,它们根本没有旋转。如果我将设备的x轴指向地球的北方,并向该方向加速,则我的acceleration.x将> 1,其他值几乎为0。在这里,我的accelion.y应该转换为> 1。类似地,如果我将设备的y轴指向天空并将其沿该方向加速,则当我的加速度.z应该读为> 1时,我的加速度.y读为> 1。

谁能告诉我我在这些步骤中做错了什么?共识似乎是抓住旋转向量,将其转换为旋转矩阵,将矩阵求逆,然后将此求反矩阵乘以加速度计向量。它对我不起作用。谢谢,

    var r;
    var rinv;
    accelerometer.startAccelerometerUpdates(function (accel) {
        if (accel.sensortype == 11) {
            var q0 = Math.sqrt(1 - accel.x*accel.x - accel.y*accel.y - accel.z*accel.z);
            var q1 = accel.x;
            var q2 = accel.y;
            var q3 = accel.z;
            //calculate rotation matrix from unit quaternion
            var sq1 = 2*q1*q1;
            var sq2 = 2*q2*q2;
            var sq3 = 2*q3*q3;
            var q1q2 = 2*q1*q2;
            var q3q0 = 2*q3*q0;
            var q1q3 = 2*q1*q3;
            var q2q0 = 2*q2*q0;
            var q2q3 = 2*q2*q3;
            var q1q0 = 2*q1*q0;
            //r = math.matrix([[1-sq2-sq3,q1q2-q3q0,q1q3+q2q0],[q1q2+q3q0,1-sq1-sq3,q2q3-q1q0],[q1q3-q2q0,q2q3+q1q0,1-sq1-sq2]]);
            r = math.matrix([[1-sq2-sq3,q1q2-q3q0,q1q3+q2q0,0.0],[q1q2+q3q0,1-sq1-sq3,q2q3-q1q0,0.0],[q1q3-q2q0,q2q3+q1q0,1-sq1-sq2,0.0],[0.0,0.0,0.0,1.0]]);
            rinv = math.inv(r);
        }
        if (accel.sensortype == 10) {
            //filter accelerometer errors
            if (Math.abs(accel.x) < 10 || Math.abs(accel.y) < 10 || Math.abs(accel.z) < 10) {
                if ((Math.abs(accel.x) > .15 && Math.abs(accel.x)/oldAX < 2) || (Math.abs(accel.y) > .15 && Math.abs(accel.y)/oldAY < 2) || (Math.abs(accel.z) > .15 && Math.abs(accel.z)/oldAZ < 2)) {  //filter errors in accelerometer
                    var Ad = math.matrix([[accel.x],[accel.y],[accel.z],[0.0]]);
                    //transform acceleration values from device coordinates to Earth coordinates
                    var Ag = math.multiply(rinv,Ad);
                    var ax = Ag.get([0,0]);
                    var ay = Ag.get([1,0]);
                    var az = Ag.get([2,0]);
                    if (ax > 1 || ay > 1 || az > 1) {  //only show large values for easier analyses
                        page.getViewById("rotationLabel").text = "Earth Axes Acceleration \n x: " + ax + "\ny: " + ay + "\nz: " + az;
                    }

我希望设备的加速度计值可以像本页上的旋转矢量部分一样转换为地球的坐标系。 https://developer.android.com/guide/topics/sensors/sensors_motion

1 个答案:

答案 0 :(得分:0)

NativeScript-Accelerometer-Advanced插件编码错误。由于由传感器提供,因此无需计算单位四元数值q0。不需要除以重力(9.81 m / s ^ 2),因为它不包含在传感器中。我在本地副本中修复了此问题,并且轮换方法正常工作: 1.获取旋转矢量 2.计算旋转矩阵 3.反转旋转矩阵 4.将加速度计矢量乘以反向旋转矩阵并附加[1.0]作为第四行