0

我在使用纯 JavaScript 的网络应用程序中将设备加速度值转换为地球坐标系时遇到问题(解决方案的大多数问题都是 Android 或 iOS 特定的)。

我正在使用 gl-matrix 库来执行计算,并且到目前为止,我的解决方案主要基于我为 Android 本机应用程序找到的答案。到目前为止,我对方向和运动的事件处理程序有什么:

    readonly deg2rad = Math.PI / 180; // Degree-to-Radian conversion
    rotMatrix: mat3;
    relRotMatrix: mat3;
    earthAcc: mat3;

    resetOrientationPending: boolean = false;

handleOrientation(event) {
        var absolute = event.absolute;
        var alpha = event.alpha;
        var beta = event.beta;
        var gamma = event.gamma;

        if (this.rotMatrix) {
            let curRotMat = this.getRotationMatrix(alpha * this.deg2rad, beta * this.deg2rad, gamma * this.deg2rad);       
            this.relRotMatrix = mat3.multiply(mat3.create(), this.rotMatrix, curRotMat);
        }
        else if (this.resetOrientationPending) {
            this.resetOrientationPending = false;
            this.rotMatrix = mat3.transpose(mat3.create(), this.getRotationMatrix(alpha * this.deg2rad, beta * this.deg2rad, gamma * this.deg2rad));           
        }
    }

handleMotion(event) {
        let x = event.acceleration.x;
        let y = event.acceleration.y;
        let z = event.acceleration.z;

        let accMatrix = mat3.fromTranslation(mat3.create(), [x, y, z]);
        this.earthAcc = mat3.multiply(mat3.create(), this.relRotMatrix, accMatrix);

        let ex = this.earthAcc[6];
        let ey = this.earthAcc[7];
        let ez = this.earthAcc[8];
}

getRotationMatrix(alpha: number, beta: number, gamma: number): mat3 {
        let _x, _y, _z;
        let cX, cY, cZ, sX, sY, sZ;

        _z = alpha;
        _x = beta;
        _y = gamma;

        cX = Math.cos(_x);
        cY = Math.cos(_y);
        cZ = Math.cos(_z);
        sX = Math.sin(_x);
        sY = Math.sin(_y);
        sZ = Math.sin(_z);

        let res = mat3.create();

        res[0] = cZ * cY + sZ * sX * sY;    // row 1, col 1
        res[1] = cX * sZ;                   // row 2, col 1
        res[2] = -cZ * sY + sZ * sX * cY;   // row 3, col 1

        res[3] = -cY * sZ + cZ * sX * sY;   // row 1, col 2
        res[4] = cZ * cX;                   // row 2, col 2
        res[5] = sZ * sY + cZ * cY * sX;    // row 3, col 2

        res[6] = cX * sY;                   // row 1, col 3
        res[7] = -sX;                       // row 2, col 3
        res[8] = cX * cY;                   // row 3, col 3

        return res;
}

如果我将手机平放在桌子上(纵向模式),顶部指向远离我,并执行“resetOrientation”,这适用于左/右和向前/向后移动。也就是说,如果我将手机绕 z 轴旋转 180 度(意味着仍然平放在桌子上),所以我的顶部指向我,L/R 和 F/B 运动的加速度(代码中的 earthAcc 矩阵)是仍然正确。但是向上/向下不正确,一旦我开始围绕其他轴旋转手机,我就会得到不一致的结果。

可能只是缺少一行或类似的东西,希望矩阵代数大师能发现问题:)

更新:通过将我在 handleMotion 中创建 accMatrix 的方式更改为:

let accMatrix = mat3.create();
accMatrix.set([0, 0, 0, 0, 0, 0, x, y, z]);

...我也有 UP/DOWN 工作,但如果我在 Z 轴以外的任何其他轴上旋转手机,它不再给出正确的值。

更新 2:我正在 iOS Safari (Iphone) 上对此进行测试,所以我不知道这是否可能是特定于设备类型的问题,但我正在使用应该返回标准化值的 Gyronorm 库。

4

1 回答 1

0

我已经能够解决我的错误。加速度乘法矩阵应如下所示:

accMatrix.set([1, 0, 0,    0, 1, 0,    x, y, z]);

也就是说,基数应该是单位矩阵,而不是只有零。

于 2019-04-04T07:11:35.573 回答