CoreMotion框架-iOS设备的核心运动

来源:互联网 发布:sql语句where条件查询 编辑:程序博客网 时间:2024/04/26 22:35

原文地址:http://blog.sina.com.cn/s/blog_7b9d64af0101cu4p.html


为了防止博主的博文被删。将内容都复制下来。

我们知道iOS的应用真的太多了,很多应用让我们惊叹不已!!!很多意想不到的应用!

比如:

1.电子罗盘指南针之类的应用-让我们知道方向。

2.运动类型软件-让我们知道我们跑步多少公里。

3.社交软件中的摇一摇功能。

4.游戏中扮演角色类中根据设备的晃动等进行操作。

等等。。而且还有很多应用正在层出不穷的展现再我们面前。


其实,他们多半是使用了iOS中的一个框架-核心运动框架-CoreMotion.framework


CoreMotion.framework框架是做什么的


我们可以使用iOS提供给我们的CoreMotion 框架来访问加速度器陀螺仪的相关数据!

它不仅仅提供给你获得实时的加速度值和旋转速度值,更重要的是,苹果在其中集成了很多算法,可以直接给你输出把重力加速度分量剥离的加速度,省去你的高通滤波操作,以及提供给你一个专门的设备的三维attitude信息!


  

我刚接触的时候,也是一头雾水啊。那就普及一下相关的知识。


我们知道,智能手机已经普及到我们日常生活中了,尤其iPhoneiOS设备,也已经相当的普遍(俗称:街机)。在它的硬件设备中,其实安装了很多的传感器。其中的加速度器陀螺仪就是其中的两种传感器!


智能机中常见的传感器

1. 接近传感器

接近传感器,顾名思义,就是用来检测非常接近的目标物体的。这类传感器通常利用电磁场或者静电场的改变,或者测量发射的电磁波的反射波的改变,来进行判断。因为手段不一样,所以接近传感器的目标物体种类也不一样,有的针对金属物体,有的针对塑料物体。具体到手机上来说,现在的手机都是使用了新一代的反射光学接近传感器,可以针对较多种表面类型来检测。过程很简单,它们会发出人眼看不到的红外光,一旦手机来电话了,你肯定会接听,接听会导致脸部皮肤离传感器很近,这样只需要用光学探测器检测从皮肤反射回来的光的总量的变化,接近传感器就检测到了这个接近。这个传感结果有什么用呢?一个明显的例子,就是可以改进手机的节电功能,比如判断什么时候自动打开或关闭显示屏,键盘背光或者触摸功能,甚至于什么时候自动关机/待机,取决于设备的主人是正在通话,正在打字,还是就直接把设备扔到口袋中了。这些任务,就由接近传感器一肩挑了。


2. 加速度传感器

我个人估计,大家最熟悉的,就是加速度传感器。由于其带来了更多的直觉游戏体验,基本姿态识别和环境感知功能,这类传感器从08年开始井喷,因iPhoneiPod的带动而红火,因Wii的集成而大规模部署,并由此带动了价格的下降。现在如果还有哪款手机或者音乐播放器不配备这个传感器阿,出厂去商店都不好意思和摆在一起的别的设备打招呼。加速度计的原理很简单,现在手机里面基本配备的都是3维线传感器,也就是说,用来测量xyz三个轴上的加速力。加速力就是当物体在加速过程中作用在物体上的力,就好比地球引力,也就是重力。

我为什么说大家应该都熟悉加速度传感器呢,如果用IBM笔记本的朋友就知道,前IBM,现联想,的Thinkpad系列笔记本,一直都有硬盘保护功能,这个功能利用的就是通过加速度传感器动态监测出笔记本的震动,并根据这个震动选择关闭硬盘还是继续运行。这样可以最大程度的保护由于振动,比如颠簸的工作环境,或者不小心摔了电脑做造成的硬盘损害,最大程度的保护里面的数据。类似的一个非常普及的用处就是目前用的数码相机和摄像机里,用加速度传感器,来检测拍摄时候的手部的振动,并根据这些振动,自动调节相机的聚焦。现在,我们手头都有iPhoneAndroid军团,Nokia N900等手机,我们至少都知道,加速度传感器可以帮助你打游戏。典型的例子比如Labyrinth2,中文名叫做迷宫滚球。但更广义地说,加速度传感器在检测人的即时背景环境信息上更有用处。比如说,通过三个轴上加速度的变化值的分析处理,手机可以知道你现在是在走路还是骑车还是坐车,是上坡还是下坡,等等。

从理论上讲,有了三个轴的加速度立体信息,我们可以推断出加速方向的信息,比如,你加速骑车的方向,或者你乘坐的电梯正在朝上还是朝下。根据初中数学的知识,这些方向和角度都是可以通过矢量的加减运算算出来的。可惜的是,我们没法仅仅依靠加速度传感器来检测加速方向的角度,也无法得知手机本身的朝向。这是为什么呢?要解释这个,就牵涉到一个困扰加速度仪的大问题,就是重力加速度分量的干扰。

当你的移动设备处于静止状态时,加速度计能告诉你它相对于地平面的朝向,这是没有问题的; 然而,当设备动起来的时候,分析朝向就相当复杂了。这种情况下,要分四种类型讨论

  1. 设备处于水平完全静止或者匀速运动,这时的它会在垂直方向的轴上输出一个值,那就是重力加速度,接近9.8 。
  2. 设备自由落体的时候,会三个轴都输出0呢。
  3. 设备静止或者匀速运动状态时,但没有处于绝对水平。此时任何轴都可能有输出值,但都是重力加速度的分量。一旦处于这种状态,我们可以通过求分量于三个轴的角度来得知手机旋转的角度。
  4. 设备沿着任意方向加速。这时,问题就变复杂了,因为你没办法知道设备目前的方向角度信息,所以你根本就不知道重力加速度的分量到底是怎么分解的,于是……你也就不清楚某个轴所报告的数值,哪些是重力加速度部分,哪些是真正的线性加速度部分

除此之外,另一个加速度传感器无能为力的地方,就是纯水平旋转,或者匀速水平变向。

这类运动,加速度传感器也只会输出一个值:g。因为无论是xy,还是z轴,都没有真正意义上的加速运动。这会带来什么问题呢?好比你带着一个手机在街上走,沿着一条大街走了一段路,这段路的加速度自然是能被采到的。然后你转弯,在另一条路上走一段,这一段的加速度也是能被采到的。你回到家,拿出手机看数据,没错阿,两端加速度都有,手机知道我走了两段路,很智能阿,缺少了什么东西?你转弯的动作和角度!这个加速度计是采不到的,而这个信息,在很多增强现实的智能应用中,却是非常有用的。为了解决这个问题,人们开始引入其他种类的传感器,比如接下来要介绍的这个陀螺仪。

关于加速度器的坐标:

CoreMotion框架-iOS设备的核心运动



3. 陀螺仪

陀螺仪代表着另一个重要的,但可能还需要等待一两年才能腾飞的传感器领域,主要是因为导航级MEMS陀螺仪目前对于手机来说仍然过于昂贵,普通陀螺仪一般厂商都很少看上眼。当然,在iPhone4的带动下,可以预见的手机军备竞赛,迟早会让陀螺仪逐渐普及开来。陀螺仪的主要作用,是基于角动量守恒的理论,沿着某个特定的坐标轴测量旋转速率。在使用中,陀螺仪的转子在高速旋转时,始终指向一个固定的方向,当运动物体的运动方向偏离预定方向时,陀螺仪就可以感受出来。在现代航空装备中,飞机驾驶的时候,就是通过多达十多个的陀螺仪来测量机体是否翻滚,以及如何翻滚的。

先来看看iPhone中,陀螺仪硬件吧:

CoreMotion框架-iOS设备的核心运动




再看看,陀螺仪的样子:

CoreMotion框架-iOS设备的核心运动

 


关于陀螺仪的坐标:

CoreMotion框架-iOS设备的核心运动


了解一下,关于陀螺仪的坐标轴:

Roll轴的信息:

CoreMotion框架-iOS设备的核心运动

Pitch轴的信息:


CoreMotion框架-iOS设备的核心运动


Yaw轴信息:

CoreMotion框架-iOS设备的核心运动


需要注意的是,这里的三个角度,和加速度计的xyz三维意义完全不同,不要混淆了。


陀螺仪的测量是随时间累计的,要知道当前的角度,只需要将之前所有的输出数值积分即可。当然,陀螺仪只会输出当前旋转的变化值,比如说,如果一架飞机是以60度的倾斜角度径直飞行,此时陀螺仪的输出为0,因为当前就没有机体旋转。但是,你可以通过之前的输出累计计算出当前机体倾斜角度是多少。陀螺仪有两个好处:

  1. 可测频率比较大,低可以低到直流信号,就是0Hz,高可以高到60-70Hz。这个范围,基本是根据人类的普遍动作频率所决定的,而且也考虑了很大的余量。一般的陀螺仪会对采集到的信号滤波,最终显示的数据基本是在0-20Hz范围的。当然,并不是所有陀螺仪都能测量到这个频率范围,这个取决于具体的档次了。
  2. 在设备中的位置并不重要。陀螺仪测量的角速度本质上是惯性角速度,所以你把它放在设备的前端或者后端,输出的值都会是一样的,没有什么区别。

说完了陀螺仪的优点,说说缺点吧。聪明的读者在看到陀螺仪计算角度的原理是,肯定能一下就发现陀螺仪的缺陷:这玩意的误差是累计的!也就是说,某一个时刻你因为不管什么样的原因引进了角度的误差,可能是静态漂移误差,可能是读数误差,whatever,这个误差就会一直跟着你,一直在后面的读数和计算中延续!更有趣的是,陀螺仪有一个臭名昭著的特性:它会随着时间而漂移!换句话说,每分每秒,它都会自动引入附加的误差!!时间一长,完了,你关于旋转度的测量值就变成了中国有关部门:可信度为0 。当然,科技是在发展的,现在很多高端的陀螺仪的随机误差很小,普通应用有时候都可以不用管这个误差。当然,一分钱一分货,这种高端陀螺仪通常都很贵,很少会采用到手机系统中。

这下好玩了,在一个短的时间刻度里,加速度值噪声特别大,而且还有重力的影响。在长的时间刻度里呢,加速度值总体是靠谱的,没有误差累计。而在短的时间刻度里,陀螺仪很准,因为误差累计的速度还是很慢的。但在长的时间刻度里,陀螺仪就不准得离谱。在某些情况下,加速度传感器可以用来校准陀螺仪,比如设备完全静止的时候,和重力相关的方向上,就可以这样做。那么,什么时候不行呢?回头看我们刚才放的那三个图,其中yaw的示意图

yaw角度的变化方向是垂直于重力方向的!所以,通过刚才关于加速度的介绍我们知道,在这个垂直于重力的平面上,加速度传感器就没办法帮陀螺仪了。

本质上,通过三维加速度传感器+三维陀螺仪的合作,我们等同于拥有了一个六维的传感器,但无处不在的误差会让这个六维传感器偶尔感到无助。这时候,我们就需要另外的设备来帮忙做进一步的校正,这就是下面要介绍的电子罗盘。

4. 电子罗盘

电子罗盘,也称磁力计,或者电子指南针,是继加速度计之后,从09年开始井喷的一种传感器。如果我没记错的话,最早集成这个传感器的主流智能手机就是GoogleG1,从这个意义上讲,G1对于磁性传感器市场的带动作用,可能堪比iPhone对于加速度传感器的意义。这玩意啥用处?顾名思义,就是告诉你南北极方向的。以前古老的那种指南针,或者叫平面罗盘,可以在你放平罗盘后告诉你南极北极在哪,这样,你就知道了目前你的正前方在地球这个大平面坐标轴上的角度了。当然,出于技术的限制,平面罗盘要求你保持水平,如果有倾斜就不准确了。后来出现的电子罗盘,很多是两轴的,也就是说,等同于电子平面罗盘。在我记忆中,几年前的openmoko手机就是集成的这种,所以有同样的限制。现在高端智能手机里面集成的都是三维电子罗盘,由于加入了倾角传感器,可以对罗盘进行倾斜补偿,这样就克服了这个缺陷,可以输出三维方向上的角度信息。

电子罗盘的原理也很简单,就是我们物理都学过的霍尔效应。当电流通过一个位于磁场中的导体的时候,磁场会对导体中的电子产生一个横向的洛伦兹力,电荷因此产生偏转,偏转的方向垂直于电流方向和磁场方向,而且正电荷和负电荷偏转的方向相反,从而在导体的两端产生电压差。 这个电压差也叫霍尔电压,和两个因素成比例:电流大小和磁场强度。当然这里有一个要注意的问题,如果磁场的方向是和导体非垂直的话,实际作用的磁场实际上是原来磁场的一个矢量分量。如何知道这个磁场分量的角度呢?我们可以用两个或者多个霍尔效应传感器,相互垂直,这样的话,磁场的方向就可以通过不同传感器上霍尔电压的比例值来求出,这个计算过程只需要知道基本的线性代数运算即可。当然,具体的计算中肯定有一些tricky的地方,不过不是关键点,所以这里就暂时不介绍了。所以和陀螺仪不一样的是,电子罗盘输出的是角方向值,而陀螺仪输出的是角方向的加速度。

所以大家应该都明白了,在电子罗盘的应用中,上述的磁场就是地球磁场,电子罗盘测量地球磁场的矢量值,然后再转换并表示在系统坐标中。在理想情况下,这样测出来的方向值也是比较准确的,一旦我知道移动设备刚开始的方向值,就能通过之后电子罗盘的输出,求出该设备接下来的一系列方向改变信息。

不幸的是,这个世界上的理想情况不存在。在我们经常使用移动设备的环境中,有时候会存在除了地球以外的别的,未被有效屏蔽的磁场,这个外加磁场会有很大可能干扰电子罗盘的读书,而让结果不可信。而且,如果移动设备周围有金属,一旦金属被磁化,电子罗盘也会受很大的影响。

注:以上文章摘自:移动设备智能化的基石iPhone4的传感器谈起


理论很长。总结一下:目的在于告诉我们,iPhone设备中,集成了很多的传感器。以及对每一种传感器进行了分析说明。


看了上面的介绍,相信大家心里面也都有了数。这些传感器,各有神通,也各有缺陷,很多时候还真得相互配合来使用,才能达到预期的效果,真正准确检测出设备主人的行动信息。这个协作的过程比较复杂。但是,我们很多情况下,不需要去了解太多细节,要不,就不用写代码了,直接去中科院搞飞机,卫星,导弹去了!为什么说,我们不需要明白关于加速度器和陀螺仪的太多的原理性的东西?因为,底层的实现全部由CorMotion框架给你准备好了!我们只需要来使用框架提供的属性方法,就可以得到我们想要的信息!


使用CorMotion框架


切回正题,来进行CorMotion框架的使用!


先贴:


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

    

    // 加速度器的检测

    if ([self.motionManager isAccelerometerAvailable]){

        NSLog(@"Accelerometer is available.");

    } else{

        NSLog(@"Accelerometer is not available.");

    }

    if ([self.motionManager isAccelerometerActive]){

        NSLog(@"Accelerometer is active.");

    } else {

        NSLog(@"Accelerometer is not active.");

    }

    

    // 陀螺仪的检测

    if([self.motionManager isGyroAvailable]){

        NSLog(@"Gryro is available.");

    } else {

        NSLog(@"Gyro is not available.");

    }

    if ([self.motionManager isGyroActive]){

        NSLog(@"Gryo is active.");

        

    } else {

        NSLog(@"Gryo is not active.");

    }


说明:

1.对加速度器和陀螺仪相关的访问,都被封装在CoreMotion.framework框架下的CMMotionManager类中。我们通过使用类的方法,来得到我们想要的加速度数据和陀螺仪数据。

2. isAccelerometerAvailable方法用来查看加速度器是否可用。

3. isAccelerometerAvailable方法用来查看加速度器的状态:是否Active(启动)。

4.同理isGyroAvailable方法和isGyroActive方法用来检测陀螺仪。


用来CMMotionManager获取加速度的数据


说到获取加速度器的数据。主要有两种方式。


1.push方式

这种方式,是实时获取到Accelerometer的数据,并且用相应的队列来显示。即主动。


贴:


// 加速度器的检测

    if ([self.motionManager isAccelerometerAvailable]){

        NSLog(@"Accelerometer is available.");

        

        NSOperationQueue *queue = [[NSOperationQueue alloc] init];

        

        [self.motionManager startAccelerometerUpdatesToQueue: queue

                                                 withHandler:^(CMAccelerometerData*accelerometerData, NSError *error) {

                                                     

                                                     NSLog(@"X = %.04f, Y = %.04f, Z = %.04f",accelerometerData.acceleration.x, accelerometerData.acceleration.y, accelerometerData.acceleration.z);

            

                                                 }];

        

        

        

    } 


2.pull方式

就是获取数据,如果要显示,就要向Accelerometer来索要数据。即:被动的方式。

self.motionManager.accelerometerUpdateInterval = 0.01; // 告诉manager,更新频率是100Hz

        [self.motionManager startAccelerometerUpdates]; // 开始更新,后台线程开始运行。



用来CMMotionManager获取陀螺仪的数据


跟加速度器获取数据类似,我们来获取关于陀螺仪的数据


贴:

// 陀螺仪的检测

    if([self.motionManager isGyroAvailable]){

        NSLog(@"Gryro is available.");

        

        if ([self.motionManager  isGyroActive] == NO){

            [self.motionManager  setGyroUpdateInterval:1.0f / 1.0f];

            NSOperationQueue *queue = [[NSOperationQueue alloc] init];

            [self.motionManager startGyroUpdatesToQueue:queue

                                            withHandler:^(CMGyroData *gyroData, NSError *error) {

                                                NSLog(@"Gyro Rotation x = %.04f", gyroData.rotationRate.x);

                                                NSLog(@"Gyro Rotation y = %.04f", gyroData.rotationRate.y);

                                                NSLog(@"Gyro Rotation z = %.04f", gyroData.rotationRate.z);

                                            }];

            

        }

        

    }else {

        NSLog(@"Gyro is not available.");

    }



希望对你有所帮助!


0 0
原创粉丝点击