2014-11-09 2 views
2

Я использую Sensortag CC2541 (подключенный к Nexus телефону)простого компаса с помощью тометра - Android (Java)

Я использую тометр этого датчика, чтобы сделать простой компас. Я использую следующие уравнения, чтобы найти Север, Юг, Запад и Восток.

Direction (y>0) = 90 - [arcTAN(x/y)]*180/pi

Direction (y<0) = 270 - [arcTAN(x/y)]*180/pi

Direction (y=0, x<0) = 180.0

Direction (y=0, x>0) = 0.0

Вот код, я использую в моей updateMagnetometer метод

@Override 
    public void onUpdateMagnetometer(SensorTagManager mgr, Point3D b) { 
     super.onUpdateMagnetometer(mgr, b); 

     double m=0; 

     if(b.x < 0.0 && (b.y < 0.01 && b.y > 0.0)) 
      m = 180; 
     else if(b.x > 0.0 && (b.y < 0.01 && b.y > 0.0)) 
      m = 0; 
     else if(b.y > 0.0) 
      m = 90 - (Math.atan(b.x/b.y))*(180/Math.PI); 
     else if(b.y < 0.0) 
      m = 270 - (Math.atan(b.x/b.y))*(180/Math.PI); 

     final float rot = (float) m; 

     runOnUiThread(new Runnable() { 

      @Override 
      public void run() { 
       pointer.setRotation(-rot); //pointer is the image of my compass 
      } 
     }); 
    } 

Но когда я запускаю его, компас всегда застрял между Северным и Западным НОМЕРАМИ, насколько я перемещаю, поворачиваю или меняю положение датчика.

Возможны ли какие-либо ошибки?

А также, я много искал в Интернете для получения помощи компаса. Но я ничего не могу найти. Любые подсказки для кодирования, псевдокод или подсказку для компаса с использованием магнитометра, акселерометра и/или гироскопа ???


Экстра Информация

Так что это в моем главном классе. Эти методы вызывают каждые x секунд для обновления показаний. PS: мой датчик имеет 2 кнопки (справа и слева)

mStManager.enableSensor(Sensor.MAGNETOMETER,MAGNETOMETER_UPDATE_PERIOD); 
    mStManager.enableSensor(Sensor.ACCELEROMETER,MAGNETOMETER_UPDATE_PERIOD);  

    @Override 
    public void onUpdateAmbientTemperature(SensorTagManager mgr, double temp) { 
     super.onUpdateAmbientTemperature(mgr, temp); 
    } 

    @Override 
    public void onUpdateAccelerometer(SensorTagManager mgr, Point3D acc) { 
     super.onUpdateAccelerometer(mgr, acc); 

    } 

    @Override 
    public void onUpdateBarometer(SensorTagManager mgr, double pressure, double height) { 
     super.onUpdateBarometer(mgr, pressure, height); 
    } 

    @Override 
    public void onUpdateGyroscope(SensorTagManager mgr, Point3D ang) { 
     super.onUpdateGyroscope(mgr, ang); 
    } 

    @Override 
    public void onUpdateHumidity(SensorTagManager mgr, double rh) { 
     super.onUpdateHumidity(mgr, rh); 
    } 

    @Override 
    public void onUpdateInfraredTemperature(SensorTagManager mgr, double temp) { 
     super.onUpdateInfraredTemperature(mgr, temp); 
    } 

    @Override 
    public void onUpdateKeys(SensorTagManager mgr, boolean left, boolean right) { 
     super.onUpdateKeys(mgr, left, right); 

     if (right) { 
      mgr.calibrateMagnetometer(); 
     } 
    } 

    @Override 
    public void onUpdateMagnetometer(SensorTagManager mgr, Point3D b) { 
     super.onUpdateMagnetometer(mgr, b); 
    } 

} 

Так в основном в методе onUpdateMagnetometer, то b содержит мое чтение. Это класс Point3D, который показан ниже

public class Point3D { 
public double x, y, z; 

public Point3D(double x, double y, double z) { 
    this.x = x; 
    this.y = y; 
    this.z = z; 
} 

public double norm() { 
    return Math.sqrt(x*x + y*y + z*z); 
} 

@Override 
public int hashCode() { 
    final int prime = 31; 
    int result = 1; 
    long temp; 
    temp = Double.doubleToLongBits(x); 
    result = prime * result + (int) (temp^(temp >>> 32)); 
    temp = Double.doubleToLongBits(y); 
    result = prime * result + (int) (temp^(temp >>> 32)); 
    temp = Double.doubleToLongBits(z); 
    result = prime * result + (int) (temp^(temp >>> 32)); 
    return result; 
} 

@Override 
public boolean equals(Object obj) { 
    if (this == obj) 
     return true; 
    if (obj == null) 
     return false; 
    if (getClass() != obj.getClass()) 
     return false; 
    Point3D other = (Point3D) obj; 
    if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x)) 
     return false; 
    if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y)) 
     return false; 
    if (Double.doubleToLongBits(z) != Double.doubleToLongBits(other.z)) 
     return false; 
    return true; 
} 

public String toString() { 
    return "[" + this.x + ", " + this.y + ", " + this.z + "]"; 
} 

} 
+0

Я хотел бы помочь вам, но я действительно не понимаю, что ваш код пытается сделать. Во-первых, 'Direction (y = 0, x> 0) = 0.0' не является уравнением, я даже не знаю, что это значит. Второе использование однобуквенных переменных - отличный способ заставить людей игнорировать ваш вопрос, поскольку их очень трудно читать. Что такое 'b'? Есть ли у него какие-то показания с магнитометра? –

+0

Я получил «Направление (y = 0, x> 0) = 0.0' с веб-сайта. В основном это означает, что 'y' магнитометра равен 0, а его' x' больше 0, тогда указатель компаса должен быть на '0.0' (север). остальные похожи на его. Кроме того, 'b' - это показание с магнитометра. В аргументе ** b ** является классом «Point3D», который имеет «x, y, z», которые являются переменной магнитометра. Объект 'b' также содержит такие методы, как' norm() ',' toString() '... и т. Д. Но единственными и наиболее важными полях являются' x, y, z'. – Masster

+0

Правильно, я вижу, что 'b' - это Point3D, это в вашем коде. Мой вопрос: какие данные в нем? являются «x, y, z», описывающие точку на единичной окружности, какой-то кватернион, сильные стороны магнитного поля на каждой оси и т. д.? Вы не дали нам достаточно кода, чтобы узнать, откуда берется значение 'b'. –

ответ

3

Одна из проблем, у вас есть, что вы обработка 3D-магнитометр в качестве 2D датчика. Это не так.

Один из способов сделать это, чтобы использовать данные как магнитометр и акселерометр:

  1. Вы захватить чтение с обоих датчиков, запускать эти значения через SensorManager.getRotationMatrix, чтобы получить начальную матрицу вращения. (Обратите внимание, что в документации, описание матриц имеет единичную матрицу и матрицу вращения переключился.)
  2. Ставишь результат через SensorManager.getOrientation, чтобы получить ориентацию устройства в 3D-пространстве
  3. используется первое значение в ориентировочная матрица как направление компаса

Это окончательное значение представляет собой поворот устройства вокруг вектора, направленного к центру Земли, что именно то, что вы хотите для компаса. Используя значение THAT, вы можете рассчитать местоположение на запад, восток и юг.

Код будет выглядеть примерно так: (без учета установки датчиков)

// globals 
private float[] gravityData = new float[3]; 
private float[] geomagneticData = new float[3]; 
private boolean hasGravityData = false; 
private boolean hasGeomagneticData = false; 
private double rotationInDegrees; 


@Override 
public void onSensorChanged(SensorEvent event) { 
    switch (event.sensor.getType()){ 
     case Sensor.TYPE_ACCELEROMETER: 
      System.arraycopy(event.values, 0, gravityData, 0, 3); 
      hasGravityData = true; 
      break; 
     case Sensor.TYPE_MAGNETIC_FIELD: 
      System.arraycopy(event.values, 0, geomagneticData, 0, 3); 
      hasGeomagneticData = true; 
      break; 
     default: 
      return; 
    } 

    if (hasGravityData && hasGeomagneticData) { 
     float identityMatrix[] = new float[9]; 
     float rotationMatrix[] = new float[9]; 
     boolean success = SensorManager.getRotationMatrix(rotationMatrix, identityMatrix, 
      gravityData, geomagneticData); 

     if (success) { 
      float orientationMatrix[] = new float[3]; 
      SensorManager.getOrientation(rotationMatrix, orientationMatrix); 
      float rotationInRadians = orientationMatrix[0]; 
      rotationInDegrees = Math.toDegrees(rotationInRadians); 

      // do something with the rotation in degrees 
     } 
    } 
} 

Я надеюсь, что помогает!

+0

Я очень ценю, что вы нашли время. Тем не менее, я считаю, что ваше объяснение и код используют магнитометр и акселерометр устройства. Я использую отдельное устройство (Sensortag cc2541). Я должен получить магнитное поле и acc от этого устройства. И устройство имеет следующее. В обоих магнитометрах и акселерометре я могу получить 'x'' y' и 'z'. В вашем коде есть функции и методы, которые, вероятно, отсутствуют у моей библиотеки датчиков. ** Я обновил вопрос и добавил методы и функции, которые у меня есть для магнитометра и акселерометра ** – Masster

+0

Так, например, у моей сенсорной библиотеки нет метода getRotationMatrix !!! – Masster

+0

Кроме того, не нужен ли этот метод калибровке? Я имею в виду из кода, который вы предоставили, он автоматически обнаружит Север ?. – Masster

Смежные вопросы