陀螺儀就是內部有一個陀螺,它的軸由於陀螺效應始終與初始方向平行,這樣就可以通過與初始方向的偏差計算出實際方向。手機裡陀螺儀實際上是一個結構非常精密的晶片,內部包含超微小的陀螺。
加速計是用來檢測手機受到的加速度的大小和方向的,而手機靜置的時候是只受到重力加速度(這個高中學過)的.所以很多人把加速計功能又叫做重力感應功能。
磁力計是測試磁場強度和方向的。
陀螺儀測量是參考標準是內部中間在與地面垂直的方向上進行轉動的陀螺。通過裝置與陀螺的夾角得到結果。
加速計是以內部測量組件在各個方向上的受力情況來得到結果。
磁力計的原理就是中學物理中涉及到的那個最簡單的指南針了(那記得那根被磁化的鋼針麼)。
它們分別有自己的強項:
陀螺儀的強項在於測量裝置自身的旋轉運動。對裝置自身運動更擅長。但不能確定裝置的方位。
加速計的強項在於測量裝置的受力情況。對裝置相對外部參考物(比如,地面)的運動更擅長。但用來測量裝置相對於地面的擺放姿勢,則精確度不高。
磁力計的強項在於定位裝置的方位。可以測量出當前裝置與東南西北四個方向上的夾角。
舉幾個例子:
陀螺儀對裝置旋轉角度的檢測是瞬時的而且是非常精確的,能滿足一些需要高解析度和快速反應的應用比如FPS遊戲的瞄準。而且陀螺儀配合加速計可以在沒有衛星和網路的情況下進行導航,這是陀螺儀的經典應用。加速度計可用於有固定的重力參考座標系、存線上性或傾斜運動但旋轉運動被限制在一定範圍內的應用。同時處理直線運動和旋轉運動時,就需要把加速度和陀螺儀計結合起來使用。如果還想裝置在運動時不至於迷失方向,就再加上磁力計。
對於一個發射出去的飛彈來說,要想精確追蹤並調整飛彈的軌道的話,下面幾組資料必不可少:
GPS定位它的位置
加速計測量當前加速度
磁力計確定飛彈頭的方向(只能知道東南西北四個方向上的夾角),陀螺儀知道飛彈的角速度。這兩個儀器結合才能確定飛彈的準確的立體運動方向。
加速計得到的結果就是XYZ三個值,分別代表三個方向的加速度。關於XYZ三值的介紹,可以看這裡:
android 重力感應和旋轉螢幕關係
http://blog.csdn.net/lzx_bupt/archive/2010/04/20/5507165.aspx
用加速計和磁力計可以計算出orientation(方位計),orientation涉及到了三個概念:
Roll:左右傾斜角度,也叫滾轉角 http://baike.baidu.com/view/1769672.htm
Pitch:前後傾斜,也叫俯仰角 http://baike.baidu.com/view/3832041.htm
Yaw:左右搖擺,也叫偏航角 http://baike.baidu.com/view/1769448.htm
下面代碼是Android2.3中/development/samples/Compass的源碼,示範了如何使用加速計和磁力計來確定手機的擺放姿勢和方位。因為手機運動的加速度不高,精確度也沒有太大的要求,用加速計替代陀螺儀也可以。但如果做一些精度比較高的遊戲的話,最好還是有陀螺儀。
//開啟加速計和磁力計兩個感應器。Sensor gsensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);Sensor msensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);mSensorManager.registerListener(this, gsensor, SensorManager.SENSOR_DELAY_GAME);mSensorManager.registerListener(this, msensor, SensorManager.SENSOR_DELAY_GAME);//加速計資料。private float[] mGData = new float[3];//磁力計資料。private float[] mMData = new float[3];//旋轉矩陣(rotation matrix),用於計算手機自身相對於地面座標系的旋轉角度。比如手機現在是橫著還是豎著的。反映的是手機的立體擺放位置。這個資料最好用陀螺儀來測量,沒有陀螺儀的話,藉助於加速計和重力加速度也可以,只是精度不夠強罷了。private float[] mR = new float[16];//傾斜矩陣(inclination matrix),用於計算手機方位。比如手機的頭部現在朝南還是朝北。是針對一個平面上的東南西北四個方向而言的。private float[] mI = new float[16];//存放最終的旋轉角度資料private float[] mOrientation = new float[3];public void onSensorChanged(SensorEvent event) { int type = event.sensor.getType(); float[] data; if (type == Sensor.TYPE_ACCELEROMETER) { data = mGData; } else if (type == Sensor.TYPE_MAGNETIC_FIELD) { data = mMData; } else { // we should not be here. return; } for (int i = 0; i < 3; i++) data[i] = event.values[i];//這一步的目的是擷取mR和mI兩個矩陣。 SensorManager.getRotationMatrix(mR, mI, mGData, mMData);//用矩陣mR擷取手機的旋轉角度。 SensorManager.getOrientation(mR, mOrientation);//用矩陣mI擷取手機在東南西北四個方向上的夾角。 float incl = SensorManager.getInclination(mI); final float rad2deg = (float)(180.0f / Math.PI); Log.d("Compass", "yaw: " + (int)(mOrientation[0] * rad2deg) + " pitch: " + (int)(mOrientation[1] * rad2deg) + " roll: " + (int)(mOrientation[2] * rad2deg) + " incl: " + (int)(incl * rad2deg));}
補充於2011.7.14
gsensor的較正比較容易完成,一般是讓機器以某個固定角度(比如水平)放置,然後連續取N個值(比如20個)進行一系列計算。Android和iphone中,螢幕會隨著裝置的旋轉方向變化而改變,其實應用的只是gsensor。
msensor的較正分為水平較正和傾斜補償。水平較正有平面較正、8字較正、十面較正等幾種方法。經過水平較正後,msensor在水平放置時已經可以使用了,但裝置與水平面有一定的傾斜角時,這個傾斜角會對msensor的精度造成影響。因此,還需要進行傾斜角補償較正。先通過較正好的gsensor得出傾斜角,然後使用傾斜角(pitch,roll)進行補償較正計算。
orientation sensor可以由一個單獨晶片來實現,也可以由gsensor和msensor共同計算出來的(我看android2.3的Sample中的Compass就已經這樣幹了)。orientation sensor輸出三個值:roll,pitch,yaw。其中,roll和pitch分別代表手機的X軸和Y軸與水平面的夾角,所以這兩個值可以由gsensor計算出來。yaw代表手機y軸水平面上的投影與正北方向的夾角,由msensor計算出來。
陀螺儀可以捕捉很微小的運動軌跡變化,因此可以做高解析度和快速反應的旋轉檢測。但不能像msensor或orientation sensor那樣測量當前的運行方向。飛機當中就用它記錄運動角度改變,從而形成運動軌跡。缺點就是隨著時間增長會有誤差積累,
補充於2011.7.19
陀螺儀的XYZ分別代表裝置圍繞XYZ三個軸旋轉的角速度:radians/second。至於XYZ使用的座標系與gsensor相同。逆時針方向旋轉時,XYZ的值是正的。下面是使用陀螺儀進行開發時的示範代碼:
private static final float NS2S = 1.0f / 1000000000.0f;private float timestamp;public void onSensorChanged(SensorEvent event){ if (timestamp != 0) { final float dT = (event.timestamp - timestamp) * NS2S; angle[0] += event.data[0] * dT; angle[1] += event.data[1] * dT; angle[2] += event.data[2] * dT; } timestamp = event.timestamp;}
另外,陀螺儀運轉一段時間以後,noise和offset會導致資料偏差,需要藉助其它感應器進行較正。
補充於2011.7.20
利用加速計(gsensor),磁力計(msensor)類比出方位感應器(orientation)來
Android最近的新版本已經不建議我們在開發的時候像下面這樣直接用方位感應器了:
Sensor ori = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
mSensorManager.registerListener(this, ori, SensorManager.SENSOR_DELAY_GAME);
而是建議使用SensorManager.getOrientation(mR, mOrientation)這個API自己在應用程式的onSensorChanged中計算出方位感應器。但我們在做HAL層時,卻不得不考慮一些APK還是像上面代碼那樣直接使用方位感應器的情況,所以,我們必須在sensor.c中類比出一個方位感應器來:
啟用方位感應器時,同時啟用加速計和磁力計,關閉方位感應器時也要同時關閉加速計和磁力計,同時還要考慮如果使用者註冊了加速計或磁力計,並且正在使用的情況。
//預設狀態,0代表關閉。static int accStatus = 0;static int magStatus = 0;static int switchSensor(int fd, int handle, int enabled) {int status = 0;switch (handle) {case ID_ACCELERATION:if (enabled) {if (!accStatus) {//=0說明目前狀態是關閉時,執行開啟操作。否則,說明已經開啟過。status = ioctl(fd, ACC_FLAG, 1);LOGW("open gsensor");}accStatus++;} else {if (accStatus > 0) {//>0說明目前狀態是開啟,這個時候才會嘗試關閉gsensor。accStatus--;if (!accStatus) {//減1後如果==0,說明orientation沒有使用gsensor,可以關閉gsensor了status = ioctl(fd, ACC_FLAG, 0);LOGW("close gsensor");}}}break;case ID_MAGNETIC:if (enabled) {if (!magStatus) {status = ioctl(fd, MAG_FLAG, 1);LOGW("open msensor");}magStatus++;} else {if (magStatus > 0) {magStatus--;if (!magStatus) {status = ioctl(fd, MAG_MFLAG, 0);LOGW("close msensor");}}}break;case ID_ORIENTATION:if (enabled) {if (!accStatus) {//=0說明gsensor沒有開啟過,直接開啟。status = ioctl(fd, ACC_AFLAG, 1);LOGW("open msensor");}if (!magStatus) {status = ioctl(fd, MAG_FLAG, 1);LOGW("open msensor");}accStatus++;magStatus++;} else {if (accStatus > 0) {//>0說明被開啟過,嘗試關閉gsensor。accStatus--;if (!accStatus) {//減1後=0說明使用者沒有直接使用gsensor,只是使用了orientation,可以關閉gsensor了。status = ioctl(fd, ACC_AFLAG, 0);LOGW("close gsensor");}}if (magStatus > 0) {magStatus--;if (!magStatus) {status = ioctl(fd, MAG_FLAG, 0);LOGW("close msensor");}}}break;default:LOGW("unsupported sensor type");}return status;}
參考文章:
加速度計和陀螺儀的區別
http://www.cnblogs.com/liuq0s/archive/2010/09/02/1816394.html
三軸陀螺儀與加速度計如何輔助Iphone定位的
http://www.weizhiquan.com/archives/1072
ST整合感應器方案實現電子羅盤功能
http://www.eeworld.com.cn/gykz/2011/0408/article_5352.html
Android裝置中實現陀螺儀(Orientation Sensor)
http://blog.csdn.net/beeboobeeboo/article/details/6536941
簡單易懂的文字 帶你認識iPhone 4陀螺儀
http://mobile.zol.com.cn/187/1876651.html
Android作業系統11種感應器介紹
http://hi.baidu.com/aokikyon/blog/item/f9a539d74a4f5fc4a044df40.html