【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)

猜你喜欢

转载自blog.51cto.com/4789781/2126356