39

加速计和陀螺仪

 5 years ago
source link: http://www.cocoachina.com/ios/20190121/26181.html?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前言

最近因为工作需要对加速计和陀螺仪进行学习和了解,过程中有所收获。

正文

一、加速计

iPhone在静止时会受到地球引力,以屏幕中心为坐标原点,建立一个三维坐标系(如右图),此时iPhone收到的地球引力会分布到三个轴上。

iOS开发者可以通过CoreMotion框架获取分布到三个轴的值。如果iPhone是如图放置,则分布情况为x=0,y=-1.0,z=0。

在CoreMotion中地球引力(重力)的表示为1.0。

手机如果屏幕朝上的放在水平桌面上,此时的(x,y,z)分布是什么?

7N7BbeV.png!web

上面答案是(0,0, -1.0);

如何检测手机的运动?

CoreMotion框架中有CMDeviceMotion类,其中的gravity属性用来描述前面介绍的重力;另外的userAcceleration是用来描述手机的运动。

当手机不动时,userAcceleration的(x, y, z)为(0, 0, 0);

当手机运动,比如在屏幕水平朝上的自由落体时,检测到的(x, y, z)将为(0, 0, 1);

当手机屏幕水平朝上,往屏幕左边以9.8m/s2的加速度运动时,检测到的(x, y, z)将为(1, 0, 0);

1、gravity是固定不变,因为地球引力的不变;但是xyz的分布会变化,收到手机朝向的影响;
2、userAcceleration是手机的运动相关属性,但是检测到的值为运动加速度相反的方向;
3、一种理解加速计的方式:在水平的路上有一辆车,车上有一个人;当车加速向右运动时,人会向左倾斜;此时可以人不需要知道外面的环境如何,根据事先在车里建立好的方向坐标系,可以知道车在向右加速运动。

二、加速计的简单应用

图片悬浮

手机旋转,但是图片始终保持水平。

QZ36Zne.gif

实现流程

1、加载图片,创建CMMotionManager;

2、监听地球重力的变化,根据x和y轴的重力变化计算出来手机与水平面的夹角;

3、将图片逆着旋转相同的角度;

x、y轴和UIKit坐标系相反,原点在屏幕中心,向上为y轴正方向,向右为x轴正方向,屏幕朝外是z轴正方向;

在处理图片旋转角度时需要注意。

三、陀螺仪

如图,建立三维坐标系;

陀螺仪描述的是iPhone关于x、y、z轴的旋转速率;

静止时(x, y, z)为(0, 0, 0);

当右图手机绕Y轴正方向旋转,速率为每秒180°,则(x, y, z)为(0, 0, 3.14);

IfAnAvF.png!web

陀螺仪和加速计是同样的坐标系,但是新增了旋转的概念,可以用右手法则来辅助记忆;

陀螺仪回调结构体的单位是以弧度为单位,这个不是加速度而是速率;

四、CoreMotion的使用

CoreMotion的使用有两种方式 :

1、Push方式:设置间隔,由manager不断回调;

self.motionManager = [[CMMotionManager alloc] init];
self.motionManager.deviceMotionUpdateInterval = 0.2;
[self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]
                                                withHandler:^(CMDeviceMotion * _Nullable motion, NSError * _Nullable error) {
}];

2、Pull方式:启动监听,自定义定时器,不断读取manager的值;

self.motionManager = [[CMMotionManager alloc] init];
self.motionManager.deviceMotionUpdateInterval = 0.2;
[self.motionManager startDeviceMotionUpdates];
// self.motionManager.deviceMotion 后续通过这个属性可以直接读取结果

iOS系统在监听到运动信息的时候,需要把信息回调给开发者,方式就有push和pull两种;

push 是系统在规定的时间间隔,不断的回调;

pull 是由开发则自己去读取结果值,但同样需要设定一个更新频率;

两种方式的本质并无太大区别,都需要设置回调间隔,只是读取方式的不同;

在不使用之后(比如说切后台)要关闭更新,这是非常耗电量的操作。

五、demo实践

基于加速计,做了一个小游戏,逻辑不复杂详见具体代码,分享几个处理逻辑:

1、圆球的边界处理;(以球和右边界的碰撞为例)

if (self.ballView.right > self.gameContainerView.width) {
        self.ballView.right = self.gameContainerView.width;
        self.ballSpeedX /= -1;
    }

2、圆球是否触碰目标的检测;

- (BOOL)checkTarget {
    CGFloat disX = (self.ballView.centerX - self.targetView.centerX);
    CGFloat disY = (self.ballView.centerY - self.targetView.centerY);
    return sqrt(disX * disX + disY * disY) <= (kConstBallLength / 2 + kConstTargetLength / 2);
}

3、速度的平滑处理;

static CGFloat lySlowLowPassFilter(NSTimeInterval elapsed,
                            GLfloat target,
                            GLfloat current) {
    return current + (4.0 * elapsed * (target - current));
}

FZ3Q3iz.gif

总结

加速计和陀螺仪的原理复杂但使用简单,实际应用也比较广。

之前就用过加速计和陀螺仪,但是没有系统的学习过。在完整的学习一遍之后,我才知道原来加速计的单位是以重力加速度(9.8 m/s2)为标准单位,陀螺仪的数据仅仅是速率,单位是弧度每秒。

上面的小游戏代码地址在 Github

作者:落影loyinglin

链接:https://www.jianshu.com/p/6d6b213912f5


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK