CoreMotion (加速仪与陀螺仪)
CoreMotion (加速仪与陀螺仪)
主要是使用 CMMotionManager
iOS中的主要传感器:
@加速度传感器电子罗盘陀螺仪
功能通过测量三个轴的加速度大小来判断人体运动通过测量设备周围地磁场的强度和方向来判断朝向通过测量三个轴的旋转速率来判断朝向
主要局限性受重力干扰大,瞬时误差大误差大, 容易受其他磁场和金属物体影响。主要用于校正其他设备误差会累积,长时间读数的准确性差
应用活动测量导航导航
加速仪 (类型:CMAcceleration)
简介:
加速仪可以检测三维空间中的加速度 ,坐标对应如下:
例如:当垂直手持手机且顶部向上,Y坐标上回收到 -1G的加速度。
陀螺仪 (类型:CMRotationRate)
简介:
陀螺仪用于检测设备绕XYZ轴转动的速度,坐标对应如下:
deviceMotion
包含下面四种数据:
attitude(类型:CMAttitude)
返回设备的方位信息,包含roll 、pitch、yaw三个欧拉角的值
roll: 设备绕 Z 轴转过的角度
pitch: 设备绕 X 轴转过的角度
yaw: 设备绕 Y 轴转过的角度
rotationRate(类型:CMRotationRate)
经过滤波操作之后的陀螺仪数据,即 静止时,三个方向的转动速度接近于0;
gravity(类型:CMAcceleration)
返回重力对设备在三个方向上的加速度
即重力加速度矢量在当前设备的参考坐标系中的表达,开发中不再需要通过滤波来提取这个信息
userAcceleration(类型:CMAcceleration)
返回用户对设备在三个方向上的加速度
不再需要滤波,但根据程序需求而加的滤波算法可以保留
示例:
数据获取方式有两种:主动获取(pull),基于代码块获取(push)
主动获取
-(void)viewDidLoad{[superviewDidLoad];// 创建CMMotionManager对象self.motionManager = [[CMMotionManager alloc] init];// ①// 如果CMMotionManager的支持获取加速度数据if(self.motionManager.accelerometerAvailable){ [self.motionManager startAccelerometerUpdates];}else{NSLog(@"该设备不支持获取加速度数据!");}// 如果CMMotionManager的支持获取陀螺仪数据if(self.motionManager.gyroAvailable){ [self.motionManager startGyroUpdates];}else{NSLog(@"该设备不支持获取陀螺仪数据!");}// 如果CMMotionManager的支持获取磁场数据if(self.motionManager.magnetometerAvailable){ [self.motionManager startMagnetometerUpdates];}else{NSLog(@"该设备不支持获取磁场数据!");}}-(void)viewWillAppear:(BOOL)animated{[superviewWillAppear:animated];// 启动定时器来周期性地轮询加速度、陀螺仪、磁场数据updateTimer = [NSTimerscheduledTimerWithTimeInterval:0.1target:selfselector:@selector(updateDisplay) userInfo:nilrepeats:YES];// ②}-(void)updateDisplay{// 如果CMMotionManager的加速度数据可用if(self.motionManager.accelerometerAvailable){// 主动请求获取加速度数据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的陀螺仪数据可用if(self.motionManager.gyroAvailable){// 主动请求获取陀螺仪数据CMGyroData* gyroData =self.motionManager.gyroData;self.gyroLabel.text = [NSStringstringWithFormat:@"绕各轴的转速为\n--------\nX轴: %+.2f\nY轴: %+.2f\nZ轴: %+.2f", gyroData.rotationRate.x, gyroData.rotationRate.y, gyroData.rotationRate.z];}// 如果CMMotionManager的磁场数据可用if(self.motionManager.magnetometerAvailable){// 主动请求获取磁场数据CMMagnetometerData* magnetometerData =self.motionManager.magnetometerData;self.magnetometerLabel.text = [NSStringstringWithFormat:@"磁场数据为\n--------\nX轴: %+.2f\nY轴: %+.2f\nZ轴: %+.2f", magnetometerData.magneticField .x, magnetometerData.magneticField .y, magnetometerData.magneticField .z];}}
结果如下:
基于代码块获取
self.motionManager = [[CMMotionManager alloc]init];if(_motionManager.isDeviceMotionAvailable) {//更新数据频率_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}]; }]; }
简单应用
图片无论在设备如何倾斜的情况下都保持水平
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);}];}
结果如下:
敲击手掌的时候实现导航返回
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]; }}];}
结果如下:
旋转改变页面
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]; }}];}
结果如下:
计算设备的位移
理论上设备一开始静止,就可以通过加速度和时间的值来计算设备的位移,(时间越长 误差越大),然是尝试了一下 做不到,误差太大,看来加速计做不了这么精细的活。。