加速計和陀螺儀

前言

最近因為工作需要對加速計和陀螺儀進(jìn)行學(xué)習(xí)和了解,過程中有所收獲。

正文

一、加速計

iPhone在靜止時會受到地球引力,以屏幕中心為坐標(biāo)原點,建立一個三維坐標(biāo)系(如右圖),此時iPhone收到的地球引力會分布到三個軸上。
iOS開發(fā)者可以通過CoreMotion框架獲取分布到三個軸的值。如果iPhone是如圖放置,則分布情況為x=0,y=-1.0,z=0
在CoreMotion中地球引力(重力)的表示為1.0。

手機(jī)如果屏幕朝上的放在水平桌面上,此時的(x,y,z)分布是什么?


上面答案是(0,0, -1.0);

如何檢測手機(jī)的運動?
CoreMotion框架中有CMDeviceMotion類,其中的gravity屬性用來描述前面介紹的重力;另外的userAcceleration是用來描述手機(jī)的運動。
當(dāng)手機(jī)不動時,userAcceleration的(x, y, z)為(0, 0, 0);
當(dāng)手機(jī)運動,比如在屏幕水平朝上的自由落體時,檢測到的(x, y, z)將為(0, 0, 1);
當(dāng)手機(jī)屏幕水平朝上,往屏幕左邊以9.8m/s2的加速度運動時,檢測到的(x, y, z)將為(1, 0, 0);

1、gravity是固定不變,因為地球引力的不變;但是xyz的分布會變化,收到手機(jī)朝向的影響;
2、userAcceleration是手機(jī)的運動相關(guān)屬性,但是檢測到的值為運動加速度相反的方向;
3、一種理解加速計的方式:在水平的路上有一輛車,車上有一個人;當(dāng)車加速向右運動時,人會向左傾斜;此時可以人不需要知道外面的環(huán)境如何,根據(jù)事先在車?yán)锝⒑玫姆较蜃鴺?biāo)系,可以知道車在向右加速運動。

二、加速計的簡單應(yīng)用

圖片懸浮
手機(jī)旋轉(zhuǎn),但是圖片始終保持水平。


實現(xiàn)流程
1、加載圖片,創(chuàng)建CMMotionManager;
2、監(jiān)聽地球重力的變化,根據(jù)x和y軸的重力變化計算出來手機(jī)與水平面的夾角;
3、將圖片逆著旋轉(zhuǎn)相同的角度;

x、y軸和UIKit坐標(biāo)系相反,原點在屏幕中心,向上為y軸正方向,向右為x軸正方向,屏幕朝外是z軸正方向;
在處理圖片旋轉(zhuǎn)角度時需要注意。

三、陀螺儀

如圖,建立三維坐標(biāo)系;
陀螺儀描述的是iPhone關(guān)于x、y、z軸的旋轉(zhuǎn)速率;
靜止時(x, y, z)為(0, 0, 0);
當(dāng)右圖手機(jī)繞Y軸正方向旋轉(zhuǎn),速率為每秒180°,則(x, y, z)為(0, 0, 3.14);


陀螺儀和加速計是同樣的坐標(biāo)系,但是新增了旋轉(zhuǎn)的概念,可以用右手法則來輔助記憶;
陀螺儀回調(diào)結(jié)構(gòu)體的單位是以弧度為單位,這個不是加速度而是速率;

四、CoreMotion的使用

CoreMotion的使用有兩種方式 :

  • 1、Push方式:設(shè)置間隔,由manager不斷回調(diào);
self.motionManager = [[CMMotionManager alloc] init];
self.motionManager.deviceMotionUpdateInterval = 0.2;
[self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]
                                                withHandler:^(CMDeviceMotion * _Nullable motion, NSError * _Nullable error) {

}];
  • 2、Pull方式:啟動監(jiān)聽,自定義定時器,不斷讀取manager的值;
self.motionManager = [[CMMotionManager alloc] init];
self.motionManager.deviceMotionUpdateInterval = 0.2;
[self.motionManager startDeviceMotionUpdates];
// self.motionManager.deviceMotion 后續(xù)通過這個屬性可以直接讀取結(jié)果

iOS系統(tǒng)在監(jiān)聽到運動信息的時候,需要把信息回調(diào)給開發(fā)者,方式就有push和pull兩種;
push 是系統(tǒng)在規(guī)定的時間間隔,不斷的回調(diào);
pull 是由開發(fā)則自己去讀取結(jié)果值,但同樣需要設(shè)定一個更新頻率;
兩種方式的本質(zhì)并無太大區(qū)別,都需要設(shè)置回調(diào)間隔,只是讀取方式的不同;
在不使用之后(比如說切后臺)要關(guān)閉更新,這是非常耗電量的操作。

五、demo實踐

基于加速計,做了一個小游戲,邏輯不復(fù)雜詳見具體代碼,分享幾個處理邏輯:

  • 1、圓球的邊界處理;(以球和右邊界的碰撞為例)
if (self.ballView.right > self.gameContainerView.width) {
        self.ballView.right = self.gameContainerView.width;
        self.ballSpeedX /= -1;
    }
  • 2、圓球是否觸碰目標(biāo)的檢測;
- (BOOL)checkTarget {
    CGFloat disX = (self.ballView.centerX - self.targetView.centerX);
    CGFloat disY = (self.ballView.centerY - self.targetView.centerY);
    return sqrt(disX * disX + disY * disY) <= (kConstBallLength / 2 + kConstTargetLength / 2);
}
  • 3、速度的平滑處理;
static CGFloat lySlowLowPassFilter(NSTimeInterval elapsed,
                            GLfloat target,
                            GLfloat current) {
    return current + (4.0 * elapsed * (target - current));
}

總結(jié)

加速計和陀螺儀的原理復(fù)雜但使用簡單,實際應(yīng)用也比較廣。
之前就用過加速計和陀螺儀,但是沒有系統(tǒng)的學(xué)習(xí)過。在完整的學(xué)習(xí)一遍之后,我才知道原來加速計的單位是以重力加速度(9.8 m/s2)為標(biāo)準(zhǔn)單位,陀螺儀的數(shù)據(jù)僅僅是速率,單位是弧度每秒。
上面的小游戲代碼地址在Github。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容