Javascript - преобразование устройства ускорения в земные координаты - PullRequest
0 голосов
/ 02 апреля 2019

У меня проблема с преобразованием значений ускорения устройства в систему координат Земли в веб-приложении с использованием чистого 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», это работает для перемещения влево / вправо и вперед / назад. То есть, если я поверну телефон на 180 градусов вокруг оси z (имеется в виду, что он все еще лежит на столе), и верх будет направлен на меня, ускорение (матрица earthAcc в коде) для движения L / R и F / B будет все еще правильно. Но вверх / вниз не правильно, и как только я начинаю поворачивать телефон вокруг другой оси, я получаю противоречивые результаты.

Возможно, отсутствует только одна строка или что-то в этом роде, надеюсь, кто-то, кто является гуру матричной алгебры, обнаружит проблему:)

ОБНОВЛЕНИЕ: изменив способ создания accMatrix в handleMotion следующим образом:

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

... У меня также работает UP / DOWN, но если я поворачиваю телефон по любой другой оси, кроме Z, он больше не дает правильных значений.

ОБНОВЛЕНИЕ 2: я тестирую это на iOS Safari (Iphone), поэтому не знаю, может ли это быть проблемой, связанной с типом устройства, но я использую библиотеку Gyronorm, которая должна возвращать нормализованные значения.

1 Ответ

0 голосов
/ 04 апреля 2019

Мне удалось разобраться в моей ошибке. Матрица умножения ускорения должна выглядеть так:

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

То есть вместо нулей база должна быть единичной матрицей.

...