來說說CoreMotion

關(guān)于CoreMotion

Core Motion可以讓開發(fā)者從各個內(nèi)置傳感器那里獲取未經(jīng)修改的傳感數(shù)據(jù),并觀測或響應設(shè)備各種運動和角度變化翩概。這些傳感器包括陀螺儀、加速器和磁力儀(羅盤)返咱。

CoreMotion負責處理的數(shù)據(jù)

它包含幾種類型的數(shù)據(jù)钥庇,這些類都是CMLogItem類的子類:

  • 加速度數(shù)據(jù) :CMAccelerometerData
typedef struct {
   double x;
   double y;
   double z;
} CMAcceleration;
@interface CMAccelerometerData : CMLogItem
{
@private
   id _internal;
}
//加速度的數(shù)據(jù)對象
@property(readonly, nonatomic) CMAcceleration acceleration;
@end
  • 螺旋儀數(shù)據(jù) :CMGyroData
typedef struct {
   double x;
   double y;
   double z; 
} CMRotationRate;
@interface CMGyroData : CMLogItem
{
@private
   id _internal;
}
//螺旋儀數(shù)據(jù)對象
@property(readonly, nonatomic) CMRotationRate rotationRate;
@end
  • 磁感應數(shù)據(jù) :magnetometerData
typedef struct {
   double x;
   double y;
   double z;
} CMMagneticField;
@interface CMMagnetometerData : CMLogItem
{
@private
   id _internal;
}
//磁力對象
@property(readonly, nonatomic) CMMagneticField magneticField;
@end
  • 前三種數(shù)據(jù)通過復雜運算得到的設(shè)備的運動數(shù)據(jù) :CMDeviceMotion
@interface CMDeviceMotion : CMLogItem
{
@private
   id _internal;
}
//設(shè)備的狀態(tài)對象
@property(readonly, nonatomic) CMAttitude *attitude;
//設(shè)備的角速度
@property(readonly, nonatomic) CMRotationRate rotationRate;
//設(shè)備的重力加速度
@property(readonly, nonatomic) CMAcceleration gravity;
//用戶嫁給設(shè)備的加速度 設(shè)備的總加速度為重力加速度叫上用戶給的加速度
@property(readonly, nonatomic) CMAcceleration userAcceleration;
//設(shè)備的磁場矢量對象
@property(readonly, nonatomic) CMCalibratedMagneticField magneticField NS_AVAILABLE(NA,5_0);

我們來看下 attitude 這個對象, 它又封裝了許多設(shè)備的狀態(tài)屬性

@interface CMAttitude : NSObject <NSCopying, NSSecureCoding>
{
@private
   id _internal;
}
//設(shè)備的歐拉角roll
@property(readonly, nonatomic) double roll;
//設(shè)備的歐拉角pitch
@property(readonly, nonatomic) double pitch;
//設(shè)備的歐拉角yaw
@property(readonly, nonatomic) double yaw;
//設(shè)備狀態(tài)的旋轉(zhuǎn)矩陣
@property(readonly, nonatomic) CMRotationMatrix rotationMatrix;
//設(shè)備狀態(tài)的四元數(shù)
@property(readonly, nonatomic) CMQuaternion quaternion;
@end

CoreMotion的使用

CoreMotion中獲取數(shù)據(jù)主要是兩種方式:

  • 一種是Push咖摹,就是你提供一個線程管理器NSOperationQueue评姨,再提供一個Block,這樣萤晴,CoreMotion自動在每一個采樣數(shù)據(jù)到來的時候回調(diào)這個Block吐句,進行處理。在這中情況下店读,block中的操作會在你自己的主線程內(nèi)執(zhí)行嗦枢。

  • 一種是 Pull,在這個方式里屯断,你必須主動去像CMMotionManager要數(shù)據(jù)文虏,這個數(shù)據(jù)就是最近一次的采樣數(shù)據(jù)侣诺。你不去要,CMMotionManager就不會給你氧秘。當然年鸳,在這種情況下,CoreMotion所有的操作都在自己的后臺線程中進行丸相,不會有任何干擾你當前線程的行為阻星。

有兩點需要注意:第一就是需要檢測是否可用,第二就是在不需要的時候已添,停止更新數(shù)據(jù)。蘋果建議在使用CoreMotionManager的時候采用單例模式滥酥。

我們以CMAccelerometerData為例更舞,其他方式都是一樣的

pull獲取方式

if ([_motionManager isAccelerometerAvailable]) {    
   // 設(shè)置加速計采樣頻率
   [_motionManager setAccelerometerUpdateInterval:1 / 40.0];
   [_motionManager startAccelerometerUpdates];
}else {
   NSLog(@"設(shè)備不支持加速計");
}

//可以寫個定時器去定時主動獲取數(shù)據(jù)
//獲取數(shù)據(jù)
CMAcceleration acceleration=_motionManager.accelerometerData.acceleration;
NSLog(@"%f---%f---%f",acceleration.x,acceleration.y,acceleration.z);

push獲取方式

//判斷加速計是否可用
if([_motionManager isAccelerometerAvailable]) {
   // 設(shè)置加速計頻率
   [_motionManager setAccelerometerUpdateInterval:1 / 40.0];
   //開始采樣數(shù)據(jù)
   [_motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
       NSLog(@"%f---%f",accelerometerData.acceleration.x,accelerometerData.acceleration.y);
   }];
} else{
   NSLog(@"設(shè)備不支持加速計");
}

我們再列舉幾個它的其他屬性和方法:

@interface CMMotionManager : NSObject
{
@private
   id _internal;
}
//設(shè)置加速度傳感器更新幀率
@property(assign, nonatomic) NSTimeInterval accelerometerUpdateInterval __TVOS_PROHIBITED;
//加速度傳感器是否可用
@property(readonly, nonatomic, getter=isAccelerometerAvailable) BOOL accelerometerAvailable __TVOS_PROHIBITED;
//加速度傳感器是否激活
@property(readonly, nonatomic, getter=isAccelerometerActive) BOOL accelerometerActive __TVOS_PROHIBITED;
//加速度傳感器數(shù)據(jù)對象
@property(readonly, nullable) CMAccelerometerData *accelerometerData __TVOS_PROHIBITED;
//pull方式開始更新加速度數(shù)據(jù)
- (void)startAccelerometerUpdates __TVOS_PROHIBITED;
//push方式更新加速度數(shù)據(jù)
- (void)startAccelerometerUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMAccelerometerHandler)handler __TVOS_PROHIBITED;
//停止更新加速度數(shù)據(jù)
- (void)stopAccelerometerUpdates __TVOS_PROHIBITED;
//設(shè)備狀態(tài)更新幀率
@property(assign, nonatomic) NSTimeInterval deviceMotionUpdateInterval __TVOS_PROHIBITED;
//參考器枚舉
+ (CMAttitudeReferenceFrame)availableAttitudeReferenceFrames NS_AVAILABLE(NA,5_0) __TVOS_PROHIBITED;
@property(readonly, nonatomic) CMAttitudeReferenceFrame attitudeReferenceFrame NS_AVAILABLE(NA,5_0) __TVOS_PROHIBITED;
//設(shè)備運動信息是否可用
@property(readonly, nonatomic, getter=isDeviceMotionAvailable) BOOL deviceMotionAvailable __TVOS_PROHIBITED;
//設(shè)備運動信息是否激活
@property(readonly, nonatomic, getter=isDeviceMotionActive) BOOL deviceMotionActive __TVOS_PROHIBITED;
//設(shè)備運動信息對象
@property(readonly, nullable) CMDeviceMotion *deviceMotion __TVOS_PROHIBITED;
//pull方式開始刷新運動信息
- (void)startDeviceMotionUpdates __TVOS_PROHIBITED;
//push方式開始刷新運動信息
- (void)startDeviceMotionUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMDeviceMotionHandler)handler __TVOS_PROHIBITED;
//使用某個參考系
- (void)startDeviceMotionUpdatesUsingReferenceFrame:(CMAttitudeReferenceFrame)referenceFrame NS_AVAILABLE(NA,5_0) __TVOS_PROHIBITED;
//push方式開始刷新設(shè)備運動信息
- (void)startDeviceMotionUpdatesUsingReferenceFrame:(CMAttitudeReferenceFrame)referenceFrame toQueue:(NSOperationQueue *)queue withHandler:(CMDeviceMotionHandler)handler NS_AVAILABLE(NA,5_0) __TVOS_PROHIBITED;
//停止刷新設(shè)備運動信息
- (void)stopDeviceMotionUpdates __TVOS_PROHIBITED;

關(guān)于CMDeviceMotion

我們都知道,設(shè)備靜止時受到的地球引力為1g坎吻,1g是物體在地球的海平面上受到的下拉力(9.8米/秒2)缆蝉。假如設(shè)備從高處掉落,其加速計測量到的加速度將為0g瘦真。假如設(shè)備水平放在桌面上刊头,則加速計測量出的加速度為1g,且方向朝上诸尽。

加速計測量3個軸(x原杂、y和z)上的值,如圖所示:


這個軸在方向上有些不同于傳統(tǒng)坐標軸您机,考慮以下實際情況:

1g重力的分布情況是:y=-1.0


1g重力的分布情況是:x=1.0

1g重力的分布情況是:z=-1.0

1g重力的分布情況是:x= 0.707穿肄,y=-0.707

1g重力的分布情況是:y=-0.707,z= 0.707

僅當設(shè)備的朝向相對于重力的方向發(fā)生變化時际看,加速計才能檢測到咸产;要同時檢測設(shè)備的朝向和運動數(shù)據(jù),就需要用到陀螺儀了仲闽。當查詢設(shè)備的陀螺儀時脑溢,它將報告設(shè)備繞x, y, z軸的旋轉(zhuǎn)速度,單位為弧度/秒赖欣;2弧度相當于一整圈屑彻,因此陀螺儀返回讀數(shù)2表示設(shè)備繞相應的軸每秒轉(zhuǎn)一圈。

有兩種方式訪問設(shè)備的朝向和運動數(shù)據(jù)畏鼓,一種是通過UIDevice請求朝向通知酱酬,另一種是利用框架Core Motion定期地直接訪問加速計和陀螺儀數(shù)據(jù)。

  • 通過UIDevice請求朝向通知

雖然可直接查詢加速計并使用它返回的值判斷設(shè)備的朝向云矫,但Apple為開發(fā)人員簡化了這項工作膳沽。單例UIDevice表示當前設(shè)備,它包含方法beginGeneratingDeviceOrientationNotifications,該方法命令iOS將朝向通知發(fā)送到通知中心(NSNotificationCenter)挑社。啟動通知后陨界,就可以注冊一個NSNotificationCenter實例,以便設(shè)備的朝向發(fā)生變化時自動調(diào)用指定的方法痛阻。

通過訪問UIDevice的屬性orientation來獲得設(shè)備當前朝向菌瘪,該屬性的類型為枚舉值

UIDeviceOrientation,有6個預定義值:
UIDeviceOrientationFaceUp — 設(shè)備正面朝上
UIDeviceOrientationFaceDown — 設(shè)備正面朝下
UIDeviceOrientationPortrait — 縱向(Home鍵在下)
UIDeviceOrientationPortraitUpsideDown — 縱向倒轉(zhuǎn)(Home鍵在上)
UIDeviceOrientationLandscapeLeft — Home鍵在左邊的橫向
UIDeviceOrientationLandscapeRight — Home鍵在右邊的橫向

- (void)viewDidLoad
{
   [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

   [[NSNotificationCenter defaultCenter] addObserver:selfselector:@selector(orientationChanged:) name:@"UIDeviceOrientationDidChangeNotification"object:nil];

   [super viewDidLoad];
}

- (void)orientationChanged:(NSNotification *)notification
{
  UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
  NSLog(@"當前朝向枚舉數(shù)字值:%d",orientation);

  switch (orientation) {
    case UIDeviceOrientationPortrait:
      self.lblOriention.text = @"Portrait";
      break;
    case UIDeviceOrientationPortraitUpsideDown:
      self.lblOriention.text = @"Portrait Upside Down";
      break;
    case UIDeviceOrientationLandscapeLeft:
      self.lblOriention.text = @"Landscape Left";
      break;
    case UIDeviceOrientationLandscapeRight:
      self.lblOriention.text = @"Landscape Right";
      break;
    case UIDeviceOrientationFaceUp:
      self.lblOriention.text = @"Face Up";
      break;
    case UIDeviceOrientationFaceDown:
      self.lblOriention.text = @"Face Down";
      break;
    default:
      self.lblOriention.text = @"Unknown";
      break;
   }
}
  • 使用Core Motion讀取加速計和陀螺儀數(shù)據(jù)

利用UIDevice只能判斷極端朝向阱当,應用程序經(jīng)常要獲悉這些朝向之間的過渡狀態(tài)俏扩,如設(shè)備處于某個傾斜位置。Core Motion運動管理器讓您能夠指定從加速計和陀螺儀那里接收更新的頻率(單位為秒)弊添,還讓您能夠直接指定一個處理程序塊(handle block)录淡,每當更新就緒時都將執(zhí)行該處理程序塊。

實際加速度在Core Motion里被分解成了兩部分:Gravity和UserAcceleration油坝。Gravity代表重力1g在設(shè)備的分布情況嫉戚,UserAcceleration代表設(shè)備運動中的加速度分布情況。將這兩者相加就等于實際加速度澈圈。Gravity的三個軸所受的重力加起來始終等于1g彬檀,而UserAcceleration取決于單位時間內(nèi)動作的幅度大小。

CMRotationRate的X瞬女,Y,Z分別代表三個軸上的旋轉(zhuǎn)速率窍帝,單位為弧度/秒。旋轉(zhuǎn)速度為1弧度/秒诽偷,意味著設(shè)備每秒旋轉(zhuǎn)半圈盯桦。這里復習一下弧度與角度的轉(zhuǎn)換:

1角度 = π/180 弧度

1弧度 = 180/π角度

360角度 = 360 * π/180 = 2π弧度 = 一整圈

CMAttitude的三個屬性Yaw,Pitch和Roll分別代表左右擺動、俯仰以及滾動渤刃∮德停可以將設(shè)備想象成一架飛機,下面的gif圖演示了各種運動狀態(tài):

Yaw的運動狀態(tài):

yaw.gif

Pitch的運動狀態(tài):

pitch.gif

Roll的運動狀態(tài):

roll.gif

實例

下面的代碼實現(xiàn)了這樣一個界面卖子,通過CMMotionManager返回了設(shè)備的各個狀態(tài)值:

#import "ViewController.h"


@interface ViewController ()

@property (strong, nonatomic) IBOutlet UILabel *lblYaw;
@property (strong, nonatomic) IBOutlet UILabel *lblPitch;
@property (strong, nonatomic) IBOutlet UILabel *lblRoll;

@property (strong, nonatomic) IBOutlet UILabel *lblAccelerometerX;
@property (strong, nonatomic) IBOutlet UILabel *lblAccelerometerY;
@property (strong, nonatomic) IBOutlet UILabel *lblAccelerometerZ;

@property (strong, nonatomic) IBOutlet UILabel *lblGravityX;
@property (strong, nonatomic) IBOutlet UILabel *lblGravityY;
@property (strong, nonatomic) IBOutlet UILabel *lblGravityZ;

@property (strong, nonatomic) IBOutlet UILabel *lblRotationRateX;
@property (strong, nonatomic) IBOutlet UILabel *lblRotationRateY;
@property (strong, nonatomic) IBOutlet UILabel *lblRotationRateZ;

@property (strong, nonatomic) CMMotionManager *motionManager;

- (IBAction)motionSwitchHandler:(id)sender;

@end

@implementation ViewController

- (void)viewDidLoad
{
   [super viewDidLoad];

   self.motionManager = [[CMMotionManager alloc] init];
   self.motionManager.deviceMotionUpdateInterval = 1.0f/10.0f; //1秒10次
}

- (void)controlHardware
{
   [self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
       //Acceleration
       if(fabs(motion.userAcceleration.x)>1.3f)
           self.lblAccelerometerX.text = [NSString stringWithFormat:@"%.2f",motion.userAcceleration.x];
       if(fabs(motion.userAcceleration.y)>1.3f)
           self.lblAccelerometerY.text = [NSString stringWithFormat:@"%.2f",motion.userAcceleration.y];
       if(fabs(motion.userAcceleration.z)>1.3f)
           self.lblAccelerometerZ.text = [NSString stringWithFormat:@"%.2f",motion.userAcceleration.z];
       //Gravity
       self.lblGravityX.text = [NSString stringWithFormat:@"%.2f",motion.gravity.x];
       self.lblGravityY.text = [NSString stringWithFormat:@"%.2f",motion.gravity.y];
       self.lblGravityZ.text = [NSString stringWithFormat:@"%.2f",motion.gravity.z];
       //yaw,pitch,roll
       self.lblYaw.text = [NSString stringWithFormat:@"%.2f",motion.attitude.yaw];
       self.lblPitch.text = [NSString stringWithFormat:@"%.2f",motion.attitude.pitch];
       self.lblRoll.text = [NSString stringWithFormat:@"%.2f",motion.attitude.roll];
       //Gyroscope's rotationRate(CMRotationRate)
       self.lblRotationRateX.text = [NSString stringWithFormat:@"%.2f",motion.rotationRate.x];
       self.lblRotationRateY.text = [NSString stringWithFormat:@"%.2f",motion.rotationRate.y];
       self.lblRotationRateZ.text = [NSString stringWithFormat:@"%.2f",motion.rotationRate.z];
   }];
}

- (IBAction)motionSwitchHandler:(id)sender
{
   UISwitch *motionSwitch = (UISwitch *)sender;
   if(motionSwitch.on)
   {
       [self controlHardware];
   }
   else
   {
       [self.motionManager stopDeviceMotionUpdates];
   }
}

- (void)didReceiveMemoryWarning
{
   [super didReceiveMemoryWarning];
   // Dispose of any resources that can be recreated.
}
@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末略号,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子洋闽,更是在濱河造成了極大的恐慌玄柠,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诫舅,死亡現(xiàn)場離奇詭異羽利,居然都是意外死亡,警方通過查閱死者的電腦和手機刊懈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門这弧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來娃闲,“玉大人,你說我怎么就攤上這事匾浪』拾铮” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵蛋辈,是天一觀的道長属拾。 經(jīng)常有香客問我,道長冷溶,這世上最難降的妖魔是什么渐白? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮逞频,結(jié)果婚禮上礼预,老公的妹妹穿的比我還像新娘。我一直安慰自己虏劲,他們只是感情好,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布褒颈。 她就那樣靜靜地躺著柒巫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪谷丸。 梳的紋絲不亂的頭發(fā)上堡掏,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音刨疼,去河邊找鬼泉唁。 笑死,一個胖子當著我的面吹牛揩慕,可吹牛的內(nèi)容都是我干的亭畜。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼迎卤,長吁一口氣:“原來是場噩夢啊……” “哼拴鸵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蜗搔,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤劲藐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后樟凄,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體聘芜,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年缝龄,在試婚紗的時候發(fā)現(xiàn)自己被綠了汰现。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挂谍。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖服鹅,靈堂內(nèi)的尸體忽然破棺而出凳兵,到底是詐尸還是另有隱情,我是刑警寧澤企软,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布庐扫,位于F島的核電站,受9級特大地震影響仗哨,放射性物質(zhì)發(fā)生泄漏形庭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一厌漂、第九天 我趴在偏房一處隱蔽的房頂上張望萨醒。 院中可真熱鬧,春花似錦苇倡、人聲如沸富纸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽晓褪。三九已至,卻和暖如春综慎,著一層夾襖步出監(jiān)牢的瞬間涣仿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工示惊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留好港,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓米罚,卻偏偏與公主長得像钧汹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子录择,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 版本記錄 前言 我們的app很多都需要獲取使用者的動作崭孤、方向以及其他和方位或者位置有關(guān)的參數(shù),在ios中對應的框架...
    刀客傳奇閱讀 2,661評論 0 3
  • 前言 現(xiàn)在大部分的智能移動設(shè)備通過自動旋轉(zhuǎn)糊肠,能夠自動切換去呈現(xiàn)最適合當前屏幕顯示的內(nèi)容辨宠,無疑大大提升了使用者的用戶...
    BladeWayne閱讀 9,956評論 2 54
  • 獲取設(shè)備的移動事件 當我們移動,晃動货裹,或者傾斜手機的時候嗤形,這些動作都會被設(shè)備的硬件捕獲。其實每一個動都都會在 X,...
    xiao333ma閱讀 2,030評論 1 3
  • 我們先簡單了解一下弧圆,加速計可以用來干嘛赋兵。我們下次有時間再繼續(xù)講解陀螺儀的使用笔咽,以下,我們只能使用真機測試霹期,系統(tǒng)提供...
    Raybon_lee閱讀 4,364評論 2 10
  • 猜猜運用以下哪個傳感器:點這里下載(下載了,記得點星星,謝謝!) 傳感器的...
    在逃科學家閱讀 2,262評論 0 1