在 AR 中使用指南针
在 AR 中使用指南针主要有三种方式:
- CoreMotion:可以获取加速度计、陀螺仪、磁力计、重力感应等信息,可以指定更新间隔时间。
- CoreLocation:不仅可获取磁北,还可与 GPS 结合获取真北,缺点是更新频率不如 CoreMotion。
- ARKit:在ARConfiguration的子类中,指定
ARConfiguration.WorldAlignment.gravityAndHeading
就可以让 ARKit 启动后,场景自动指向真北。
对于 AR 开发来说,最简单又好用的方式就是用 ARKit 自带的功能,但是有些场景下,我们不能随意改动 rootNode 的朝向,或者因为使用了其他定位技术,需要在 AR 启动后,再去更改朝向问题,就必须要自己用CoreMotion或者CoreLocation来实现指南/指北功能了。
精度与刷新问题
苹果在开发文档中,给出指南针的精度是 15 度,因此不管用什么方式,都必然存在一定误差。在CoreLocation中会同时返回heading
的误差,经过测试,一般给出的在 7 度左右。但实际肉眼观察,这个值也并不是太准确,尤其是在室内,只能做为参考。经验上,一般最大误差在± 40 度左右,也就是说只能大概指出北方,iPhone 8 误差最大,8 plus 就没那么差,iPhone 11 系列好一些。
刷新问题就是指,当方向确定后,后续如果出现变动或者误差累积,手机指示的正北方向是否会改变。
在 ARKit 中,如果使用.gravityAndHeading
配置,那么在 AR 启动后,正北的方向就确定了,接下来以视觉跟踪为主,根据肉眼观察是不会再去对方向做更新(可能会有微调,但很难确定是什么原因导致,也可能是误差或场景变化导致的)
如果使用CoreMotion或者CoreLocation,那么位置变化后可以拿到当前的方向值,根据项目需要确定是不是操作场景,朝向北方。一般来说,当拿着手机来回运动或进行“8”字运动后,方向指示会更准确。
还有刷新的稳定性问题,根据经验来说,CoreMotion或者CoreLocation中返回的方向值,是平缓而又连续的,也就是已经经过了低通滤波,不会出现数值跳动现象。直接拿来做动画,也是没有问题的。
朝向计算标准
首先需要说明的是,手机的朝向都是设备朝向,也就是没有考虑横屏等操作的,需要自己在项目中判断横屏后的方向问题。
那么所谓的设备朝向又是怎么计算的?并不是简单以留海方向,或后盖正对的方向来计算的。而是在两者之间取中间值,与两者夹角 45 度的方向上,再投影到水平面上,来计算与正北的夹角的。
这么做的好处是,当你面向正北方站立,竖直拿着手机的时候,或者轻微后仰(向上拍照时)时,手机指示的正北不变,仍然是前方;而当你水平拿着手机,或者留海轻微下垂时,手机指示也仍然是前面是正北。
当你面向正北,用力抬头,后仰超过 45 度时,手机会从指北瞬间变成指向正南方向;而当你用力低头,手机留海下垂超过 45 度时,手机也会从指亲瞬间变成指向正南方向。
但是,对于iPhone 自带的指南针 app 来说,不完全是这样,需要下机留海下垂到 90 度,指南针才会改变方向,这是因为苹果做了特殊处理。