Плавный Ориентационный Компас, используя магнитометр реагирующих нативных датчиков

Я разрабатываю приложение компаса, используя react-native-sensors магнитометр. Я получаю правильные значения, и компас работает отлично, главная проблема - быстрое обновление компаса, направление меняется слишком часто, и изменение составляет +-5 градусов. Я хочу сделать компас плавной ориентации.

_angle = (magnetometer) => {
    if (magnetometer) {
      let { x, y, z } = magnetometer

      if (Math.atan2(y, x) >= 0) {
        angle = Math.atan2(y, x) * (180 / Math.PI)
      } else {
        angle = (Math.atan2(y, x) + 2 * Math.PI) * (180 / Math.PI)
      }
    }

    return Math.round(angle)
  }


//Inside ComponentDidMount
magnetometer.subscribe(({ x, y, z, timestamp }) =>
      this.setState({ sensorValue: this._angle({ x, y, z }) })

2 ответа

Нахождение ответа звучит похоже на ответ SamuelPS, я использовал LPF: фильтр нижних частот для JavaScript, он просто более оптимизирован и плавен.

constructor(props) {
    super(props)
    LPF.init([])
  }

_angle = (magnetometer) => {
    if (magnetometer) {
      let { x, y, z } = magnetometer

      if (Math.atan2(y, x) >= 0) {
        angle = Math.atan2(y, x) * (180 / Math.PI)
      } else {
        angle = (Math.atan2(y, x) + 2 * Math.PI) * (180 / Math.PI)
      }
    }

    return Math.round(LPF.next(angle))
  }

Я бы предложил 2 вещи.

Не обновляйте свое состояние с каждым выходом магнитометра. Вместо этого сделайте какой-то фильтр с данными. Простым примером может быть уменьшение выборки. Скажем, магнитометр дает вам 1000 сэмплов / с (я составил данные). 1000 обновлений в секунду для представления - это слишком много, вместо этого создайте буфер из 200 выборок и установите состояние среднего значения этих 200 выборок при каждом заполнении. В этом случае у вас будет всего 5 обновлений в секунду, что значительно уменьшит ощущение вибрации. Проведите здесь некоторые эксперименты с различными значениями, пока не найдете желаемый результат. Если вы хотите что-то более гладкое, может также работать перекрывающийся буфер: буфер 200 выборок, но вместо того, чтобы каждый раз переполнять буфер, вы просто удаляете первый из 100. Таким образом, у вас есть сокращение на 1/10 выборок, но каждый выход - это среднее значение между 100 новыми выборками и 100 выборками, которые уже влияли на выход.

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

С этими двумя вещами все должно работать гладко. Я надеюсь, что эта информация полезна, удачи с вашим компасом!

Добавив к ответу Абдуллы Яхьи, установите и импортируйте модуль LPF. Установите значение сглаживания LPF и проверьте, не исчезли ли колебания.

import LPF from "lpf";

constructor() {
  super();
  LPF.init([]);
  LPF.smoothing = 0.2;
}

_angle = magnetometer => {
let angle = 0;
if (magnetometer) {
  let {x, y} = magnetometer;
    if (Math.atan2(y, x) >= 0) {
      angle = Math.atan2(y, x) * (180 / Math.PI);
    } else {
      angle = (Math.atan2(y, x) + 2 * Math.PI) * (180 / Math.PI);
    }
  }
  return Math.round(LPF.next(angle));
};

См. Это репо - react-native-compass для получения подробной информации.

Другие вопросы по тегам