Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 位移傳感器

位移傳感器

編輯:關於Android編程

Android平台提供了一些傳感器讓你能監測設備的移動。它們中的兩個傳感器總是基於硬件的(加速度和陀螺儀),另外的這類這些傳感器中的3個即能使用基於硬件的也能使用基於軟件的(重力,線性加速度和旋轉矢量傳感器)。例如,一些設備從基於原件的傳感器中獲取加速度和磁強的數據,但另外一些設備也用陀螺儀獲取這些數據。大多數Android設備都有加速度傳感器,很多設備現在也包含陀螺儀傳感器。那些基於軟件的傳感期大多也是可變的,因為它們常常也要依賴於一類或更多類的基於硬件的傳感器去獲得它們需要的數據。

位移傳感器對檢測設備的移動(如傾斜、搖動、旋轉、搖擺等)是有用的。這些動作通常直接反映了用戶的輸入(如用戶游戲中操控汽車,或是用戶在控制游戲中的球),但它也反映了設備所處的物理環境的變化(例如設備隨著你正在駕駛的汽車運動)。在第一種情況下,你監控的運動是相對於設備或應用為參考坐標系的;在第二種情況下,所監控的應用是相對於地球為參考坐標系系的。位移傳感器本身不是主要用來監控設備的位置的,但是他們結合其他傳感器(如地磁傳感器),可用於檢測設備相對於地球參考系的位置。

所有的位移傳感器都會在SensorEvent中返回用多維數組表示的傳感數據。如,在一個加速度傳感器事件中,會返回三維坐標軸上的加速度數據,陀螺儀會返回三維坐標軸上的旋轉速率數據。 這些數據都是隨著SensorEvent參數中以 float 數組的方式返回的。表1總結了Android平台中可用的位移傳感器:

表1. Android平台支持的位移傳感器。

Sensor Sensor event數據 描述 計量單位 TYPE_ACCELEROMETER SensorEvent.values[0] 沿X軸的加速度值(包括重力加速度)。 m/s2   SensorEvent.values[1] 沿Y軸的加速度值(包括重力加速度)。     SensorEvent.values[2] 沿Z軸的加速度值(包括重力加速度)。   TYPE_GRAVITY SensorEvent.values[0] 沿X軸的重力加速度值。 m/s2   SensorEvent.values[1] 沿Y軸的重力加速度值。     SensorEvent.values[2] 沿Z軸的重力加速度值。   TYPE_GYROSCOPE SensorEvent.values[0] 圍繞X軸的旋轉角速度。 rad/s   SensorEvent.values[1] 圍繞Y軸的旋轉角速度     SensorEvent.values[2] 圍繞Z軸的旋轉角速度   TYPE_GYROSCOPE_UNCALIBRATED SensorEvent.values[0] 圍繞X軸的旋轉角速度(沒有漂移補償)。 rad/s   SensorEvent.values[1] 圍繞Y軸的旋轉角速度(沒有漂移補償)。     SensorEvent.values[2] 圍繞Z軸的旋轉角速度(沒有漂移補償)。     SensorEvent.values[3] 圍繞X軸的漂移估值。     SensorEvent.values[4] 圍繞Y軸的漂移估值。     SensorEvent.values[5] 圍繞Z軸的漂移估值。   TYPE_LINEAR_ACCELERATION SensorEvent.values[0] 沿X軸的加速度值(不包括重力加速度)。 m/s2   SensorEvent.values[1] 沿Y軸的加速度值(不包括重力加速度)。     SensorEvent.values[2] 沿Z軸的加速度值(不包括重力加速度)。   TYPE_ROTATION_VECTOR SensorEvent.values[0] 沿X軸的旋轉矢量分量(x * sin(θ/2))。 無單位   SensorEvent.values[1] 沿Y軸的旋轉矢量分量(y * sin(θ/2))。     SensorEvent.values[2] 沿Z軸的旋轉矢量分量(z * sin(θ/2))。     SensorEvent.values[3] 旋轉矢量的度量因子((cos(θ/2))1。   TYPE_SIGNIFICANT_MOTION N/A N/A N/A TYPE_STEP_COUNTER SensorEvent.values[0] 自從上次傳感器被重啟激活後攜帶設備的用戶的所走的步數. 步 TYPE_STEP_DETECTOR N/A N/A N/A

1 度量元素是可選值。

旋轉矢量和重力傳感器是最常用的運動檢測傳感器。在相關運動的任務中,如檢測收拾、角度變化、相對方位的變化等信息,旋轉矢量加速度是是尤其強大的。例如,如果你正在開發游戲、AR應用、二維或三維羅盤、相機防抖應用等,旋轉矢量傳感器對你來說是非常理想的。在大多數情況下,用這些傳感器是比選擇使用加速度和地磁場傳感器或是方向傳感器更理想。

Android開源項目傳感器


Android 開源項目(AOSP)提供了三種基於軟件的位移傳感器:重力、線性加速度和旋轉矢量傳感器。 Android 4.0 中對這些傳感器進行了升級,目前利用陀螺儀來提高穩定性和性能。 如果你想嘗試這些傳感器,你可以用 getVendor() 和 getVersion() 方法來識別它們(制造商為 Google 公司;版本號為3)。通過vendor和version識別這些傳感器是必須的,因為Android系統把這三種傳感器作為備選傳感器。例如,如果設備廠商提供了它們自己的的重力傳感器,那麼AOSP重力傳感器則會顯示它們為備選的重力傳感器。所有這三個傳感器都依賴於陀螺儀:如果設備上沒有提供陀螺儀,這些傳感器都不會顯示出來,用戶也無法使用。

加速度傳感器的使用


加速度傳感器測量設備的加速度,包括重力加速度。以下代碼展示了如何獲取默認加速度傳感器的實例:

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

從概念上來說,加速度傳感器通過測量施於傳感器上的作用力,並按以下關系來檢測設備的加速度(Ad)。
加速度傳感器通過測量施加於傳感器自身的作用力(Fs)來檢測到設備加速度(Ad),公式如下:
Ad = - ∑Fs / mass

然而,重力總是會影響到測量的精度,其公式如下:
Ad = -g - ∑F / mass

基於這個理由,如果設備是平放在桌子上的(沒有加速度),加速度計會讀到g = 9.81 m/s2。 同理,設備在自由落體或以 9.81 m/s2 的加速度墜向地面時,加速度計會讀到 g = 0 m/s2。 因此,要測量設備的真實加速度,必須從加速度數據中移除掉重力加速度的貢獻。可以通過高通過濾器實現它。 反之,低通過濾器則可以用於分離出重力加速度值。下面的例子展示了如果做:

public void onSensorChanged(SensorEvent event){
  // In this example, alpha is calculated as t / (t + dT),
  // where t is the low-pass filter's time-constant and
  // dT is the event delivery rate.

  final float alpha = 0.8;

  // Isolate the force of gravity with the low-pass filter.
  gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
  gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
  gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];

  // Remove the gravity contribution with the high-pass filter.
  linear_acceleration[0] = event.values[0] - gravity[0];
  linear_acceleration[1] = event.values[1] - gravity[1];
  linear_acceleration[2] = event.values[2] - gravity[2];
}

注意: 你可以使用多種不同的技術來過濾傳感器數據。 以上例子只是使用了過濾器常量(alpha)來創建一個低通過濾器。 這個過濾器常量是由時間常量(t)(過濾器事件間隔的粗略表示)和傳感器事件傳送頻率(dt)推導出來的。 使用的0.8僅僅是為了示例的演示,如果你要用這個過濾方法,你可能需要選用另外的 alpha 值。

加速度傳感器使用標准的傳感器坐標系統,事實上,這意味著當設備以自然方向平放在桌子上時,將會適用以下情況:

如果從左側平推設備(向右移動),X軸方向加速度為正值。 如果從下側平推設備(遠離你的方向移動),Y軸方向加速度為正值。 如果以 A m/s2的加速度向空中移動設備,Z方向加速度等於 A + 9.81,即設備加速度(+A m/s2)減去重力加速度(-9.81 m/s2)。 靜止設備的加速度值為 +9.81,即設備加速度(0 m/s2)減去重力加速度(-9.81 m/s2)。

總之,加速度傳感器已足以檢測設備的移動。幾乎所有 Android 手機和平板都帶有加速度傳感器,它的能耗比其它運動傳感器要少10倍。 不過缺點是,你不得不實現低通和高通過濾器去消除重力加速度的影響和減噪。

Android SDK 提供了一個應用示例,展示如何使用加速度傳感器( Accelerometer Play )

重力加速度傳感器的使用


重力傳感器提供了方向和數值上三維矢量。下面的代碼展示了如何獲取默認的重力傳感器的實例:

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

和加速度傳感器具有相同的單位(m/s2)和坐標系。

Note: When a device is at rest, the output of the gravity sensor should be identical to that of the accelerometer.

注意: 當設備靜止時,重力傳感器的輸出應該與加速度傳感器相同。

陀螺儀的使用


陀螺儀以rad/s為單位測量設備圍繞 X, Y, Z軸的旋轉速度。下面的代碼展示了如何獲取默認陀螺儀的實例:

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

陀螺儀的坐標系與加速度傳感器相同。正值表示逆時針方向旋轉,也就是說,從 X、Y、Z 的正軸位置觀看,如果設備已逆時針方向旋轉,正值將會上報, 這是標准的數學意義上的正向旋轉定義,而與方向傳感器定義的轉動不同。

通常,陀螺儀的輸出會被集成到一定的時間上,以便計算在一段不長的時間上旋轉角度的變化。例如:

// Create a constant to convert nanoseconds to seconds.
private static final float NS2S = 1.0f / 1000000000.0f;
private final float[] deltaRotationVector = new float[4]();
private float timestamp;

public void onSensorChanged(SensorEvent event) {
  // This timestep's delta rotation to be multiplied by the current rotation
  // after computing it from the gyro sample data.
  if (timestamp != 0) {
    final float dT = (event.timestamp - timestamp) * NS2S;
    // Axis of the rotation sample, not normalized yet.
    float axisX = event.values[0];
    float axisY = event.values[1];
    float axisZ = event.values[2];

    // Calculate the angular speed of the sample
    float omegaMagnitude = sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ);

    // Normalize the rotation vector if it's big enough to get the axis
    // (that is, EPSILON should represent your maximum allowable margin of error)
    if (omegaMagnitude > EPSILON) {
      axisX /= omegaMagnitude;
      axisY /= omegaMagnitude;
      axisZ /= omegaMagnitude;
    }

    // Integrate around this axis with the angular speed by the timestep
    // in order to get a delta rotation from this sample over the timestep
    // We will convert this axis-angle representation of the delta rotation
    // into a quaternion before turning it into the rotation matrix.
    float thetaOverTwo = omegaMagnitude * dT / 2.0f;
    float sinThetaOverTwo = sin(thetaOverTwo);
    float cosThetaOverTwo = cos(thetaOverTwo);
    deltaRotationVector[0] = sinThetaOverTwo * axisX;
    deltaRotationVector[1] = sinThetaOverTwo * axisY;
    deltaRotationVector[2] = sinThetaOverTwo * axisZ;
    deltaRotationVector[3] = cosThetaOverTwo;
  }
  timestamp = event.timestamp;
  float[] deltaRotationMatrix = new float[9];
  SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector);
    // User code should concatenate the delta rotation we computed with the current rotation
    // in order to get the updated rotation.
    // rotationCurrent = rotationCurrent * deltaRotationMatrix;
   }
}

標准的陀螺儀能夠提供未經過濾的原始旋轉數據,或是經過噪聲及漂移修正的數據。 實際上,噪點和漂移會帶來誤差,這些需要進行相應的補償。 通常你要利用其它傳感器來確定漂移和噪點值,如重力傳感器或加速計。

未校准陀螺儀的使用


除了旋轉速率沒有使用陀螺儀漂移補償外,未校准的陀螺儀和陀螺儀是相似的。工廠校准和溫度補償仍然應用到旋轉速率中。對於後處理和數據融合定位,未校准陀螺儀是有用的 。通常,gyroscope_event.values[0] 的值接近於uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_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_GYROSCOPE_UNCALIBRATED);

線性加速度傳感器的使用


線性加速度用三維矢量表示設備各個坐標軸的加速度(不包括重力加速度)。下面的代碼展示了如果獲取默認線性加速度的實例:

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

概念上,這種傳感器根據下列關系提供加速度數據:

線性加速度 = 加速度 - 重力加速度

這種傳感器的典型用法是你想獲得不受重力加速度影響的加速度數據。
例如,你能夠使用這種傳感器來測量你的汽車運行速度。線性加速度傳感器始終有一個偏移量,你需要移除掉這個偏移量。最簡單的方法就是在你的應用程序中設立一個校准步驟。在校准期間,你可以要求用戶把設備放到桌面上,讀取所有三軸的偏移量,然後從加速度傳感器中讀取的數據中直接減去對應的偏移量,從而獲取真實的線性加速度。

該傳感器的坐標系與加速度傳感器的坐標系相同,其測量單位是(m/s2)。

旋轉矢量傳感器的使用


旋轉矢量用角和軸的組合來代表設備的方向,即設備繞著軸(X、Y或Z)旋轉角度θ。下列代碼顯示了如何獲取默認旋轉矢量傳感器的一個實例:

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

如下描述了旋轉矢量的三個元素:

x*sin(θ/2)
y*sin(θ/2)

其中sin(θ/2)是旋轉矢量的數據,旋轉矢量的方向等於旋轉軸的方向。

這三個旋轉矢量元素等於一個四元數(cos(θ/2),X*sin(θ/2),Y*sin(θ/2),Z*sin(θ/2)的最後三部分。旋轉矢量元素是無單位的。X、Y和Z軸的定義與加速度傳感器相同。該參照坐標系統是用直接正交基來定義的(如圖1)。該坐標系有下面幾個元素:

這裡寫圖片描述

圖1. 旋轉矢量傳感器的坐標系<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCljW4crH08NZIHggWrXEyrjBv7v9tqjS5bXEo6zL/NTayeixuLXEtbHHsM671sPT67XYw+bP4MfQo6yyota4z/K2q7e9o7sgWdbh1NrJ6LG4tbHHsM671sPT67XYw+bP4MfQo6yyota4z/K12LTFs6G1xLGxvKuhoyBa1rjP8szsv9WjrLKi0+u12MPmtLnWsaGjDQo8cD5BbmRyb2lkIFNES9PQ0ru49nNhbXBsZdOm08OjrLjD06bTw9W5yr7By8jnus7KudPD0P3Xqsq4wb+0q7jQxvejrLjDc2FtcGxlzrvT2kFQSSBEZW1vcyBjb2RlICggPGEgaHJlZj0="https://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/os/RotationVectorDemo.html">OS - RotationVectorDemo)。

場景轉移傳感器


每次場景轉移被檢測到後,場景轉移傳感器會觸發一個事件,接著它會禁止掉它自己。場景轉移運動是可能會導致用戶位置改變的一個運動;例如走路,騎自行車,或坐在一個移動的汽車中。下面的代碼展示了如何獲取默認場景轉移傳感器的實例和怎樣注冊一個時間listener:

private SensorManager mSensorManager;
private Sensor mSensor;
private TriggerEventListener mTriggerEventListener;
...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
mTriggerEventListener = new TriggerEventListener() {
    @Override
    public void onTrigger(TriggerEvent event) {
        // Do work
    }
};
mSensorManager.requestTriggerSensor(mTriggerEventListener, mSensor);

更多的信息,參閱TriggerEventListener。

步伐計數傳感器的使用


步伐計數傳感器返回自開機以來活動狀態下用戶的總的運動步數。步計數有更多的延遲(高達10秒),但是比步檢測傳感器更精確。下面的代碼展示了如何獲得默認的步伐計數傳感器的實例:

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

步伐檢測傳感器的使用


步伐檢測傳感器在用戶每走一步時都會觸發一個事件。其延遲理想值在2秒已下。下面的代碼展示了如何獲得默認的步伐檢測傳感器的實例:

private SensorManager mSensorManager;
private Sensor mSensor;
...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved