CoreMotion (加速儀與陀螺儀)
主要是使用?CMMotionManager
iOS中的主要傳感器:
@加速度傳感器電子羅盤陀螺儀
功能通過(guò)測(cè)量三個(gè)軸的加速度大小來(lái)判斷人體運(yùn)動(dòng)通過(guò)測(cè)量設(shè)備周圍地磁場(chǎng)的強(qiáng)度和方向來(lái)判斷朝向通過(guò)測(cè)量三個(gè)軸的旋轉(zhuǎn)速率來(lái)判斷朝向
主要局限性受重力干擾大握玛,瞬時(shí)誤差大誤差大亿驾, 容易受其他磁場(chǎng)和金屬物體影響势就。主要用于校正其他設(shè)備誤差會(huì)累積,長(zhǎng)時(shí)間讀數(shù)的準(zhǔn)確性差
應(yīng)用活動(dòng)測(cè)量導(dǎo)航導(dǎo)航
加速儀 (類型:CMAcceleration)
簡(jiǎn)介:
加速儀可以檢測(cè)三維空間中的加速度 ,坐標(biāo)對(duì)應(yīng)如下:
例如:當(dāng)垂直手持手機(jī)且頂部向上格侯,Y坐標(biāo)上回收到 -1G的加速度格仲。
陀螺儀 (類型:CMRotationRate)
簡(jiǎn)介:
陀螺儀用于檢測(cè)設(shè)備繞XYZ軸轉(zhuǎn)動(dòng)的速度,坐標(biāo)對(duì)應(yīng)如下:
deviceMotion
包含下面四種數(shù)據(jù):
attitude(類型:CMAttitude)
返回設(shè)備的方位信息,包含roll 引颈、pitch耕皮、yaw三個(gè)歐拉角的值
roll: 設(shè)備繞 Z 軸轉(zhuǎn)過(guò)的角度
pitch: 設(shè)備繞 X 軸轉(zhuǎn)過(guò)的角度
yaw: 設(shè)備繞 Y 軸轉(zhuǎn)過(guò)的角度
rotationRate(類型:CMRotationRate)
經(jīng)過(guò)濾波操作之后的陀螺儀數(shù)據(jù),即 靜止時(shí)蝙场,三個(gè)方向的轉(zhuǎn)動(dòng)速度接近于0凌停;
gravity(類型:CMAcceleration)
返回重力對(duì)設(shè)備在三個(gè)方向上的加速度
即重力加速度矢量在當(dāng)前設(shè)備的參考坐標(biāo)系中的表達(dá),開發(fā)中不再需要通過(guò)濾波來(lái)提取這個(gè)信息
userAcceleration(類型:CMAcceleration)
返回用戶對(duì)設(shè)備在三個(gè)方向上的加速度
不再需要濾波售滤,但根據(jù)程序需求而加的濾波算法可以保留
示例:
數(shù)據(jù)獲取方式有兩種:主動(dòng)獲确D狻(pull),基于代碼塊獲韧曷帷(push)
主動(dòng)獲取
-(void)viewDidLoad{[superviewDidLoad];// 創(chuàng)建CMMotionManager對(duì)象self.motionManager = [[CMMotionManager alloc] init];// ①// 如果CMMotionManager的支持獲取加速度數(shù)據(jù)if(self.motionManager.accelerometerAvailable){? ? [self.motionManager startAccelerometerUpdates];}else{NSLog(@"該設(shè)備不支持獲取加速度數(shù)據(jù)赐俗!");}// 如果CMMotionManager的支持獲取陀螺儀數(shù)據(jù)if(self.motionManager.gyroAvailable){? ? [self.motionManager startGyroUpdates];}else{NSLog(@"該設(shè)備不支持獲取陀螺儀數(shù)據(jù)!");}// 如果CMMotionManager的支持獲取磁場(chǎng)數(shù)據(jù)if(self.motionManager.magnetometerAvailable){? ? [self.motionManager startMagnetometerUpdates];}else{NSLog(@"該設(shè)備不支持獲取磁場(chǎng)數(shù)據(jù)弊知!");}}-(void)viewWillAppear:(BOOL)animated{[superviewWillAppear:animated];// 啟動(dòng)定時(shí)器來(lái)周期性地輪詢加速度阻逮、陀螺儀、磁場(chǎng)數(shù)據(jù)updateTimer = [NSTimerscheduledTimerWithTimeInterval:0.1target:selfselector:@selector(updateDisplay)? ? userInfo:nilrepeats:YES];// ②}-(void)updateDisplay{// 如果CMMotionManager的加速度數(shù)據(jù)可用if(self.motionManager.accelerometerAvailable){// 主動(dòng)請(qǐng)求獲取加速度數(shù)據(jù)CMAccelerometerData* accelerometerData =self.motionManager.accelerometerData;self.accelerometerLabel.text? = [NSStringstringWithFormat:@"加速度為\n-----------\nX軸: %+.2f\nY軸: %+.2f\nZ軸: %+.2f",? ? ? ? accelerometerData.acceleration.x,? ? ? ? accelerometerData.acceleration.y,? ? ? ? accelerometerData.acceleration.z];}// 如果CMMotionManager的陀螺儀數(shù)據(jù)可用if(self.motionManager.gyroAvailable){// 主動(dòng)請(qǐng)求獲取陀螺儀數(shù)據(jù)CMGyroData* gyroData =self.motionManager.gyroData;self.gyroLabel.text = [NSStringstringWithFormat:@"繞各軸的轉(zhuǎn)速為\n--------\nX軸: %+.2f\nY軸: %+.2f\nZ軸: %+.2f",? ? ? ? gyroData.rotationRate.x,? ? ? ? gyroData.rotationRate.y,? ? ? ? gyroData.rotationRate.z];}// 如果CMMotionManager的磁場(chǎng)數(shù)據(jù)可用if(self.motionManager.magnetometerAvailable){// 主動(dòng)請(qǐng)求獲取磁場(chǎng)數(shù)據(jù)CMMagnetometerData* magnetometerData =self.motionManager.magnetometerData;self.magnetometerLabel.text =? [NSStringstringWithFormat:@"磁場(chǎng)數(shù)據(jù)為\n--------\nX軸: %+.2f\nY軸: %+.2f\nZ軸: %+.2f",? ? ? ? magnetometerData.magneticField .x,? ? ? ? magnetometerData.magneticField .y,? ? ? ? magnetometerData.magneticField .z];}}
結(jié)果如下:
基于代碼塊獲取
self.motionManager = [[CMMotionManager alloc]init];if(_motionManager.isDeviceMotionAvailable) {//更新數(shù)據(jù)頻率_motionManager.deviceMotionUpdateInterval =1/60;? ? ? ? TestViewController * __weakweakSelf =self;NSOperationQueue*queue = [[NSOperationQueuealloc]init];? ? ? ? [_motionManager startDeviceMotionUpdatesToQueue:queue withHandler:^(CMDeviceMotion * _Nullable motion,NSError* _Nullable error) {doubleuserX = motion.userAcceleration.x;doubleuserY = motion.userAcceleration.y;//...[[NSOperationQueuemainQueue] addOperationWithBlock:^{//更新UI}];? ? ? ? }];? ? }
簡(jiǎn)單應(yīng)用
圖片無(wú)論在設(shè)備如何傾斜的情況下都保持水平
RotationViewController * __weakweakSelf =self;if(manager.accelerometerAvailable) {manager.accelerometerUpdateInterval =0.01f;[manager startAccelerometerUpdatesToQueue:[NSOperationQueuemainQueue]? ? ? ? ? ? ? ? ? ? ? ? ? withHandler:^(CMAccelerometerData *data,NSError*error) {doublerotation = atan2(data.acceleration.x, data.acceleration.y) - M_PI;? ? weakSelf.imageView.transform =CGAffineTransformMakeRotation(rotation);}];}
結(jié)果如下:
敲擊手掌的時(shí)候?qū)崿F(xiàn)導(dǎo)航返回
ClunkViewController * __weakweakSelf =self;if(manager.deviceMotionAvailable) {manager.deviceMotionUpdateInterval =0.01f;[manager startDeviceMotionUpdatesToQueue:[NSOperationQueuemainQueue]? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? withHandler:^(CMDeviceMotion *data,NSError*error) {if(data.userAcceleration.x <-2.5f) {? ? ? ? [weakSelf.navigationController popViewControllerAnimated:YES];? ? }}];}
結(jié)果如下:
旋轉(zhuǎn)改變頁(yè)面
doubleshowPromptTrigger =1.0f;doubleshowAnswerTrigger =0.8f;+(double)magnitudeFromAttitude:(CMAttitude *)attitude {returnsqrt(pow(attitude.roll,2.0f) + pow(attitude.yaw,2.0f) + pow(attitude.pitch,2.0f));}FacingViewController * __weakweakSelf =self;if(manager.deviceMotionAvailable) {[manager startDeviceMotionUpdatesToQueue:[NSOperationQueuemainQueue]? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? withHandler:^(CMDeviceMotion *data,NSError*error) {// translate the attitude[data.attitude multiplyByInverseOfAttitude:initialAttitude];// calculate magnitude of the change from our initial attitudedoublemagnitude = [FacingViewController magnitudeFromAttitude:data.attitude];// show the promptif(!showingPrompt && (magnitude > showPromptTrigger)) {? ? ? ? showingPrompt =YES;? ? ? ? PromptViewController *promptViewController = [weakSelf.storyboard instantiateViewControllerWithIdentifier:@"PromptViewController"];? ? ? ? promptViewController.modalTransitionStyle =UIModalTransitionStyleCrossDissolve;? ? ? ? [weakSelf presentViewController:promptViewController animated:YEScompletion:nil];? ? }// hide the promptif(showingPrompt && (magnitude < showAnswerTrigger)) {? ? ? ? showingPrompt =NO;? ? ? ? [weakSelf dismissViewControllerAnimated:YEScompletion:nil];? ? }}];}
結(jié)果如下:
計(jì)算設(shè)備的位移
理論上設(shè)備一開始靜止秩彤,就可以通過(guò)加速度和時(shí)間的值來(lái)計(jì)算設(shè)備的位移夺鲜,(時(shí)間越長(zhǎng) 誤差越大),然是嘗試了一下 做不到呐舔,誤差太大币励,看來(lái)加速計(jì)做不了這么精細(xì)的活。珊拼。