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

4

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


我在对100个样本进行平均值计算方面运气不错,这似乎可以使结果更平滑,并且更新速度合理。 - Anger Density
@AngerDensity 实际上我尝试过取中位数,也尝试过取平均值,虽然平滑了一些,但效果并不是很好。 - Abdullah Yahya
3个回答

3

找到一个听起来和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))
  }

抱歉,我不知道为什么它没有解决我的问题。请帮我解决一下。 - Ahtesham Shah
当指南针的数值从360变为0时,立刻出现奇怪的不稳定情况..... :( - Hani Q

1
我建议两件事情。
不要每次磁力计输出都更新状态。相反,使用数据进行某种过滤。 一个简单的例子是减少采样。假设磁力计提供了1000个样本/秒(我编造了数据)。每秒向视图更新1000次太多了,相反,创建一个缓冲区200个样本,并且每次填满时将该200个样本的平均值设置为状态。在这种情况下,你只有每秒5次更新,大大减少了震动感觉。在此尝试使用不同的值进行一些实验,直到找到所需的输出。如果你想要更平滑的效果,重叠的缓冲区也可以起作用: 200个样本的缓冲区,但不是每次填满时重置缓冲区,而是删除前100个样本。因此,你的样本数减少了1/10,但每次输出都是100个新样本和100个已经影响输出的样本的平均值。
第二件事是不要直接将指南针针头设置在磁力计值的位置,否则它看起来会跳动(没有平滑)。要创建一个过渡动画,在改变位置时产生平滑的移动。
有了这两个东西,应该能够平稳地工作了。 希望这些信息有用,祝你的指南针好运!

0

添加到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 获取详细信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接