Подтвердить что ты не робот

Внедрите фильтр Kalman, чтобы сгладить данные из API DeviceOrientation

Я пытаюсь сгладить данные, получаемые с API-интерфейса DeviceOrientation, чтобы сделать приложение Google Cardboard в браузере.

Я передаю данные акселерометра прямо в поворот камеры ThreeJs, но мы получаем много шума на сигнале, вызывающем видение.

Кто-то предложил фильтр Калмана как лучший способ приблизиться к сглаживающим сигналам обработки сигнала, и я нашел эту простую библиотеку Javascript на gitHub

https://github.com/itamarwe/kalman

Однако он действительно освещает документацию.

Я понимаю, что мне нужно создать модель Калмана, предоставив Vector и 3 Matrices в качестве аргументов, а затем обновить модель, снова с вектором и матрицами в качестве аргументов за период.

Я также понимаю, что уравнение фильтра Калмана имеет несколько отдельных частей: текущее оценочное положение, значение усиления Кальмана, текущее считывание из API ориентации и предыдущее оценочное положение.

Я вижу, что точка в трехмерном пространстве может быть описана как вектор, поэтому любое из значений позиции, таких как оценочное положение или текущее чтение, может быть Vector.

Я не понимаю, как эти части могут быть переведены в Matrices, чтобы сформировать аргументы для библиотеки Javascript.

4b9b3361

Ответ 1

Хорошо, я написал ложно задокументированную библиотеку пару лет назад. Если у меня есть интерес, я определенно готов его обновить, улучшить документацию и написать тесты.

Позвольте мне вкратце объяснить, каковы все разные матрицы и векторы и как они должны быть получены:

x - это вектор, который вы пытаетесь оценить. В вашем случае это, вероятно, 3 angular ускорения.

P - это ковариационная матрица оценки, что означает неопределенность оценки. Он также оценивается на каждом шаге фильтра Калмана вместе с x.

F - описывает, как x развивается в соответствии с моделью. Как правило, модель x[k] = Fx[k-1]+w[k]. В вашем случае F может быть идентификационной матрицей, если вы ожидаете, что ускорение angular будет относительно плавным, или нулевая матрица, если вы ожидаете, что ускорение angular будет полностью непредсказуемым. В любом случае w будет представлять, насколько вы ожидаете, что ускорение изменится с шага на шаг.

w - описывает шум процесса, а это означает, насколько модель отклоняется от "идеальной" модели. Он определяется как нулевое среднее многомерное нормальное распределение с ковариационной матрицей Q.

Все указанные выше переменные определяют вашу модель, что означает то, что вы пытаетесь оценить. В следующей части мы расскажем о модели наблюдения - о том, что вы измеряете, чтобы оценить вашу модель.

z - это то, что вы измеряете. В вашем случае, поскольку вы используете акселерометры, вы измеряете то, что вы также оцениваете. Это будут ускорения angular.

H - описывает связь между вашей моделью и наблюдением. z[k]=H[k]x[k]+v[k]. В вашем случае это единичная матрица.

v - измерительный шум и считается нулевым средним гауссовским белым шумом с ковариацией R [k]. Здесь вам нужно измерить, насколько шумными являются акселерометры, и вычислить матрицу ковариации шума.

Подводя итог, шаги по использованию фильтра Калмана:

  • Определите x[0] и P[0] - начальное состояние вашей модели и начальную оценку того, насколько точно вы знаете x[0].
  • Определите F на основе вашей модели и как она развивается с шага на шаг.
  • Определите Q на основе стохастического характера вашей модели.
  • Определите H на основе соотношения между тем, что вы измеряете, и тем, что вы хотите оценить (между моделью и измерением).
  • Определите R на основе измерения шума. Насколько шумно ваше измерение.

Затем при каждом новом наблюдении вы можете обновить оценку состояния модели с использованием фильтра Калмана и получить оптимальную оценку состояния модели (x[k]) и точности этой оценки (P[k]).

Ответ 2

var acc = {
 x:0,
 y:0,
 z:0
};

var count = 0;

if (window.DeviceOrientationEvent) {
  window.addEventListener('deviceorientation', getDeviceRotation, false);
}else{
  $(".accelerometer").html("NOT SUPPORTED")
}

var x_0 = $V([acc.x, acc.y, acc.z]); //vector. Initial accelerometer values

//P prior knowledge of state
var P_0 = $M([
              [1,0,0],
              [0,1,0],
              [0,0,1]
            ]); //identity matrix. Initial covariance. Set to 1
var F_k = $M([
              [1,0,0],
              [0,1,0],
              [0,0,1]
            ]); //identity matrix. How change to model is applied. Set to 1
var Q_k = $M([
              [0,0,0],
              [0,0,0],
              [0,0,0]
            ]); //empty matrix. Noise in system is zero

var KM = new KalmanModel(x_0,P_0,F_k,Q_k);

var z_k = $V([acc.x, acc.y, acc.z]); //Updated accelerometer values
var H_k = $M([
              [1,0,0],
              [0,1,0],
              [0,0,1]
            ]); //identity matrix. Describes relationship between model and observation
var R_k = $M([
              [2,0,0],
              [0,2,0],
              [0,0,2]
            ]); //2x Scalar matrix. Describes noise from sensor. Set to 2 to begin
var KO = new KalmanObservation(z_k,H_k,R_k);

//each 1/10th second take new reading from accelerometer to update
var getNewPos = window.setInterval(function(){

    KO.z_k = $V([acc.x, acc.y, acc.z]); //vector to be new reading from x, y, z
    KM.update(KO);

    $(".kalman-result").html(" x:" +KM.x_k.elements[0]+", y:" +KM.x_k.elements[1]+", z:" +KM.x_k.elements[2]);
    $(".difference").html(" x:" +(acc.x-KM.x_k.elements[0])+", y:" +(acc.y-KM.x_k.elements[1])+", z:" +(acc.z-KM.x_k.elements[2]))


}, 100);

 //read event data from device
function getDeviceRotation(evt){

    // gamma is the left-to-right tilt in degrees, where right is positive
    // beta is the front-to-back tilt in degrees, where front is positive
    // alpha is the compass direction the device is facing in degrees
    acc.x = evt.alpha;
    acc.y = evt.beta;
    acc.z = evt.gamma; 
    $(".accelerometer").html(" x:" +acc.x+", y:" +acc.y+", z:" +acc.z);
}

Вот демонстрационная страница, показывающая мои результаты

http://cardboard-hand.herokuapp.com/kalman.html

Я установил шум датчика для 2-х скалярных матриц, чтобы убедиться, что Kalman делает это, но мы заметили, что датчик имеет большую дисперсию по оси x, когда телефон лежит на столе. Мы считаем, что это может быть проблемой с Gimbal lock. Мы не тестировали, но его возможная изменчивость изменяется в каждой оси в зависимости от ориентации устройства.