Android API Guides---Motion Sensors
Motion Sensors
Android平台提供了多種感應器,讓你監控裝置的運動。這些感應器的兩個總是基於硬體的(加速度計和陀螺儀),並且可以要麼基於硬體或基於軟體的這三個感應器(重力,線性加速度和旋轉向量感應器)。例如,在某些裝置上的基於軟體的感應器從加速度計和磁力計獲得它們的資料,但在其他裝置也可以使用陀螺儀來匯出他們的資料。大多數Android裝置有一個加速度計,現在許多人包括陀螺儀。基於軟體的感應器的可用性是更加可變的,因為它們通常依賴於一個或一個以上硬體感應器來匯出他們的資料。
動作感應器用於監視裝置的運動,比如傾斜,搖動,旋轉或搖擺有用。運動通常是直接使用者輸入的反射(例如,使用者在遊戲或控制在遊戲中球的使用者操縱汽車),但它也可以是在該裝置所坐的實體環境的反射(例如,與你動,而你開你的車)。在第一種情況下,您正在監視相對於參考裝置的架構或引用您的應用程式架構的議案;在第二種情況下,你正在監測相對於參考世界幀運動。本身動作感應器通常不用於監控裝置的位置,但它們可以與其他感應器,例如地磁場感應器中使用,以確定裝置的相對於參考世界幀位置(更多資訊參見定位感應器)。
所有的動作感應器返回感應器值的多維陣列每個SensorEvent。例如,一個單一的感應器事件期間加速度返回加速度力資料為三個座標軸,和陀螺儀返迴旋轉資料的速率為三個座標軸。這些資料值與其他SensorEvent參數一起float數組(值)返回。表1總結了可用的Andr??oid平台上的動作感應器。
所支援的Andr??oid平台上表1.動作感應器。
感應器感應器事件數目據說明測量單位
TYPE_ACCELEROMETER SensorEvent.values?? [0]沿x軸(包括重力)加速力。米/秒2
沿y軸(包括重力)SensorEvent.values?? [1]加速力。
沿z軸(包括重力)SensorEvent.values?? [2]加速力。
TYPE_GRAVITY SensorEvent.values?? [0]沿x軸的重力的力。米/秒2
SensorEvent.values?? [1]沿y軸的重力的力。
SensorEvent.values?? [2]沿著z軸的重力的力。
TYPE_GYROSCOPE SensorEvent.values?? [0]速率圍繞x軸的旋轉。弧度/秒
SensorEvent.values?? [1]速率繞y軸的旋轉。
SensorEvent.values?? [2]速率圍繞z軸的旋轉。
型陀螺儀無標定感應器Event.values?? [0]速率旋轉(無漂移補償)的繞x軸。弧度/秒
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軸(不包括重力)加速力。米/秒2
SensorEvent.values?? [1]加速沿y軸(不包括重力)的力。
沿z軸(不包括重力)SensorEvent.values?? [2]加速力。
沿x軸TYPE_ROTATION_VECTOR SensorEvent.values?? [0]旋轉向量分量(X * SIN(θ/ 2))。無單位
沿y軸(y * SIN(θ/ 2))SensorEvent.values?? [1]旋轉向量分量。
沿z軸SensorEvent.values?? [2]旋轉向量成分(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標量分量是可選的值。
旋轉向量感應器和重力感應器是用於運動檢測和監測中最常用的感應器。旋轉向量感應器是特別通用,可用於廣泛範圍的運動相關的任務,如檢測的手勢,監測的角度變化,和監測的相對定向的改變。例如,如果你正在開發一個遊戲,增強現實應用,二維或三維羅盤,或相機穩定應用的旋轉向量感應器是理想的。在大多數情況下,使用這些感應器比使用加速度計和地磁感應器或方位感應器更好的選擇。
Android開源項目的感應器
Android開源項目(AOSP)提供了三個基於軟體的動作感應器:重力感應器,線性加速度感應器和旋轉向量感應器。這些感應器中的Andr??oid 4.0更新和現在使用的裝置的陀螺儀(除了其他感應器),以改善穩定性和效能。如果你想嘗試這些感應器,可以通過使用getVendor()方法和getVersion()方法識別它們(供應商是Google公司;版本號碼為3)。由供應商和版本號碼識別這些感應器是必要的,因為Android系統認為這些三個感應器是次要感應器。例如,如果一個裝置製造商提供了其自身的重力感應器,則AOSP重力感應器示出了作為輔助重力感應器。所有這三個感應器依靠一個陀螺儀:如果一個裝置不具有一個陀螺儀,這些感應器沒有顯示出來,並且不能使用。
使用加速度計
加速度感應器測量施加到該裝置的加速度,包括重力的力。下面的代碼展示了如何獲得預設加速度感應器的一個執行個體:
private SensorManager mSensorManager;private Sensor mSensor; ...mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
概念上,加速度感應器確定是通過測量被施加到使用以下關係感應器本身(FS)的力施加到一個裝置(廣告)的加速度:
AD = - ΣFs/質譜
然而,在重力的作用根據以下關係總是影響所測量的加速度:
AD =-g - ΣF/質譜
因為這個原因,當裝置坐在一個表(而不是加速)時,加速計讀取g的大小=9.81米/秒2。類似地,當裝置處於自由下落,並在9.81米/秒2朝向接地因此迅速加快,其加速度計讀出G =0米/ 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];}注意:您可以使用許多不同的技術來過濾感應器資料。上面的程式碼範例使用一個簡單的過濾器常數(阿爾法)來建立一個低通濾波器。此濾波器常數從一個時間常數(t)的,它是延遲的粗略表示該濾波器增加了感應器事件,並且感應器的事件傳遞率(DT)的。該程式碼範例使用的0.8用於示範的alpha值。如果使用這種過濾方法可能需要選擇不同的alpha值。
加速度計使用標準的感應器座標系。在實踐中,這意味著,當一個裝置是在其自然取向的表平放以下條件適用:
如果按下裝置上的左側(所以它移動到右側)中,x加速度值是正的。
如果按下裝置上的底部(因此它移動遠離您),在y加速度值是正的。
如果按下該裝置朝向天空具有A米/秒2的加速度,則Z加速度值等於A + 9.81,其對應於該裝置的加速度(+ A米/秒2)減去重力( - 9.81米/秒2)。
該固定裝置將具有9.81的加速度值,其對應於該裝置的加速度(0米/秒2減去重力的作用,這是-9.81米/秒2)。
一般來說,加速度計,如果要監視裝置的運動一個很好用的感應器。幾乎每一個Android平台的手機和平板電腦有一個加速度計,它使用較少的約10倍的功率比其它動作感應器。一個缺點是,你可能必須實現低通和高通濾波器來消除引力,降低噪音。
Android SDK中提供了一個應用程式範例,展示了如何使用加速度感應器(加速度計播放)。
使用重力感應
重力感應器提供指示的方向和重力的大小的三維向量。下面的代碼展示了如何獲得預設重力感應的一個執行個體:
private SensorManager mSensorManager;private Sensor mSensor;...mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
單位是相同的那些由加速度感應器(米/秒2)中使用,和座標系是與由加速度感應器所使用的。
註:當裝置處於靜止,重力感應器的輸出應該是相同的加速度計的。
使用陀螺儀
陀螺儀測量圍繞一個裝置的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; }}標準陀螺儀提供沒有經過任何過濾或更正雜訊和漂移(偏差)的未經處理資料旋轉。在實踐中,陀螺儀的雜訊和漂移將引入需要被補償的誤差。通常你確定通過監控其它感應器,如重力感應器或加速度計的漂移(偏差)和噪音。
使用未校準陀螺儀
未校正陀螺儀是類似於陀螺儀,除了不陀螺漂移補償被施加到旋轉速率。工廠校準和溫度補償仍施加到旋轉的速率。未校準陀螺儀是後處理和melding方向的資料是有用的。在一般情況下,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);
概念上,該感應器根據以下的關係提供了加速度資料:
線性加速度=加速度 - 重力加速度
當你想獲得加速度資料沒有重力的影響,通常使用此感應器。例如,你可以使用這個感應器來看看你的車有多快。線性加速度感應器總是有位移,您需要刪除。要做到這一點最簡單的方法是建立一個校準步驟到應用程式中。在校準過程中,你可以要求使用者佈建裝置在桌子上,然後讀取位移量所有三個軸。然後,您可以減去從加速度感應器直接讀數偏差獲得實際的線性加速度。
該感應器座標系中是相同的由加速度感應器中所使用的一樣,都是測量單位(米/秒2)。
使用旋轉向量感應器
旋轉向量表示裝置的方向作為角度和一個軸,其中該裝置已通過旋轉角度θ繞軸(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)z*sin(θ/2)
於旋轉軸的方向。
圖1.通過座標旋轉向量感應器使用的系統。
旋轉向量的三個元素是等於一個單位四元數的最後三個組成部分(COS(θ/ 2)中,x * SIN(θ/ 2)中,y * SIN(θ/ 2)中,z * SIN(θ/ 2))。旋轉向量的元素是無單位的。在x,y和z軸都以相同的方式如加速度感應器所定義。參照座標系被定義為一個直接正交基(見圖1)。這個座標系統具有以下特徵:
X定義為向量積Y X Z的是在該裝置的當前位置相切於地面並指出約東。
Y是在該裝置的當前位置相切地朝向地磁北極指向。
朝向天空?點並垂直於地平面。
Android SDK中提供了一個應用程式範例,展示了如何使用旋轉向量感應器。應用程式範例位於API示範代碼(OS - RotationVectorDemo)。
利用重大動作感應器
該顯著動作感應器觸發檢測每次顯著運動事件,然後自行禁用。一個顯著運動,可能導致使用者的位置變化的議案;例如步行,騎單車,或坐在行駛的汽車。下面的代碼示範了如何獲得預設顯著動作感應器的一個執行個體,以及如何註冊一個事件監聽器:
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);欲瞭解更多資訊,請參見觸發事件接聽程式。
使用步驟計數感應器
步進計數器感應器提供的,而在感應器被啟用自上次重啟由使用者所採取的步驟的數目。在步驟計數器有更多的等待時間(最長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);