CoreMotion框架-iOS設備的核心運動

原文地址:http://blog.sina.com.cn/s/blog_7b9d64af0101cu4p.html


爲了防止博主的博文被刪。將內容都複製下來。

我們知道iOS的應用真的太多了,很多應用讓我們驚歎不已!!!很多意想不到的應用!

比如:

1.電子羅盤指南針之類的應用-讓我們知道方向。

2.運動類型軟件-讓我們知道我們跑步多少公里。

3.社交軟件中的搖一搖功能。

4.遊戲中扮演角色類中根據設備的晃動等進行操作。

等等。。而且還有很多應用正在層出不窮的展現再我們面前。


其實,他們多半是使用了iOS中的一個框架-核心運動框架-CoreMotion.framework


CoreMotion.framework框架是做什麼的


我們可以使用iOS提供給我們的CoreMotion 框架來訪問加速度器陀螺儀的相關數據!

它不僅僅提供給你獲得實時的加速度值和旋轉速度值,更重要的是,蘋果在其中集成了很多算法,可以直接給你輸出把重力加速度分量剝離的加速度,省去你的高通濾波操作,以及提供給你一個專門的設備的三維attitude信息!


  

我剛接觸的時候,也是一頭霧水啊。那就普及一下相關的知識。


我們知道,智能手機已經普及到我們日常生活中了,尤其iPhoneiOS設備,也已經相當的普遍(俗稱:街機)。在它的硬件設備中,其實安裝了很多的傳感器。其中的加速度器陀螺儀就是其中的兩種傳感器!


智能機中常見的傳感器

1. 接近傳感器

接近傳感器,顧名思義,就是用來檢測非常接近的目標物體的。這類傳感器通常利用電磁場或者靜電場的改變,或者測量發射的電磁波的反射波的改變,來進行判斷。因爲手段不一樣,所以接近傳感器的目標物體種類也不一樣,有的針對金屬物體,有的針對塑料物體。具體到手機上來說,現在的手機都是使用了新一代的反射光學接近傳感器,可以針對較多種表面類型來檢測。過程很簡單,它們會發出人眼看不到的紅外光,一旦手機來電話了,你肯定會接聽,接聽會導致臉部皮膚離傳感器很近,這樣只需要用光學探測器檢測從皮膚反射回來的光的總量的變化,接近傳感器就檢測到了這個接近。這個傳感結果有什麼用呢?一個明顯的例子,就是可以改進手機的節電功能,比如判斷什麼時候自動打開或關閉顯示屏,鍵盤背光或者觸摸功能,甚至於什麼時候自動關機/待機,取決於設備的主人是正在通話,正在打字,還是就直接把設備扔到口袋中了。這些任務,就由接近傳感器一肩挑了。


2. 加速度傳感器

我個人估計,大家最熟悉的,就是加速度傳感器。由於其帶來了更多的直覺遊戲體驗,基本姿態識別和環境感知功能,這類傳感器從08年開始井噴,因iPhoneiPod的帶動而紅火,因Wii的集成而大規模部署,並由此帶動了價格的下降。現在如果還有哪款手機或者音樂播放器不配備這個傳感器阿,出廠去商店都不好意思和擺在一起的別的設備打招呼。加速度計的原理很簡單,現在手機裏面基本配備的都是3維線傳感器,也就是說,用來測量xyz三個軸上的加速力。加速力就是當物體在加速過程中作用在物體上的力,就好比地球引力,也就是重力。

我爲什麼說大家應該都熟悉加速度傳感器呢,如果用IBM筆記本的朋友就知道,前IBM,現聯想,的Thinkpad系列筆記本,一直都有硬盤保護功能,這個功能利用的就是通過加速度傳感器動態監測出筆記本的震動,並根據這個震動選擇關閉硬盤還是繼續運行。這樣可以最大程度的保護由於振動,比如顛簸的工作環境,或者不小心摔了電腦做造成的硬盤損害,最大程度的保護裏面的數據。類似的一個非常普及的用處就是目前用的數碼相機和攝像機裏,用加速度傳感器,來檢測拍攝時候的手部的振動,並根據這些振動,自動調節相機的聚焦。現在,我們手頭都有iPhoneAndroid軍團,Nokia N900等手機,我們至少都知道,加速度傳感器可以幫助你打遊戲。典型的例子比如Labyrinth2,中文名叫做迷宮滾球。但更廣義地說,加速度傳感器在檢測人的即時背景環境信息上更有用處。比如說,通過三個軸上加速度的變化值的分析處理,手機可以知道你現在是在走路還是騎車還是坐車,是上坡還是下坡,等等。

從理論上講,有了三個軸的加速度立體信息,我們可以推斷出加速方向的信息,比如,你加速騎車的方向,或者你乘坐的電梯正在朝上還是朝下。根據初中數學的知識,這些方向和角度都是可以通過矢量的加減運算算出來的。可惜的是,我們沒法僅僅依靠加速度傳感器來檢測加速方向的角度,也無法得知手機本身的朝向。這是爲什麼呢?要解釋這個,就牽涉到一個困擾加速度儀的大問題,就是重力加速度分量的干擾。

當你的移動設備處於靜止狀態時,加速度計能告訴你它相對於地平面的朝向,這是沒有問題的; 然而,當設備動起來的時候,分析朝向就相當複雜了。這種情況下,要分四種類型討論

  1. 設備處於水平完全靜止或者勻速運動,這時的它會在垂直方向的軸上輸出一個值,那就是重力加速度,接近9.8 。
  2. 設備自由落體的時候,會三個軸都輸出0呢。
  3. 設備靜止或者勻速運動狀態時,但沒有處於絕對水平。此時任何軸都可能有輸出值,但都是重力加速度的分量。一旦處於這種狀態,我們可以通過求分量於三個軸的角度來得知手機旋轉的角度。
  4. 設備沿着任意方向加速。這時,問題就變複雜了,因爲你沒辦法知道設備目前的方向角度信息,所以你根本就不知道重力加速度的分量到底是怎麼分解的,於是……你也就不清楚某個軸所報告的數值,哪些是重力加速度部分,哪些是真正的線性加速度部分

除此之外,另一個加速度傳感器無能爲力的地方,就是純水平旋轉,或者勻速水平變向。

這類運動,加速度傳感器也只會輸出一個值:g。因爲無論是xy,還是z軸,都沒有真正意義上的加速運動。這會帶來什麼問題呢?好比你帶着一個手機在街上走,沿着一條大街走了一段路,這段路的加速度自然是能被採到的。然後你轉彎,在另一條路上走一段,這一段的加速度也是能被採到的。你回到家,拿出手機看數據,沒錯阿,兩端加速度都有,手機知道我走了兩段路,很智能阿,缺少了什麼東西?你轉彎的動作和角度!這個加速度計是採不到的,而這個信息,在很多增強現實的智能應用中,卻是非常有用的。爲了解決這個問題,人們開始引入其他種類的傳感器,比如接下來要介紹的這個陀螺儀。

關於加速度器的座標:

CoreMotion框架-iOS設備的核心運動



3. 陀螺儀

陀螺儀代表着另一個重要的,但可能還需要等待一兩年才能騰飛的傳感器領域,主要是因爲導航級MEMS陀螺儀目前對於手機來說仍然過於昂貴,普通陀螺儀一般廠商都很少看上眼。當然,在iPhone4的帶動下,可以預見的手機軍備競賽,遲早會讓陀螺儀逐漸普及開來。陀螺儀的主要作用,是基於角動量守恆的理論,沿着某個特定的座標軸測量旋轉速率。在使用中,陀螺儀的轉子在高速旋轉時,始終指向一個固定的方向,當運動物體的運動方向偏離預定方向時,陀螺儀就可以感受出來。在現代航空裝備中,飛機駕駛的時候,就是通過多達十多個的陀螺儀來測量機體是否翻滾,以及如何翻滾的。

先來看看iPhone中,陀螺儀硬件吧:

CoreMotion框架-iOS設備的核心運動




再看看,陀螺儀的樣子:

CoreMotion框架-iOS設備的核心運動

 


關於陀螺儀的座標:

CoreMotion框架-iOS設備的核心運動


瞭解一下,關於陀螺儀的座標軸:

Roll軸的信息:

CoreMotion框架-iOS設備的核心運動

Pitch軸的信息:


CoreMotion框架-iOS設備的核心運動


Yaw軸信息:

CoreMotion框架-iOS設備的核心運動


需要注意的是,這裏的三個角度,和加速度計的xyz三維意義完全不同,不要混淆了。


陀螺儀的測量是隨時間累計的,要知道當前的角度,只需要將之前所有的輸出數值積分即可。當然,陀螺儀只會輸出當前旋轉的變化值,比如說,如果一架飛機是以60度的傾斜角度徑直飛行,此時陀螺儀的輸出爲0,因爲當前就沒有機體旋轉。但是,你可以通過之前的輸出累計計算出當前機體傾斜角度是多少。陀螺儀有兩個好處:

  1. 可測頻率比較大,低可以低到直流信號,就是0Hz,高可以高到60-70Hz。這個範圍,基本是根據人類的普遍動作頻率所決定的,而且也考慮了很大的餘量。一般的陀螺儀會對採集到的信號濾波,最終顯示的數據基本是在0-20Hz範圍的。當然,並不是所有陀螺儀都能測量到這個頻率範圍,這個取決於具體的檔次了。
  2. 在設備中的位置並不重要。陀螺儀測量的角速度本質上是慣性角速度,所以你把它放在設備的前端或者後端,輸出的值都會是一樣的,沒有什麼區別。

說完了陀螺儀的優點,說說缺點吧。聰明的讀者在看到陀螺儀計算角度的原理是,肯定能一下就發現陀螺儀的缺陷:這玩意的誤差是累計的!也就是說,某一個時刻你因爲不管什麼樣的原因引進了角度的誤差,可能是靜態漂移誤差,可能是讀數誤差,whatever,這個誤差就會一直跟着你,一直在後面的讀數和計算中延續!更有趣的是,陀螺儀有一個臭名昭著的特性:它會隨着時間而漂移!換句話說,每分每秒,它都會自動引入附加的誤差!!時間一長,完了,你關於旋轉度的測量值就變成了中國有關部門:可信度爲0 。當然,科技是在發展的,現在很多高端的陀螺儀的隨機誤差很小,普通應用有時候都可以不用管這個誤差。當然,一分錢一分貨,這種高端陀螺儀通常都很貴,很少會採用到手機系統中。

這下好玩了,在一個短的時間刻度裏,加速度值噪聲特別大,而且還有重力的影響。在長的時間刻度裏呢,加速度值總體是靠譜的,沒有誤差累計。而在短的時間刻度裏,陀螺儀很準,因爲誤差累計的速度還是很慢的。但在長的時間刻度裏,陀螺儀就不準得離譜。在某些情況下,加速度傳感器可以用來校準陀螺儀,比如設備完全靜止的時候,和重力相關的方向上,就可以這樣做。那麼,什麼時候不行呢?回頭看我們剛纔放的那三個圖,其中yaw的示意圖

yaw角度的變化方向是垂直於重力方向的!所以,通過剛纔關於加速度的介紹我們知道,在這個垂直於重力的平面上,加速度傳感器就沒辦法幫陀螺儀了。

本質上,通過三維加速度傳感器+三維陀螺儀的合作,我們等同於擁有了一個六維的傳感器,但無處不在的誤差會讓這個六維傳感器偶爾感到無助。這時候,我們就需要另外的設備來幫忙做進一步的校正,這就是下面要介紹的電子羅盤。

4. 電子羅盤

電子羅盤,也稱磁力計,或者電子指南針,是繼加速度計之後,從09年開始井噴的一種傳感器。如果我沒記錯的話,最早集成這個傳感器的主流智能手機就是GoogleG1,從這個意義上講,G1對於磁性傳感器市場的帶動作用,可能堪比iPhone對於加速度傳感器的意義。這玩意啥用處?顧名思義,就是告訴你南北極方向的。以前古老的那種指南針,或者叫平面羅盤,可以在你放平羅盤後告訴你南極北極在哪,這樣,你就知道了目前你的正前方在地球這個大平面座標軸上的角度了。當然,出於技術的限制,平面羅盤要求你保持水平,如果有傾斜就不準確了。後來出現的電子羅盤,很多是兩軸的,也就是說,等同於電子平面羅盤。在我記憶中,幾年前的openmoko手機就是集成的這種,所以有同樣的限制。現在高端智能手機裏面集成的都是三維電子羅盤,由於加入了傾角傳感器,可以對羅盤進行傾斜補償,這樣就克服了這個缺陷,可以輸出三維方向上的角度信息。

電子羅盤的原理也很簡單,就是我們物理都學過的霍爾效應。當電流通過一個位於磁場中的導體的時候,磁場會對導體中的電子產生一個橫向的洛倫茲力,電荷因此產生偏轉,偏轉的方向垂直於電流方向和磁場方向,而且正電荷和負電荷偏轉的方向相反,從而在導體的兩端產生電壓差。 這個電壓差也叫霍爾電壓,和兩個因素成比例:電流大小和磁場強度。當然這裏有一個要注意的問題,如果磁場的方向是和導體非垂直的話,實際作用的磁場實際上是原來磁場的一個矢量分量。如何知道這個磁場分量的角度呢?我們可以用兩個或者多個霍爾效應傳感器,相互垂直,這樣的話,磁場的方向就可以通過不同傳感器上霍爾電壓的比例值來求出,這個計算過程只需要知道基本的線性代數運算即可。當然,具體的計算中肯定有一些tricky的地方,不過不是關鍵點,所以這裏就暫時不介紹了。所以和陀螺儀不一樣的是,電子羅盤輸出的是角方向值,而陀螺儀輸出的是角方向的加速度。

所以大家應該都明白了,在電子羅盤的應用中,上述的磁場就是地球磁場,電子羅盤測量地球磁場的矢量值,然後再轉換並表示在系統座標中。在理想情況下,這樣測出來的方向值也是比較準確的,一旦我知道移動設備剛開始的方向值,就能通過之後電子羅盤的輸出,求出該設備接下來的一系列方向改變信息。

不幸的是,這個世界上的理想情況不存在。在我們經常使用移動設備的環境中,有時候會存在除了地球以外的別的,未被有效屏蔽的磁場,這個外加磁場會有很大可能干擾電子羅盤的讀書,而讓結果不可信。而且,如果移動設備周圍有金屬,一旦金屬被磁化,電子羅盤也會受很大的影響。

注:以上文章摘自:移動設備智能化的基石iPhone4的傳感器談起


理論很長。總結一下:目的在於告訴我們,iPhone設備中,集成了很多的傳感器。以及對每一種傳感器進行了分析說明。


看了上面的介紹,相信大家心裏面也都有了數。這些傳感器,各有神通,也各有缺陷,很多時候還真得相互配合來使用,才能達到預期的效果,真正準確檢測出設備主人的行動信息。這個協作的過程比較複雜。但是,我們很多情況下,不需要去了解太多細節,要不,就不用寫代碼了,直接去中科院搞飛機,衛星,導彈去了!爲什麼說,我們不需要明白關於加速度器和陀螺儀的太多的原理性的東西?因爲,底層的實現全部由CorMotion框架給你準備好了!我們只需要來使用框架提供的屬性方法,就可以得到我們想要的信息!


使用CorMotion框架


切回正題,來進行CorMotion框架的使用!


先貼:


self.motionManager = [[CMMotionManager alloc] init];

    

    // 加速度器的檢測

    if ([self.motionManager isAccelerometerAvailable]){

        NSLog(@"Accelerometer is available.");

    } else{

        NSLog(@"Accelerometer is not available.");

    }

    if ([self.motionManager isAccelerometerActive]){

        NSLog(@"Accelerometer is active.");

    } else {

        NSLog(@"Accelerometer is not active.");

    }

    

    // 陀螺儀的檢測

    if([self.motionManager isGyroAvailable]){

        NSLog(@"Gryro is available.");

    } else {

        NSLog(@"Gyro is not available.");

    }

    if ([self.motionManager isGyroActive]){

        NSLog(@"Gryo is active.");

        

    } else {

        NSLog(@"Gryo is not active.");

    }


說明:

1.對加速度器和陀螺儀相關的訪問,都被封裝在CoreMotion.framework框架下的CMMotionManager類中。我們通過使用類的方法,來得到我們想要的加速度數據和陀螺儀數據。

2. isAccelerometerAvailable方法用來查看加速度器是否可用。

3. isAccelerometerAvailable方法用來查看加速度器的狀態:是否Active(啓動)。

4.同理isGyroAvailable方法和isGyroActive方法用來檢測陀螺儀。


用來CMMotionManager獲取加速度的數據


說到獲取加速度器的數據。主要有兩種方式。


1.push方式

這種方式,是實時獲取到Accelerometer的數據,並且用相應的隊列來顯示。即主動。


貼:


// 加速度器的檢測

    if ([self.motionManager isAccelerometerAvailable]){

        NSLog(@"Accelerometer is available.");

        

        NSOperationQueue *queue = [[NSOperationQueue alloc] init];

        

        [self.motionManager startAccelerometerUpdatesToQueue: queue

                                                 withHandler:^(CMAccelerometerData*accelerometerData, NSError *error) {

                                                     

                                                     NSLog(@"X = %.04f, Y = %.04f, Z = %.04f",accelerometerData.acceleration.x, accelerometerData.acceleration.y, accelerometerData.acceleration.z);

            

                                                 }];

        

        

        

    } 


2.pull方式

就是獲取數據,如果要顯示,就要向Accelerometer來索要數據。即:被動的方式。

self.motionManager.accelerometerUpdateInterval = 0.01; // 告訴manager,更新頻率是100Hz

        [self.motionManager startAccelerometerUpdates]; // 開始更新,後臺線程開始運行。



用來CMMotionManager獲取陀螺儀的數據


跟加速度器獲取數據類似,我們來獲取關於陀螺儀的數據


貼:

// 陀螺儀的檢測

    if([self.motionManager isGyroAvailable]){

        NSLog(@"Gryro is available.");

        

        if ([self.motionManager  isGyroActive] == NO){

            [self.motionManager  setGyroUpdateInterval:1.0f / 1.0f];

            NSOperationQueue *queue = [[NSOperationQueue alloc] init];

            [self.motionManager startGyroUpdatesToQueue:queue

                                            withHandler:^(CMGyroData *gyroData, NSError *error) {

                                                NSLog(@"Gyro Rotation x = %.04f", gyroData.rotationRate.x);

                                                NSLog(@"Gyro Rotation y = %.04f", gyroData.rotationRate.y);

                                                NSLog(@"Gyro Rotation z = %.04f", gyroData.rotationRate.z);

                                            }];

            

        }

        

    }else {

        NSLog(@"Gyro is not available.");

    }



希望對你有所幫助!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章