轉自 http://blog.csdn.net/a345017062/article/details/6459643
陀螺儀就是內部有一個陀螺,它的軸由於陀螺效應始終與初始方向平行,這樣就可以通過與初始方向的偏差計算出實際方向。手機里陀螺儀實際上是一個結構非常精密的芯片,內部包含超微小的陀螺。
加速計是用來檢測手機受到的加速度的大小和方向的,而手機靜置的時候是只受到重力加速度(這個高中學過)的.所以很多人把加速計功能又叫做重力感應功能。
磁力計是測試磁場強度和方向的。
陀螺儀測量是參考標准是內部中間在與地面垂直的方向上進行轉動的陀螺。通過設備與陀螺的夾角得到結果。
加速計是以內部測量組件在各個方向上的受力情況來得到結果。
磁力計的原理就是中學物理中涉及到的那個最簡單的指南針了(那記得那根被磁化的鋼針么)。
它們分別有自己的強項:
陀螺儀的強項在於測量設備自身的旋轉運動。對設備自身運動更擅長。但不能確定設備的方位。
加速計的強項在於測量設備的受力情況。對設備相對外部參考物(比如,地面)的運動更擅長。但用來測量設備相對於地面的擺放姿勢,則精確度不高。
磁力計的強項在於定位設備的方位。可以測量出當前設備與東南西北四個方向上的夾角。
舉幾個例子:
陀 螺儀對設備旋轉角度的檢測是瞬時的而且是非常精確的,能滿足一些需要高分辨率和快速反應的應用比如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 & lt; 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
