【Sensors】位置傳感器(4)


Android平臺提供兩種傳感器,可讓您確定設備的位置:地磁場傳感器和加速度計。Android平臺還提供了一個傳感器,通過該傳感器可以確定設備的臉部距離物體有多近(稱爲接近傳感器)。地磁場傳感器和接近傳感器是基於硬件的。大多數手機和平板電腦製造商都包含地磁場傳感器。類似地,手機製造商通常包括接近傳感器以確定手持機何時靠近用戶的臉部(例如,在電話呼叫期間)。爲了確定設備的方向,您可以使用設備的加速度計和地磁場傳感器的讀數。

注意:方向傳感器在Android 2.2(API級別8)中不推薦使用,方向傳感器類型在Android 4.4W(API級別20)中已棄用。

位置傳感器可用於確定設備在世界參照系中的物理位置。例如,您可以將地磁場傳感器與加速度計結合使用,以確定設備相對於磁北極的位置。您還可以使用這些傳感器來確定應用程序參考框架中設備的方向。位置傳感器通常不用於監視設備的運動或運動,例如搖晃,傾斜或推力(有關更多信息,請參閱運動傳感器)。

地磁場傳感器和加速計返回每個傳感器值的多維數組SensorEvent。例如,地磁場傳感器在單個傳感器事件期間爲三個座標軸中的每一個提供地磁場強度值。同樣,加速計傳感器測量傳感器事件期間施加到設備的加速度。有關傳感器使用的座標系的更多信息,請參閱 傳感器座標系。接近傳感器爲每個傳感器事件提供單個值。表1總結了Android平臺上支持的位置傳感器。

表1. Android平臺支持的位置傳感器。
【Sensors】位置傳感器(4)
1此傳感器在Android 2.2(API級別8)中已棄用,此傳感器類型已在Android 4.4W(API級別20)中棄用。傳感器框架提供了獲取設備方向的替代方法,這些方法在計算設備的方向中討論。

2一些接近傳感器僅提供代表近和遠的二進制值。

使用遊戲旋轉矢量傳感器


遊戲旋轉矢量傳感器是相同的 旋轉矢量傳感器,除了它不使用地磁場。因此Y軸不指向北,而是指向其他參考。允許該參考值與陀螺儀圍繞Z軸漂移相同的數量級漂移。

由於遊戲旋轉矢量傳感器不使用磁場,因此相對旋轉更準確,而不受磁場變化的影響。如果你不關心北方的位置,那麼在遊戲中使用這個傳感器,由於它依賴於磁場,正常的旋轉矢量並不適合你的需求。

以下代碼顯示如何獲取默認遊戲旋轉矢量傳感器的實例:

private SensorManager mSensorManager;
private Sensor mSensor;
...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);

使用地磁旋轉矢量傳感器


地磁旋轉矢量傳感器是類似於 旋轉矢量傳感器,但它使用磁力,而不是一個陀螺儀的。該傳感器的精度低於正常的旋轉矢量傳感器,但功耗降低。如果您想要在背景中收集一些旋轉信息而不消耗太多電量,請僅使用此傳感器。與配料一起使用時,此傳感器非常有用。

以下代碼顯示如何獲取默認地磁旋轉矢量傳感器的實例:

private SensorManager mSensorManager;
private Sensor mSensor;
...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR);

計算設備的方向


通過計算設備的方向,您可以監視設備相對於地球參照系(特別是磁北極)的位置。以下代碼顯示如何計算設備的方向

private SensorManager mSensorManager;
...
// Rotation matrix based on current readings from accelerometer and magnetometer.
final float[] rotationMatrix = new float[9];
mSensorManager.getRotationMatrix(rotationMatrix, null,
  accelerometerReading, magnetometerReading);

// Express the updated rotation matrix as three orientation angles.
final float[] orientationAngles = new float[3];
mSensorManager.getOrientation(rotationMatrix, orientationAngles);

系統通過將設備的地磁場傳感器與設備的加速度計結合使用來計算方位角。使用這兩個硬件傳感器,系統爲以下三個方向角度提供數據:

  • 方位角(圍繞-z軸的旋轉角度)。這是設備當前指南針方向和磁北極之間的角度。如果設備的頂部邊緣朝向磁北,則方位角爲0度; 如果頂部邊緣朝南,則方位角爲180度。類似地,如果頂部邊緣朝東,則方位角是90度,並且如果頂部邊緣朝向西部,則方位角是270度。
  • 間距(圍繞x軸的旋轉角度)。這是平行於設備屏幕的平面與平行於地面的平面之間的角度。如果將設備平行於地面,且底邊距離您最近,並將設備的頂部邊緣朝地面傾斜,則俯仰角度爲正值。以相反的方向傾斜 - 將設備的頂部邊緣移離地面 - 導致俯仰角變爲負值。值的範圍是-180度到180度。
  • 滾動(繞y軸的旋轉角度)。這是垂直於設備屏幕的平面與垂直於地面的平面之間的角度。如果您將設備平行於地面並且底邊靠近您,並將設備的左邊朝向地面傾斜,則滾動角度會變爲正值。向相反的方向傾斜 - 將設備的右側邊緣朝向地面移動 - 導致滾動角度變爲負值。值的範圍是-90度到90度。

注意:傳感器的滾動定義已經改變,以反映絕大多數在地理傳感器生態系統中的實現。

請注意,這些角度與航空中使用的不同座標系有關(偏航,俯仰和俯仰)。在航空系統中,x軸沿着飛機的長邊,從尾部到鼻子。

定位傳感器通過處理來自加速度計和地磁場傳感器的原始傳感器數據來導出其數據。由於涉及到繁重的處理,定向傳感器的準確度和精度會降低。具體而言,該傳感器僅在滾動角度爲0時纔可靠。結果,在Android 2.2(API等級8)中取消了方向傳感器,並且在Android 4.4W(API等級20)中取消了方向傳感器類型。如下面的代碼示例所示,我們建議您不要使用方向傳感器中的原始數據,而是getRotationMatrix() 結合該 getOrientation()方法來計算方位值。作爲這個過程的一部分,你可以使用 remapCoordinateSystem() 方法將方向值轉換爲應用程序的參考框架。

public class SensorActivity extends Activity implements SensorEventListener {

  private SensorManager mSensorManager;
  private final float[] mAccelerometerReading = new float[3];
  private final float[] mMagnetometerReading = new float[3];

  private final float[] mRotationMatrix = new float[9];
  private final float[] mOrientationAngles = new float[3];

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
  }

  @Override
  public void onAccuracyChanged(Sensor sensor, int accuracy) {
    // Do something here if sensor accuracy changes.
    // You must implement this callback in your code.
  }

  @Override
  protected void onResume() {
    super.onResume();

    // Get updates from the accelerometer and magnetometer at a constant rate.
    // To make batch operations more efficient and reduce power consumption,
    // provide support for delaying updates to the application.
    //
    // In this example, the sensor reporting delay is small enough such that
    // the application receives an update before the system checks the sensor
    // readings again.
    mSensorManager.registerListener(this, Sensor.TYPE_ACCELEROMETER,
      SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
    mSensorManager.registerListener(this, Sensor.TYPE_MAGNETIC_FIELD,
      SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
  }

  @Override
  protected void onPause() {
    super.onPause();

    // Don't receive any more updates from either sensor.
    mSensorManager.unregisterListener(this);
  }

  // Get readings from accelerometer and magnetometer. To simplify calculations,
  // consider storing these readings as unit vectors.
  @Override
  public void onSensorChanged(SensorEvent event) {
    if (event.sensor == Sensor.TYPE_ACCELEROMETER) {
      System.arraycopy(event.values, 0, mAccelerometerReading,
        0, mAccelerometerReading.length);
    }
    else if (event.sensor == Sensor.TYPE_MAGNETIC_FIELD) {
      System.arraycopy(event.values, 0, mMagnetometerReading,
        0, mMagnetometerReading.length);
    }
  }

  // Compute the three orientation angles based on the most recent readings from
  // the device's accelerometer and magnetometer.
  public void updateOrientationAngles() {
    // Update rotation matrix, which is needed to update orientation angles.
    mSensorManager.getRotationMatrix(mRotationMatrix, null,
      mAccelerometerReading, mMagnetometerReading);

    // "mRotationMatrix" now has up-to-date information.

    mSensorManager.getOrientation(mRotationMatrix, mOrientationAngles);

    // "mOrientationAngles" now has up-to-date information.
  }
}

除了將傳感器的座標系轉換爲應用程序的參照系外,通常不需要執行任何數據處理或過濾設備的原始方位角。

使用地磁場傳感器


地磁場傳感器可以監測地球磁場的變化。以下代碼顯示如何獲取默認地磁場傳感器的實例:

private SensorManager mSensorManager;
private Sensor mSensor;
...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

該傳感器爲三個座標軸中的每一個提供原始場強數據(以μT爲單位)。通常,您不需要直接使用此傳感器。相反,您可以使用旋轉矢量傳感器來確定原始旋轉運動,或者可以使用加速度計和地磁場傳感器結合該getRotationMatrix()方法來獲得旋轉矩陣和傾斜矩陣。然後,您可以使用這些矩陣getOrientation() 和getInclination()方法來獲得方位角和地磁傾角數據。

注意:測試您的應用程序時,您可以通過以數字8模式揮舞設備來提高傳感器的準確性。

使用未校準的磁力計


未經校準的磁力計與地磁場傳感器相似,只是未對磁場施加硬鐵校準。工廠校準和溫度補償仍然適用於磁場。未經校準的磁力計對於處理壞的硬鐵估算很有用。一般來說,geomagneticsensor_event.values[0] 會接近uncalibrated_magnetometer_event.values[0] - uncalibrated_magnetometer_event.values[3]。那是,

calibrated_x ~= uncalibrated_x - bias_estimate_x

注意:未校準的傳感器可提供更多的原始結果,並可能包含一些偏差,但其測量值包含的校正中應用的校正的跳躍更少。有些應用程序可能更喜歡這些未校準的結果,因爲它們更平滑,更可靠。例如,如果應用程序試圖進行自己的傳感器融合,引入校準實際上可能會扭曲結果。

除了磁場之外,未校準的磁力計還提供了每個軸的估計硬鐵偏差。以下代碼顯示如何獲取默認未校準磁強計的實例:

private SensorManager mSensorManager;
private Sensor mSensor;
...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED);

使用接近傳感器


接近傳感器可以確定物體離設備有多遠。以下代碼顯示如何獲取默認接近傳感器的實例:

private SensorManager mSensorManager;
private Sensor mSensor;
...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);

接近傳感器通常用於確定人的頭部離手機設備的距離(例如,當用戶正在撥打或接聽電話時)。絕大多數接近傳感器以釐米爲單位返回絕對距離,但有些僅返回近值和遠值。以下代碼顯示如何使用接近傳感器:

public class SensorActivity extends Activity implements SensorEventListener {
  private SensorManager mSensorManager;
  private Sensor mProximity;

  @Override
  public final void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // Get an instance of the sensor service, and use that to get an instance of
    // a particular sensor.
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    mProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
  }

  @Override
  public final void onAccuracyChanged(Sensor sensor, int accuracy) {
    // Do something here if sensor accuracy changes.
  }

  @Override
  public final void onSensorChanged(SensorEvent event) {
    float distance = event.values[0];
    // Do something with this sensor data.
  }

  @Override
  protected void onResume() {
    // Register a listener for the sensor.
    super.onResume();
    mSensorManager.registerListener(this, mProximity, SensorManager.SENSOR_DELAY_NORMAL);
  }

  @Override
  protected void onPause() {
    // Be sure to unregister the sensor when the activity pauses.
    super.onPause();
    mSensorManager.unregisterListener(this);
  }
}

注意:一些接近傳感器返回代表“接近”或“遠”的二進制值。在這種情況下,傳感器通常會報告遠端狀態下的最大量程值和近端狀態下的較小值。通常,遠值是大於5釐米的值,但是這可能因傳感器而異。您可以使用該getMaximumRange()方法確定傳感器的最大範圍。

你也應該閱讀

  • 傳感器
  • 傳感器概述
  • 運動傳感器
  • 環境傳感器
  • AccelerometerPlay示例

    Lastest Update:2018.04.24

聯繫我

QQ:94297366
微信打賞:https://pan.baidu.com/s/1dSBXk3eFZu3mAMkw3xu9KQ

公衆號推薦:

【Sensors】位置傳感器(4)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章