android传感器获取运动方向,Android开发者指南-运动传感器Motion Sensor[原创译文]...
Android
平臺支持很多監測設備運動的傳感器。其中有兩個傳感器一定是基于硬件的(加速度計和陀螺儀),有三個可能基于硬件或軟件(重力計、線性加速計和旋轉向量傳感器)。
比如,某些設備的軟傳感器利用加速度計和磁力計來報送數據,而其它一些設備可能用陀螺儀來報送數據。 大部分 Android
平臺的設備都帶有加速計,有很多現在還帶有陀螺儀。軟傳感器的可用性變數更大一些,因為它們常常依靠一個以上硬件傳感器來報送數據。
運動傳感器對于監測設備的移動非常有用,諸如傾斜、震動、旋轉、搖擺等。
這些動作通常是直觀反映了用戶的輸入(比如用戶在游戲中操縱汽車或者運球),但也可能反映了設備所處的物理環境變化(比如你在開車,設備也隨著移動)。
在第一種場合中,你監測的運動是以設備或應用為參照系;而在第二種場合,運動是以地球為參照系的。
一般情況下,運動傳感器不是用來監測設備的方位的,但它們可以與其他傳感器合作使用,比如地磁傳感器,用于檢測設備的在地球參照系中的方位(詳見
方位傳感器)
所有的運動傳感器都會在 float 數組的方式在參數中返回。表
1 列出了 Android 平臺支持的所有運動傳感器:
表 1.. Android 平臺支持的運動傳感器。
傳感器
傳感器事件數據
說明
測量單位
SensorEvent.values[0]
沿 x 軸的加速度(包括重力)。
m/s2
SensorEvent.values[1]
沿 y 軸的加速度(包括重力)。
SensorEvent.values[2]
沿 z 軸的加速度(包括重力)。
SensorEvent.values[0]
沿 x 軸的重力加速度。
m/s2
SensorEvent.values[1]
沿 y 軸的重力加速度。
SensorEvent.values[2]
沿 z 軸的重力加速度。
SensorEvent.values[0]
圍繞 x 軸的旋轉角速度。
rad/s
SensorEvent.values[1]
圍繞 y 軸的旋轉角速度。
SensorEvent.values[2]
圍繞 z 軸的旋轉角速度。
SensorEvent.values[0]]
沿 x 軸的加速度(不包括重力)。
m/s2
SensorEvent.values[1]
沿 y 軸的加速度(不包括重力)。
SensorEvent.values[2]
沿 z 軸的加速度(不包括重力)。
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。
1 數值部分是可選的。
檢測和監視運動最常用的就是旋轉向量傳感器和重力傳感器。
旋轉向量傳感器尤為強大,在有關運動的任務中用途十分廣泛,諸如檢測手勢、監測角度變化、監測相對方位的變化。
比如,如果你正在開發游戲、增強現實(Augmented
Reality)應用、二維或三維羅盤、相機防抖應用,那么旋轉向量傳感器將十分有用。
在大多數場合,使用這兩個傳感器要比加速度計、磁力傳感器和方向傳感器更加合適。
Android 開源項目傳感器
Android 開源項目(AOSP)提供了三種基于軟件的運動傳感器:重力傳感器、線性加速度傳感器和旋轉向量傳感器。
Android 4.0 中對這三種傳感器進行了升級,目前利用陀螺儀(除了其它傳感器)來增加穩定性和提高性能。
如果你想試試這些傳感器,你可以用 備選傳感器,所以必須用 vendor 和版本號來識別它們。
比如,如果設備制造商已經提供了重力傳感器,則 AOSP 重力傳感器會顯示為備選傳感器。
這三個傳感器都依賴于陀螺儀:如果設備未提供陀螺儀,則它們都不會顯示出來,也無法使用。
加速度傳感器測量設備的加速度,包括重力加速度。以下代碼展示了如何獲取缺省的加速度傳感器的一個實例:
privateSensorManagermSensorManager;privateSensormSensor;...mSensorManager=(SensorManager)getSystemService(Context.SENSOR_SERVICE);mSensor=mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
從概念上說,加速度傳感器通過測量施于傳感器上的作用力,并按以下關系來檢測設備的加速度(Ad)。
Ad = - ∑Fs / mass
然而,重力總是會按以下關系影響測量的精度。
Ad = -g - ∑F / mass
因此,如果設備是平放在桌子上的(沒有加速度),加速度計會讀到g = 9.81 m/s2。
同理,設備在自由落體或以 9.81 m/s2 的加速度墜向地面時,加速度計會讀到 g = 0
m/s2。 因此,要測出設備真實的加速度,必須排除加速計數據中的重力干擾。這可以通過高通濾波器來實現。
反之,低通濾波器則可以用于分離出重力加速度值。以下例程展示了它們的用法:
publicvoidonSensorChanged(SensorEventevent){// 在本例中,alpha 由 t / (t + dT)計算得來,// 其中 t 是低通濾波器的時間常數,dT 是事件報送頻率finalfloatalpha=0.8;// 用低通濾波器分離出重力加速度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];// 用高通濾波器剔除重力干擾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)推導出來的,t 大致等于過濾器觸發傳感器事件的間隔時間。
為了演示,此例程使用 0.8 作為 alpha 的值。如果你要用這個過濾方法,你可能需選用其它的 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 )。
重力傳感器能以三維向量的方式提供重力方向和數量值。以下代碼展示了如何獲取缺省的重力傳感器的一個實例:
privateSensorManagermSensorManager;privateSensormSensor;...mSensorManager=(SensorManager)getSystemService(Context.SENSOR_SERVICE);mSensor=mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
單位與加速度傳感器的一樣(m/s2),坐標系也相同。
注意: 當設備靜止時,重力傳感器的輸出應該與加速度計相同。
陀螺儀測量設備圍繞 x、y、z 軸旋轉的速率,單位是 rad/s。以下代碼展示了如何獲取缺省的陀螺儀的一個實例:
privateSensorManagermSensorManager;privateSensormSensor;...mSensorManager=(SensorManager)getSystemService(Context.SENSOR_SERVICE);mSensor=mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
陀螺儀的 坐標系 與加速度傳感器的相同。逆時針方向旋轉用正值表示,也就是說,從 x、y、z
軸的正向位置觀看處于原始方位的設備,如果設備逆時針旋轉,將會收到正值。
這是標準的數學意義上的正向旋轉定義,而與方向傳感器定義的轉動不同。
通常,陀螺儀的輸出反映了轉動時的角度變化速率。例如:
// 創建常量,把納秒轉換為秒。privatestaticfinalfloatNS2S=1.0f/1000000000.0f;privatefinalfloat[]deltaRotationVector=newfloat[4]();privatefloattimestamp;publicvoidonSensorChanged(SensorEventevent){// 根據陀螺儀采樣數據計算出此次時間間隔的偏移量后,它將與當前旋轉向量相乘。if(timestamp!=0){finalfloatdT=(event.timestamp-timestamp)*NS2S;// 未規格化的旋轉向量坐標值,。floataxisX=event.values[0];floataxisY=event.values[1];floataxisZ=event.values[2];// 計算角速度floatomegaMagnitude=sqrt(axisX*axisX+axisY*axisY+axisZ*axisZ);// 如果旋轉向量偏移值足夠大,可以獲得坐標值,則規格化旋轉向量// (也就是說,EPSILON 為計算偏移量的起步值。小于該值的偏移視為誤差,不予計算。)if(omegaMagnitude>EPSILON){axisX/=omegaMagnitude;axisY/=omegaMagnitude;axisZ/=omegaMagnitude;}// 為了得到此次取樣間隔的旋轉偏移量,需要把圍繞坐標軸旋轉的角速度與時間間隔合并表示。// 在轉換為旋轉矩陣之前,我們要把圍繞坐標軸旋轉的角度表示為四元組。floatthetaOverTwo=omegaMagnitude*dT/2.0f;floatsinThetaOverTwo=sin(thetaOverTwo);floatcosThetaOverTwo=cos(thetaOverTwo);deltaRotationVector[0]=sinThetaOverTwo*axisX;deltaRotationVector[1]=sinThetaOverTwo*axisY;deltaRotationVector[2]=sinThetaOverTwo*axisZ;deltaRotationVector[3]=cosThetaOverTwo;}timestamp=event.timestamp;float[]deltaRotationMatrix=newfloat[9];SensorManager.getRotationMatrixFromVector(deltaRotationMatrix,deltaRotationVector);// 為了得到旋轉后的向量,用戶代碼應該把我們計算出來的偏移量與當前向量疊加。// rotationCurrent = rotationCurrent * deltaRotationMatrix;}}
標準的陀螺儀能夠提供未經過濾的原始旋轉數據,或是經過噪聲及漂移修正的數據。
實際生活中,陀螺儀的噪聲和漂移都會引入誤差,這是需要補償的。
通常你要利用其它傳感器來確定漂移和噪聲值,比如重力傳感器或加速計。
線性加速度傳感器能向你提供一個三維向量,表示延著三個坐標軸方向的加速度,但不包括重力加速度。
以下代碼展示了如何獲取缺省的線性加速度傳感器的一個實例:
privateSensorManagermSensorManager;privateSensormSensor;...mSensorManager=(SensorManager)getSystemService(Context.SENSOR_SERVICE);mSensor=mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
理論上說,這個傳感器基于以下公式給出加速度數據:
線性加速度 = 加速度 - 重力加速度
這個傳感器的典型應用是獲取去除了重力干擾的加速度數據。比如,你可以用這個傳感器來獲取汽車加速度。
線性加速度傳感器總是會有些偏差,你需要把這個偏差值抵消掉。最簡單的消除方式就是在你的應用中增加一個校準的環節。
在校準過程中,你可以要求用戶先把設備放在桌子上,再來讀取三個坐標軸的偏差值。
然后你就可以從傳感器的讀數中減去這個偏差值,以獲取真實的線性加速度。
傳感器 坐標系 與加速度傳感器使用的相同,單位也一樣(m/s2)。
旋轉向量代表了設備的方位,由角度和坐標軸信息組成,包含了設備圍繞坐標軸(x、y、z)旋轉的角度θ。
以下代碼展示了如何獲取缺省的旋轉向量傳感器的一個實例:
privateSensorManagermSensorManager;privateSensormSensor;...mSensorManager=(SensorManager)getSystemService(Context.SENSOR_SERVICE);mSensor=mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
旋轉向量的三個元素用以下方式表示:
x*sin(θ/2)
y*sin(θ/2)
z*sin(θ/2)
旋轉向量的大小等于 sin(θ/2),方向等于旋轉軸的方向。
圖 1. 旋轉向量傳感器的坐標系。
旋轉向量的三個元素等于四元組的后三個部分(cos(θ/2)、x*sin(θ/2)、y*sin(θ/2)、z*sin(θ/2)),沒有單位。
x、y、z 軸的定義與加速度傳感器的相同。坐標參照系定義為直接正交基(參見圖 1)。 這個坐標系具有以下特點:
X 定義為向量積 Y x Z。它是以設備當前位置為切點的地球切線,方向朝東。
Y 是以設備當前位置為切點的地球切線,指向地磁北極。
Z 與地平面垂直,指向天空。
Android SDK 提供了一個示例應用,展示了旋轉向量傳感器的使用方法。 示例應用在 API Demos 中(
OS - RotationVectorDemo )。
總結
以上是生活随笔為你收集整理的android传感器获取运动方向,Android开发者指南-运动传感器Motion Sensor[原创译文]...的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: GS009音箱收音机功能
- 下一篇: 电源插头三个怎么区分(2023年1月电脑
