Плавный Ориентационный Компас, используя магнитометр реагирующих нативных датчиков
Я разрабатываю приложение компаса, используя 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 для получения подробной информации.