`
啸笑天
  • 浏览: 3462614 次
  • 性别: Icon_minigender_1
  • 来自: China
社区版块
存档分类
最新评论

Core Motion框架使用方法

阅读更多

from : http://mobile.51cto.com/iphone-285018.htm

iOS4Core Motion框架使用方法是本文要介绍的内容,主要是来学习IOS4框架的内容。在iOS4之前,加速度计由UIAccelerometer类来负责采集工作,而电子罗盘则由Core Location接管。

而iPhone4的推出,由于加速度计的升级(有消息说使用的是这款芯片) 和陀螺仪的引入,与motion相关的编程成为重头戏,所以,苹果在iOS4中增加一个一个专门负责该方面处理的框架,就是Core Motion Framework。这个Core Motion有什么好处呢?简单来说,它不仅仅提供给你获得实时的加速度值和旋转速度值,更重要的是,苹果在其中集成了很多算法,可以直接给你输出把重力 加速度分量剥离的加速度,省去你的高通滤波操作,以及提供给你一个专门的设备的三维attitude信息,如图:



 

有这么一个好东西,我们自然就要好好利用了。下面就介绍一下,如何利用Core Motion Framework,来获得对应的motion信息。

Core Motion在iOS4.0主要负责三种数据:加速度值,陀螺仪值,设备motion值。实际上,这个设备motion值就是通过加速度和旋转速度进行 fusing变换算出来的,基本原理后面会介绍。Core Motion在系统中以单独的后台线程的方式去获得原始数据,并同时执行一些motion算法来提取更多的信息,然后呈献给应用层做进一步处理。Core Motion框架包含有一个专门的Manager类,CMMotionManager,然后由这个manager去管理三种和运动相关的数据封装类,而 且,这些类都是CMLogItem类的子类,所以相关的motion数据都可以和发生的时间信息一起保存到对应文件中,有了时间戳,两个相邻数据之间的实 际更新时间就很容易得到了。这个东西是非常有用的,比如有些时候,你得到的是50Hz的采样数据,但希望知道的是每一秒加速度的平均值。

从Core Motion中获取数据主要是两种方式,一种是Push,就是你提供一个线程管理器NSOperationQueue,再提供一个Block(有点像C中 的回调函数),这样,Core Motion自动在每一个采样数据到来的时候回调这个Block,进行处理。在这中情况下,block中的操作会在你自己的主线程内执行。另一种方式叫做 Pull,在这个方式里,你必须主动去像Core Motion Manager要数据,这个数据就是最近一次的采样数据。你不去要,Core Motion Manager就不会给你。当然,在这种情况下,Core Motion所有的操作都在自己的后台线程中进行,不会有任何干扰你当前线程的行为。

那接下来的问题就是,我在什么时候选择什么方式呢?苹果官方推荐了一个使用指南,比较了两种方式的优劣,并做出了使用场景的推荐。如下图所示。应该说,两种方式各自的优缺点还是很鲜明的,使用场景也大不一样,很好区分,如图:



 

Core Motion的大体介绍就是这些。下面说说Core Motion具体负责的采集,计算和处理。Core Motion的使用就是一三部曲:初始化,获取数据,处理后事。

在初始化阶段,不管你要获取的是什么数据,首先需要做的就是

  1. motionManager = [[CMMotionManager alloc] init]; 

所有的操作都会由这个manager接管。后面的初始化操作相当直观,以加速度的pull方式为例

  1. if (!motionManager.accelerometerAvailable) {  
  2. // fail code // 检查传感器到底在设备上是否可用  
  3. }  
  4. motionManager.accelerometerUpdateInterval = 0.01; // 告诉manager,更新频率是100Hz  
  5. [motionManager startAccelerometerUpdates]; // 开始更新,后台线程开始运行。这是pull方式。 

如果是push方式,更新的代码可以写成这样

  1. [motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMAccelerometerData *latestAcc, NSError *error)  
  2. {  
  3. // Your code here  
  4. }]; 

接下来就是获取数据了。Again,很简单的代码

  1. CMAccelerometerData *newestAccel = motionManager.accelerometerData;  
  2. filteredAcceleration[0] = newestAccel.acceleration.x;  
  3. filteredAcceleration[1] = newestAccel.acceleration.y;  
  4. filteredAcceleration[2] = newestAccel.acceleration.z; 

通过定义的CMAccelerometerData变量,获取CMAcceleration信息。和以前的UIAccelerometer类的使用方式一样,CMAcceleration在Core Motion中是以结构体形式定义的

  1. typedef struct {  
  2. double x;  
  3. double y;  
  4. double z;  

对应的motion信息,比如加速度或者旋转速度,就可以直接从这三个成员变量中得到。

最后是处理后事,就是在你不需要Core Motion进行处理的时候,释放资源

  1. [motionManager stopAccelerometerUpdates];  
  2. //[motionManager stopGyroUpdates];  
  3. //[motionManager stopDeviceMotionUpdates];  
  4. [motionManager release]; 

你看,就是这么简单。当然,如果这么Core Motion这么简单,就太无趣了。实际上,Core Motion最好玩的地方,既不是加速度,也不是角速度,而是经过sensor fusing算法处理的Device Motion信息的提供。Core Motion里面提供了一个叫做CMDeviceMotion的类,用来把下图所示的这些数据封装成Device Motion信息,如图:



 

我们来看看这些被封装数据的介绍。

第一个attitude,就是刚才说到的三维attitude,通俗来讲,就是告诉你手机在当前空间的位置和姿势。

第二个是重力信息,其本质是重力加速度矢量在当前设备的参考坐标系中的表达,开发不再需要通过滤波来提取这个信息了,因为Core Motion已经给你了。

第三个是加速度信息。同样,滤波在这里不再需要(根据程序需求而加的滤波算法自然是可以保留的)。

第四个是即时的旋转速率,也就是rotation rate,是陀螺仪的输出。

下面就来详细介绍一下这四种数据。

1. Attitude。在CMDeviceMotion对象中,attitude是以

  1. @property (readonly, nonatomic) CMAttitude *attitude; 

属性定义的。一个CMAttitude的实例,封装了关于当前设备在空间中的姿态信息。这个信息是由下面集中数学表达式定义的:

一个四元数。

一个变换rotation矩阵

三个欧拉角 (roll, pitch, 和yaw)。关于欧拉角,again,请参考我上一篇文章。

四元数是一种Attitude Determination System经常使用的数据保存形式,我不是很清楚。而欧拉角和变换矩阵则是相辅相成的,两者之间可以相互推导。所以这里主要介绍一下对虚拟现实或者游戏都大有帮助的变换矩阵。

这个rotation变换矩阵究竟有什么用呢?我们来看看下面这张图:



 

本质上讲,变换矩阵给我们阐述了从一个向量空间到另一个向量空间的映射关系。举个例子,在很多应用中都需要对加速度信息进行判断,但是,用户在使用 手机的过程中,姿势是不断变换的,我们可以采集到某个设备在t1时间点的加速度以及重力信息,也可以采集到t2时间点的信息,我们却不能直接拿他们做运 算。为什么?因为由于手机各个轴方向的变化,加速度和重力信息在t1时间点属于一个向量空间,在t2时间点,就属于另一个向量空间了,如果你硬拿 acc.x1和acc.x2求设备的运动模式,自然不可能准的。

所以,现在的问题是,我们要找到两个三维空间的线性变换T,让这个变换关系帮我们把某个空间的值变换到另一个空间去,这样就可以在同一个空间做比较 或者任何计算了。Core Motion如何解决这个问题呢?它首先让你可以在程序开始的初始时间点t1(比如你画第一祯的时候)采集一个attitude的值作为参照坐标系,我们 假定这个向量是v_ref。在任何时间点,比如t2,采集一个attitude的值,假定这个向量是v_dev,位于当前设备的坐标系,那么我们有以下关 系,如图:



 

其中R就是rotation matrix。由于v_ref是正交基向量,所以,如图:



 

刚才说到了,v_ref和v_dev都是其对应向量空间的正交基,而这个R矩阵正好是正交矩阵,所有的列向量线性独立。所以,R所对应的变换,正是我们要找的这两个空间的线性变换,而且这是一对一变换。

好,上面这个结论告诉我们什么呢?你在当前时刻t2采集的当前坐标系下的加速度信息,不仅在t1时刻的参照坐标系下有对应的向量,而且仅有一个对应 向量!如果我们定义a_dev是当前的加速度向量,那么它在参照坐标系里面对应的加速度向量只有一个,而且肯定可以由下面式子求出,如图:



 

这个式子不存在无解的情况,因为正交矩阵永远都是有逆矩阵的。经此变换,你就可以随意比较和计算不同时间点的加速度和重力信息,从而得出精确的用户运动模式了。

比较有趣的一点是,R变换矩阵的表达形式,正好表明了R和rotation rate的关系: 当前时间点的坐标系和参照坐标系的变换矩阵,是由陀螺仪提供的yaw, pitch和roll三个轴上角度信息推断的。于是,再一次,我们感受到了新加的陀螺仪强大的地方。更强大的地方在于,Core Motion直接就把R矩阵提供给开发者了,省去了开发者很多易错而繁琐的工作。

说了这么多铺垫,还是简单介绍一下获得当前时间点的R矩阵信息的步骤吧:

首先,获得参考矩阵信息

  1. if (motionManager != nil) {  
  2. CMDeviceMotion *deviceMotion = motionManager.deviceMotion;  
  3. referenceAttitude = [deviceMotion.attitude retain];  

然后在希望得到R矩阵的时候,执行下列操作:

  1. CMRotationMatrix rotation;  
  2. CMDeviceMotion *deviceMotion = motionManager.deviceMotion;  
  3. CMAttitude *attitude = deviceMotion.attitude;  
  4. if (referenceAttitude != nil) {  
  5. [attitude multiplyByInverseOfAttitude:referenceAttitude];  
  6. }  
  7. rotation = attitude.rotationMatrix; 

很简单,也很直观,一个multiplyByInverseOfAttitude的调用,正好反应了我们刚才推导的矩阵运算关系。至此,rotationMatrix被我们拿到,接下来的事情就只有想不到,没有做不到了。

2、Gravity和UserAcceleration。之所以把他们放在一起讲,是因为他们本质上比较类似,而且原始的加速度(就是通过 [motionManager startAccelerometerUpdates]获得的那个值)本来就是他们的叠加和,换句话说,将原始加速度分解就得到了他们俩,只不过现在苹果 帮你把这个滤波分解给做了。他俩在Core Motion中的属性定义是

  1. @property (readonly, nonatomic) CMAcceleration gravity;  
  2. @property (readonly, nonatomic) CMAcceleration UserAcceleration; 

都是CMAcceleration所包装的结构体。而且,两者的参考坐标系都是一样的,以设备的外框架为准,如图:



 

得到这两种数据的方式比较简单,就是直接通过读取motionManager.deviceMotion.userAcceleration/gravity的三个成员变量即可。

3、Rotation rate。旋转速率是通过叫CMRotationRate的结构体封装的,其内部变量定义和CMAcceleration一模一样。正负的确定,由右手法 则判断。看到这里,不少朋友可能会有问题:这个数据,和之前介绍的直接通过motionManager获得的CMGyroData有什么区别呢?通过 Device Motion封装处理后的Rotation rate,去掉了原始的CMGyroData所有的bias。举个例子,如果我们把设备放在桌上静止不动,理想情况下,陀螺仪的输出应该是0。问题在于, 你直接从陀螺仪获得的原始数据并不是0,而是由很多不确定因素导致的非0值,这其中就包括了很多的漂移误差等等,比如陀螺仪温漂,就会影响到我们的读数。 Core Motion经过一些算法的处理,帮开发者消除了这种bias,极大方便了motion相关的开发工作。

说到Rotation rate,要讲一下这个输出数值的特点。如果你写一个简单的测试程序,把三个轴的数值都输出到屏幕上来看,会发现一个很有意思的现象:pitch和 roll的值,和你读数时候的手机的attitude完全对应,而yaw的值,则是从0开始显示,手机的attitude在之后变了的话,yaw的值才有 对应的变化。这是因为,对于pitch和roll来讲,他们都有明确的参照面,就是水平面,而且这个值肯定是在出厂之前就校正过。但yaw呢?没有,用户 在刚打开app的时候,可能会朝向任何不同的方向。所以此时,Core Motion干脆就给你输出相对的初始值0,之后你再根据yaw方向上的相对变化来判断设备的位置变化。

另外一点要补充的是,对于设备的旋转,如果三个轴上都有变化,那么默认角度计算的顺序是先roll,再pitch,最后yaw。

小结:iOS4Core Motion框架使用方法,讲到现在,基本的Core Motion知识就都总结完了。在智能手机出现之前,我们都说,手机就是用来打电话的。智能手机改变了这一切。用户总是有各种各样的需求等待开发者满足, 而关键就在于,开发者能不能理解用户,认识用户,做好个人化。Gyroscope的集成和Core Motion的推出,让很多以前在智能手机上无法实现或者难以实现的应用成为了可能。这是机遇,想象力的机遇,也是挑战,执行能力的挑战。最后希望本文能对你有所帮助。

  • 大小: 207.7 KB
  • 大小: 255.7 KB
  • 大小: 136.1 KB
  • 大小: 12 KB
  • 大小: 17.3 KB
  • 大小: 4 KB
  • 大小: 9.2 KB
  • 大小: 209.2 KB
分享到:
评论
1 楼 ljfdestiny 2015-07-06  

相关推荐

    iOS Core Motion

    特别是在苹果公司的生态系统中,Core Motion框架为开发者提供了丰富的工具和API来访问设备内置的各种传感器数据,如加速度计、陀螺仪和磁力计等。本次讨论主要聚焦于iOS Core Motion框架在Apple Watch上的运用及其新...

    C# Leap Motion样例

    标题中的"C# Leap Motion样例"指的是一个使用C#编程语言编写的示例项目,它与Leap Motion设备的交互有关。Leap Motion是一款先进的体感控制器,能够捕捉并识别手部和手指的动作,为开发者提供了在虚拟空间中进行手势...

    通用框架iOS

    5. Core Location和Core Motion框架:用于获取设备的位置信息和运动数据,实现地图服务和健康跟踪等功能。 三、快速开发技巧 1. 使用CocoaPods或Carthage:这两个第三方依赖管理工具可以帮助开发者轻松引入和管理第...

    ios-CCPCoreMotion.zip

    《iOS中的Core Motion框架与动画应用》 在iOS开发中,我们经常需要利用设备的各种传感器来实现丰富的用户体验,其中Core Motion框架就是一个强大的工具。本文将深入探讨如何利用Core Motion框架,特别是陀螺仪和加...

    Gravity-Sensor-.zip_gravity

    这个"Gravity-Sensor-.zip_gravity"文件似乎包含了与利用苹果设备内置的Core Motion框架来实现重力感应相关的资源。Core Motion是Apple提供的一个强大的框架,它允许开发者访问设备的各种运动传感器数据,包括加速度...

    传感器代码实现完整版本.rar

    1. Core Motion框架:iOS设备中的传感器数据主要通过Apple的Core Motion框架获取,这个框架提供了一种简单而有效的方式来访问加速度计、陀螺仪、磁力计和高度计等传感器的数据。Core Motion不仅提供实时数据流,还能...

    IOS 计算运动步数

    总结来说,iOS设备通过运动传感器和Core Motion框架实现步数计算,开发者可以利用这些工具轻松集成步数追踪功能到他们的应用中。通过实时获取和展示步数,用户可以更好地了解自己的日常活动,从而鼓励健康生活方式。

    MotionRecognizer

    在这个场景中,我们主要关注如何使用iOS的Core Motion框架来实现摇一摇功能。 Core Motion是Apple提供的一个框架,它允许开发者访问来自设备的各种运动传感器的数据,包括加速度计、陀螺仪和磁力计等。这些传感器...

    背景根据重力感应动

    首先,我们需要了解iOS中的Core Motion框架。它是苹果提供的用于获取设备运动数据的库,包括重力、加速度、陀螺仪等传感器的数据。通过Core Motion框架,我们可以实时获取到设备的运动状态,并将其应用于界面更新。 ...

    iOS CoreMotion实现设备运动加速度计陀螺仪

    在使用Core Motion框架时,需要注意的是,从iOS 10.0开始,为了保护用户隐私,应用需要在Info.plist文件中添加相应的使用说明键(如NSMotionUsageDescription),来告知用户应用将获取哪些数据类型以及为何需要这些...

    IOS应用源码之Altimeter.zip

    本篇将深入探讨一个名为"Altimeter"的iOS应用源码,旨在为开发者提供一个理解iOS应用工作原理、学习Objective-C编程语言以及了解Core Location和Core Motion框架的宝贵资源。 Altimeter,顾名思义,是一个测量海拔...

    BLECoreMotionPeripheral-master

    **BLECoreMotionPeripheral-master** 是一个针对iOS平台的蓝牙低功耗(Bluetooth Low Energy, BLE)开发项目,主要关注如何利用Core Motion框架和外围设备(Peripheral)角色进行交互。这个项目提供了一个完整的示例...

    仿百度外卖-首页重力感应

    在iOS开发中,实现类似百度外卖首页的重力感应效果主要涉及到Core Motion框架的应用。Core Motion是Apple提供的一套API,用于获取设备的各种运动数据,包括加速度、陀螺仪、磁力计等传感器的数据,使得开发者能够...

    Motion welder OC IOS的解析实现

    4. **渲染动画**:iOS中的动画渲染主要通过Core Animation框架实现。根据模型对象中的信息,我们可以设置`CALayer`的属性,如位置、大小、旋转等,并应用关键帧动画。`CAAnimation`类和其子类提供了丰富的动画效果。...

    iPhone GL 重力感应 源代码

    1. **Core Motion框架**:在iOS中,我们通过Core Motion框架来访问设备的运动数据,包括重力感应器、加速度计和陀螺仪的数据。Core Motion框架提供了CMMotionManager类,该类能够实时地获取设备的运动数据。 2. **...

    IOS应用源码之利用M7处理器进行计步.zip

    1. **导入Core Motion框架**:在Objective-C项目中,你需要在`.h`文件中导入`CoreMotion.h`头文件,这将使你的类能够访问Core Motion框架中的类和方法。 ```objc #import ``` 2. **创建CMMotionActivityManager...

    【游戏】-重力感应的speedmaze.7z

    2. Core Motion框架:在iOS平台上,开发者可以使用Apple的Core Motion框架来访问设备的加速度计和陀螺仪数据。Core Motion提供了实时的运动数据,包括设备的加速度、角速度和重力方向等。 二、游戏开发中的重力感应...

    IOS应用源码之【游戏】重力感应的speedmaze_源码_游戏.zip

    2. **CoreMotionManager**:使用苹果的Core Motion框架,初始化并管理设备的运动数据。 3. **GameLogic**:游戏逻辑层,根据接收到的重力感应数据更新游戏状态。 4. **Model**:模型层,存储游戏状态,如玩家位置、...

Global site tag (gtag.js) - Google Analytics