加速计与陀螺仪

设备静止时受到的地球引力为1g,1g是物体在地球的海平面上受到的下拉力(9.8米/秒2)。假如设备从高处掉落,其加速计测量到的加速度将为0g。假如设备水平放在桌面上,则加速计测量出的加速度为1g,且方向朝上。

加速计测量3个轴(x、y和z)上的值,如图所示:

这个轴在方向上有些不同于传统坐标轴,考虑以下实际情况:

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

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

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

1g重力的分布情况是:x=0.5,y=-0.5

1g重力的分布情况是:y=-0.5,z=0.5

仅当设备的朝向相对于重力的方向发生变化时,加速计才能检测到;要同时检测设备的朝向和运动数据,就需要用到陀螺仪了。当查询设备的陀螺仪时,它将报告设备绕x, y, z轴的旋转速度,单位为弧度/秒;2弧度相当于一整圈,因此陀螺仪返回读数2表示设备绕相应的轴每秒转一圈。

有两种方式访问设备的朝向和运动数据,一种是通过UIDevice请求朝向通知,另一种是利用框架Core Motion定期地直接访问加速计和陀螺仪数据。

通过UIDevice请求朝向通知

虽然可直接查询加速计并使用它返回的值判断设备的朝向,但Apple为开发人员简化了这项工作。单例UIDevice表示当前设备,它包含方法beginGeneratingDeviceOrientationNotifications,该方法命令iOS将朝向通知发送到通知中心(NSNotificationCenter)。启动通知后,就可以注册一个NSNotificationCenter实例,以便设备的朝向发生变化时自动调用指定的方法。

通过访问UIDevice的属性orientation来获得设备当前朝向,该属性的类型为枚举值UIDeviceOrientation,有6个预定义值:

UIDeviceOrientationFaceUp — 设备正面朝上

UIDeviceOrientationFaceDown — 设备正面朝下

UIDeviceOrientationPortrait — 纵向(Home键在下)

UIDeviceOrientationPortraitUpsideDown — 纵向倒转(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(@"当前朝向枚举数字值:%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;
    }
}

代码解释:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

beginGeneratingDeviceOrientationNotifications从字面来理解是:开始产生设备朝向通知。实际作用是,通过调用该方法通知设备:如果用户改变了iPhone或iPad的朝向,我们想获悉这一点。

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

[NSNotificationCenter defaultCenter]调用默认的消息中心,然后向默认的消息中心添加

addObserver — 观察者,即处理通知的类,如果是当前类,则设置为self。

selector — 收到通知后调用何种方法。

name — 通知的名字,上面的"UIDeviceOrientationDidChangeNotification"来自于UIDevice.h:

UIKIT_EXTERNNSString *constUIDeviceOrientationDidChangeNotification;

使用Core Motion读取加速计和陀螺仪数据

利用UIDevice只能判断极端朝向,应用程序经常要获悉这些朝向之间的过渡状态,如设备处于某个倾斜位置。Core Motion运动管理器让您能够指定从加速计和陀螺仪那里接收更新的频率(单位为秒),还让您能够直接指定一个处理程序块(handle block),每当更新就绪时都将执行该处理程序块。

实际加速度在Core Motion里被分解成了两部分:Gravity和UserAcceleration。Gravity代表重力1g在设备的分布情况,UserAcceleration代表设备运动中的加速度分布情况。将这两者相加就等于实际加速度。Gravity的三个轴所受的重力加起来始终等于1g,而UserAcceleration取决于单位时间内动作的幅度大小。

CMRotationRate的X,Y,Z分别代表三个轴上的旋转速率,单位为弧度/秒。旋转速度为1弧度/秒,意味着设备每秒旋转半圈。这里复习一下弧度与角度的转换:

1角度 = π/180 弧度

1弧度 = 180/π角度

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

CMAttitude的三个属性Yaw,Pitch和Roll分别代表左右摆动、俯仰以及滚动。可以将设备想象成一架飞机,下面的gif图演示了各种运动状态:

Yaw的运动状态:

Pitch的运动状态:

Roll的运动状态:

让应用程序使用CMMotionManager需要3个步骤:分配并初始化运动管理器→设置更新频率→使用startDeviceMotionUpdatesToQueue:withHandler请求开始更新并将更新发送给一个处理程序块。

首先需要将框架Core Motion添加到项目中:

下面的代码实现了这样一个界面,通过CMMotionManager返回了设备的各个状态值:

#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

P.s. 只有2010年后的设备支持陀螺仪。要检查设备是否提供了这种支持,可使用CMMotionManager的布尔属性gyroAvailable,如果其值为YES,则表明当前设备支持陀螺仪。

时间: 2024-10-15 01:44:25

加速计与陀螺仪的相关文章

第六章:加速计与陀螺仪

iOS系统提供了加速计和陀螺仪支持,如果iOS设备提供了这些硬件支持,iOS即可通过CoreMotion框架提供的加速计来获取设备当前的加速度数据.陀螺仪数据.所处的磁场以及设备的方位等信息: 对于iOS应用开发者来说,开发传感器应用十分简单,CoreMotion框架的核心API是CMMotionManager,开发者只要创建一个CMMotionManager对象,接下来即可采用定时器周期性地从CMMotionManager对象获取加速度数据.陀螺仪数据等,也可采用基于代码块的方式来获取这些数据

ios开发——实用技术篇Swift篇&加速计和陀螺仪

加速计和陀螺仪 1 //返回按钮事件 2 @IBAction func backButtonClick() 3 { 4 self.navigationController?.popViewControllerAnimated(true) 5 } 6 7 8 @IBOutlet var xLabel:UILabel! 9 @IBOutlet var yLabel:UILabel! 10 @IBOutlet var zLabel:UILabel! 11 12 @IBOutlet var orient

加速计和陀螺仪

在程序中如果需要创建运动管理器的实例,应由一个实例向整个程序提供加速计和陀螺仪运动服务.因为设备中只有一个加速计和一个陀螺仪,使用单例更合乎逻辑. 创建运动管理器使用框架为:CoreMotion.framework 引入头文件#import <CoreMotion/CoreMotion.h> //初始化运动管理器 CMMotionManager *motionManager=[[CMMotionManager alloc]init]; //判断设备是否支持加速计和陀螺仪 if (motionM

iOS开发-CoreMotion框架(加速计和陀螺仪)

CoreMotion是一个专门处理Motion的框架,其中包含了两个部分加速度计和陀螺仪,在iOS4之前加速度计是由UIAccelerometer类来负责采集数据,现在一般都是用CoreMotion来处理加速度过程,不过由于UIAccelerometer比较简单,同样有人在使用.加速计由三个坐标轴决定,用户最常见的操作设备的动作移动,晃动手机(摇一摇),倾斜手机都可以被设备检测到,加速计可以检测到线性的变化,陀螺仪可以更好的检测到偏转的动作,可以根据用户的动作做出相应的动作,iOS模拟器无法模拟

CoreMotion框架--加速计和陀螺仪

iOS加速计是三轴加速计,可以监测三维空间中的运动和重力. 三轴坐标系统: *手机顶部向上时,正对手机屏幕,手机屏幕向左是X轴正方向. *沿手机屏幕向上是Y轴正方向. *垂直屏幕向外是Z轴正方向. 当手机静止不动时,地球引力将会给予手机1g加速度.

陀螺仪、加速计、磁力计等传感器汇总 (转)

转自 http://blog.csdn.net/a345017062/article/details/6459643 陀螺仪就是内部有一个陀螺,它的轴由于陀螺效应始终与初始方向平行,这样就可以通过与初始方向的偏差计算出实际方向.手机里陀螺仪实际上是一个结构非常精密的芯片,内部包含超微小的陀螺.加速计是用来检测手机受到的加速度的大小和方向的,而手机静置的时候是只受到重力加速度(这个高中学过)的.所以很多人把加速计功能又叫做重力感应功能.磁力计是测试磁场强度和方向的. 陀螺仪测量是参考标准是内部中间

iOS新加速计事件(陀螺仪和加速计)

iOS新加速计事件 [iOS新加速计事件] 1.iOS5.0以前,可以使用UIAcceleration来监听加速计事件. 2.Bug iOS5.0以后,UIAccelerometerDelegate已经被depreacated,如下: deprecated不是说不能说了,而是意味着在将来版本会删除,所以如果不想更新知识的话,就使用UIAccelerometer吧.更保险的方法是使用一个Timer来检查UIAcceleration,即不依赖于此Delegate回调. 3.针对iOS4.0以上版本,

swift目录

第二部分 实 战 第3章 UI基础 138 3.1 iOS开发平台限制和方式 138 3.2 iOS SDK介绍 141 第4章 UI开发与控件 182 4.1 窗口与视图 182 4.1.1 UIScreen.UIWindow和UIView 182 4.1.2 界面旋转和大小处理 188 4.2 图片资源的使用 191 4.3 UILabel 201 4.4 UITextField 206 4.5 UIButton 216 4.6 UITableView 221 4.6.1 UITableVi

STM32四旋翼飞行器

这个飞控是基于STM32,整合了MPU6050,即陀螺仪和重力加速计,但没有融合电子罗盘: 这是飞控程序的控制流程(一个执行周期): 比较重要的地方: 1.i2c通信方式: STM32的开发库是带有i2c通信的相关函数的,但是我最后还是没有用这些函数. 我通过GPIO模拟i2c,这样也能获得mpu6050的数据,虽然代码多了一些,但是比较好的理解i2c的原理. STM32库实现的模拟i2c代码(注释好像因为编码问题跪了): /***********************************