使用 react-native-sensors 的磁力计的平滑方向指南针

Smooth Orientation Compass using react-native-sensors's Magnetometer

我正在使用 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 }) })

我会提出两件事。

不要用磁力计的每个输出更新你的状态。相反,对数据进行某种过滤。 一个简单的例子就是减少采样。假设磁力计为您提供 1000 samples/s(我编造了数据)。每秒对视图进行 1000 次更新太多了,而不是创建一个 200 个样本的缓冲区,并在每次缓冲区满时设置这 200 个样本的平均值的状态。在那种情况下,你每秒只有 5 次更新,大大减少了震动感。在这里用不同的值做一些实验,直到找到所需的输出。如果你想要更平滑的东西,重叠缓冲区也可以工作:200 个样本缓冲区,但不是每次都重置缓冲区已满,你只需删除第一个 100 个。所以你减少了 1/10 的样本,但每个输出都是 100 个新样本和 100 个已经影响输出的样本之间的平均值。

其次是罗盘指针不要直接放在磁力计数值的位置,否则看起来指针在跳动(零位平滑)。创建过渡动画以在更改位置时产生平滑的移动。

有了这两个东西,应该就可以顺利运行了。 希望这些信息有用,祝你的指南针好运!!

找到一个听起来类似于 answer, I used LPF: Low Pass Filter for 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))
  }

添加到 Abdullah Yahya 的回答中,安装并导入 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 了解详细信息。