Javascript 如何计算给定(x,y,z)磁强计和加速计数据的航向(N/W/S/E)?

Javascript 如何计算给定(x,y,z)磁强计和加速计数据的航向(N/W/S/E)?,javascript,geolocation,core-location,sensors,cllocation,Javascript,Geolocation,Core Location,Sensors,Cllocation,我用它来获取这些传感器的原始数据 import {magnetometer, acclerometer} from 'react-native-sensors'; const subscription = accelerometer.subscribe(({ x, y, z, timestamp }) => console.log({ x, y, z, timestamp }) this.setState({ accelerometer: { x, y, z, timest

我用它来获取这些传感器的原始数据

import {magnetometer, acclerometer} from 'react-native-sensors';
const subscription = accelerometer.subscribe(({ x, y, z, timestamp }) =>
    console.log({ x, y, z, timestamp })
    this.setState({ accelerometer: { x, y, z, timestamp } })
);
const subscription = magnetometer.subscribe(({ x, y, z, timestamp }) => 
    console.log({ x, y, z })
    this.setState({ magnetometer: { x, y, z, timestamp } })
);
考虑到这6个数据点,我如何获得度和方向?什么是合适的算法

我不明白这里面的算法。这个答案利用了alpha,beta,gamma…这和“x,y,z”一样吗?为什么只使用3个数据点而不使用6个?为什么其他一些答案说需要加速计数据(用于倾斜调整?)。为什么没有利用所有6个数据点的答案

(注意:文档中有“magenetometer”的拼写错误)

磁强计测量地球的磁场。此信息与手机内的加速器相结合。加速器获取有关手机在空间中位置的信息。它能够通过手机内的固态传感器精确定位手机的位置,这些传感器可以测量手机的倾斜和移动。根据算法软件开发公司Sensor Platform的说法,这些设备提供的信息意味着无论手机处于哪个方向,compass应用程序都可以显示基本方向

一个类似的仅使用设备内置的磁强计传感器,使用包react原生传感器识别方向和计算角度,使用磁强计的3个数据点:

subscribe = async () => {
    new Magnetometer({
      updateInterval: 100
    })
    .then(magnetometerObservable => {
      this._subscription = magnetometerObservable;
      this._subscription.subscribe(sensorData => {
        console.log(sensorData);
        this.setState({magnetometer: this._angle(sensorData)});
      });
    })
    .catch(error => {
      console.log("The sensor is not available");
    });
  };

  _unsubscribe = () => {
    this._subscription && this._subscription.stop();
    this._subscription = null;
  };

  _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);
  };

  _direction = (degree) => {
    if (degree >= 22.5 && degree < 67.5) {
      return 'NE';
    }
    else if (degree >= 67.5 && degree < 112.5) {
      return 'E';
    }
    else if (degree >= 112.5 && degree < 157.5) {
      return 'SE';
    }
    else if (degree >= 157.5 && degree < 202.5) {
      return 'S';
    }
    else if (degree >= 202.5 && degree < 247.5) {
      return 'SW';
    }
    else if (degree >= 247.5 && degree < 292.5) {
      return 'W';
    }
    else if (degree >= 292.5 && degree < 337.5) {
      return 'NW';
    }
    else {
      return 'N';
    }
  };

  // Match the device top with pointer 0° degree. (By default 0° starts from the right of the device.)
  _degree = (magnetometer) => {
    return magnetometer - 90 >= 0 ? magnetometer - 90 : magnetometer + 271;
};
subscribe=async()=>{
新型磁强计({
更新间隔:100
})
.然后(磁强计可维护=>{
本._订阅=磁强计可维护;
此.\u subscription.subscripte(传感器数据=>{
控制台日志(传感器数据);
this.setState({磁强计:this._角度(传感器数据)});
});
})
.catch(错误=>{
console.log(“传感器不可用”);
});
};
_取消订阅=()=>{
this._subscription&&this._subscription.stop();
此订阅为空;
};
_角度=(磁强计)=>{
中频(磁强计){
设{x,y,z}=磁强计;
如果(数学常数2(y,x)>=0){
角度=数学atan2(y,x)*(180/数学PI);
}
否则{
角度=(数学atan2(y,x)+2*数学PI)*(180/数学PI);
}
}
返回数学圆(角);
};
_方向=(度)=>{
如果(度>=22.5和度<67.5){
返回“NE”;
}
否则如果(度>=67.5和度<112.5){
返回“E”;
}
否则如果(度>=112.5和度<157.5){
返回“SE”;
}
否则,如果(度>=157.5和度<202.5){
返回'S';
}
否则如果(度>=202.5和度<247.5){
返回“SW”;
}
否则,如果(学位>=247.5&&学位<292.5){
返回“W”;
}
否则如果(度>=292.5和度<337.5){
返回“NW”;
}
否则{
返回'N';
}
};
//将设备顶部与指针0°匹配。(默认情况下,0°从设备右侧开始。)
_度=(磁强计)=>{
返回磁强计-90>=0?磁强计-90:磁强计+271;
};
另一个使用磁强计和加速计中的6个数据点来计算方向:

 float[] mGravity;
float[] mGeomagnetic;

@Override
public void onSensorChanged(SensorEvent sensorEvent) {
  Sensor mySensor = sensorEvent.sensor;
  WritableMap map = mArguments.createMap();

  if (mySensor.getType() == Sensor.TYPE_ACCELEROMETER)
    mGravity = sensorEvent.values;
  if (mySensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
    mGeomagnetic = sensorEvent.values;
  if (mGravity != null && mGeomagnetic != null) {
    float R[] = new float[9];
    float I[] = new float[9];
    boolean success = mSensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
    if (success) {
      long curTime = System.currentTimeMillis();
      float orientation[] = new float[3];
      mSensorManager.getOrientation(R, orientation);

      float heading = (float)((Math.toDegrees(orientation[0])) % 360.0f);
      float pitch = (float)((Math.toDegrees(orientation[1])) % 360.0f);
      float roll = (float)((Math.toDegrees(orientation[2])) % 360.0f);

      if (heading < 0) {
        heading = 360 - (0 - heading);
      }

      if (pitch < 0) {
        pitch = 360 - (0 - pitch);
      }

      if (roll < 0) {
        roll = 360 - (0 - roll);
      }

      map.putDouble("azimuth", heading);
      map.putDouble("pitch", pitch);
      map.putDouble("roll", roll);
      sendEvent("Orientation", map);
      lastUpdate = curTime;
    }
  }
}
float[]mGravity;
浮磁;
@凌驾
传感器更改时的公共无效(传感器事件传感器事件){
传感器mySensor=sensorEvent.Sensor;
WritableMap=mArguments.createMap();
if(mySensor.getType()==Sensor.TYPE\u加速计)
mGravity=sensorEvent.values;
if(mySensor.getType()==传感器.TYPE\u磁场)
mGeomagnetic=传感器事件值;
if(mGravity!=null&&mGeomagnetic!=null){
浮动R[]=新浮动[9];
浮动I[]=新浮动[9];
boolean success=mSensorManager.getRotationMatrix(R,I,mGravity,mGeomagnetic);
如果(成功){
long curTime=System.currentTimeMillis();
浮动方向[]=新浮动[3];
mSensorManager.getOrientation(R,orientation);
浮动航向=(浮动)((数学角度(方向[0]))%360.0f);
浮动节距=(浮动)((数学角度(方向[1]))%360.0f);
浮动辊=(浮动)((数学角度(方向[2]))%360.0f);
如果(标题<0){
航向=360-(0-航向);
}
如果(节距<0){
节距=360-(0-节距);
}
如果(滚动<0){
滚动=360-(0-滚动);
}
地图双(“方位角”,航向);
地图。双(“音高”,音高);
地图。双掷(“滚”,滚);
sendEvent(“方向”,地图);
lastUpdate=curTime;
}
}
}

有。

这就是我在安卓系统中工作的原因:

let angle = Math.atan2(y, x);
angle = angle * (180 / Math.PI)
angle = angle + 90
angle = (angle +360) % 360
来自磁强计的数据在android和ios上并不一致。最后我自己做了一个包裹:


您能展示输入和输出示例吗?看看这似乎比我的原始数据好。