免费开源的iOS开发学习平台

CoreMotion框架:3-CMDeviceMotion

CoreMotionManager对象,不仅仅能够分别提供加速计、陀螺仪和磁力计的裸数据,并且还能够把获取到的以上三种传感器的数据进行综合计算以及偏差调整,得到更加具有实际使用价值的数据,加工后的数据可以通过CoreMotionManager的deviceMotion属性获得。

CMDeviceMotion类介绍

在CMDeviceMotion类中,可以获取设备当前的加速计、陀螺仪以及磁力计的裸数据,但与传感器的裸数据相比,CMDeviceMotion类中的数据已经经过了进一步的处理,这个处理过程由CoreMotion框架自动完成,主要包括对于裸数据的偏差纠正以及综合计算。总之,CMDeviceMotion类中获取的传感器数据,更加具有使用价值。

  • 获取设备方向/朝向的数据
@property(readonly, nonatomic) CMAttitude *attitude; 
  • 获取陀螺仪相关数据
@property(readonly, nonatomic) CMRotationRate rotationRate; 
  • 获取加速计相关数据。其中,总加速度=重力加速度+用户产生的加速度
@property(readonly, nonatomic) CMAcceleration gravity; //重力加速度
@property(readonly, nonatomic) CMAcceleration userAcceleration; //用户产生的加速度 
  • 磁力计相关数据。其中,CMCalibratedMagneticField是一个结构体,包括两个成员变量field以及accuracy;
@property(readonly, nonatomic) CMCalibratedMagneticField magneticField ; 

Pull模式

使用Pull模式来获取deviceMotion对象的值,首先需要检测设备的可用性,并启动。

- (void)viewDidLoad {
    [super viewDidLoad];  
    //Pull模式--device motion
    if (self.motionMgr.isDeviceMotionAvailable) {
        [self.motionMgr startDeviceMotionUpdates];
    }else {
        NSLog(@"device motion不可用");
    }
    //Pull模式--陀螺仪
    if (self.motionMgr.isGyroAvailable) {
        [self.motionMgr startGyroUpdates];
    }else {
        NSLog(@"陀螺仪GyroScope不可用");
    } 
}

当需要采集数据时,可以通过CMMotionManager的deviceMotion属性获取相关数据。

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{   
    //通过deviceMotion获取陀螺仪当前状态
    CMDeviceMotion * deviceMotion = self.motionMgr.deviceMotion;
    NSLog(@"device motion rationRate: x:%f, y:%f, z:%f",deviceMotion.rotationRate.x, deviceMotion.rotationRate.y,deviceMotion.rotationRate.z);
    //获取陀螺仪当前状态
    CMRotationRate rationRate = self.motionMgr.gyroData.rotationRate;
    NSLog(@"gyroscope current state: x:%f, y:%f, z:%f", rationRate.x, rationRate.y, rationRate.z);
}

运行后,我们可以发现:通过deviceMotion获取的陀螺仪数据与直接获取陀螺仪的裸数据有差别,即数据进行了处理。

Push模式

在Push模式下,我们可以通过deviceMotionUpdateInterval属性来设置采样间隔,然后调用startDeviceMotionUpdatesToQueue:withHandler:方法来获取采集到的传感器数据。

- (IBAction)startDeviceMotion:(id)sender {
    //设置采样间隔
    self.motionMgr.deviceMotionUpdateInterval = 1.0;
    //开始采样
    [self.motionMgr startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion * _Nullable motion, NSError * _Nullable error) {
        NSLog(@"x:%f, y:%f, z:%f", motion.rotationRate.x, motion.rotationRate.y, motion.rotationRate.z);
    }]; 
}
- (IBAction)stopDeviceMotion:(id)sender {
    [self.motionMgr stopDeviceMotionUpdates];
}

示例代码

https://github.com/99ios/17.5.3