iOS核心运动在汽车,火车,航班中漂移

时间:2015-01-09 09:07:42

标签: ios core-motion

我得到了我的用户的反馈,“我的游戏 - 应用程序有时会出现一个错误,即船舶完全无法控制。在对此进行调查之后,CoreMotion报告的态度看起来非常快(低于一秒)并且它会突然消失。您可以玩最多五分钟,然后突然发生船舶移动到其中一个屏幕边框并且不再远离该点。

我的问题:有没有人对CoreMotion的态度有相同的体验,你有什么方法或想法来控制这些突如其来的大规模漂移?

我用来获取SpriteKit update()态度的代码是:

if let motion = motionManager.deviceMotion {
    let x = CGFloat(motion.attitude.yaw - basePosition.x)
    let y = CGFloat(motion.attitude.roll - basePosition.y)
    ship.physicsBody?.applyImpulse(CGVectorMake(X_SENSITITVITY * x, Y_SENSITITVITY * y))
}

其中basePositionX_SENSITITVITYY_SENSITITVITY是游戏中的常量值。 motionManager由班级顶部的private var motionManager = CMMotionManager()定义。

据我了解文档,deviceMotion使用重力和态度测量的组合来最小化长期漂移。

也许重要的是要注意:当游戏在没有汽车等振动的静音环境中运行时,它的工作原理非常好。 我想让人们在需要休息的时候玩我的游戏 - 比如乘坐长途火车或飞机 - 或者坐在汽车后座的小孩。

2 个答案:

答案 0 :(得分:1)

我发现了同样的漂移问题。我将CMDeviceMotion的态度与CLLocation的magneticHeading进行了比较。因此,我在一张小桌子周围走了10次,然后在每一轮之后将设备放在同一个地方。

我发现,DeviceMotion的态度每轮都会漂移30度左右。因此,在10轮之后,态度大约是300度。 根据Apple的WWDC 2012演讲“Session 524:了解核心运动”,使用的传感器融合取决于指定的参考框架。 Phil Adam提到,如果指定了xArbitraryCorrected参考帧,传感器融合算法也会使用磁力计。我使用xArbitrary,xArbitraryCorrected和xMagneticNorth进行了相同的测试,但没有区别。指南针的不确定性大约为2-3度(标题滤波器为1.0度)。

也许这是一个错误,我不知道。但我预计至少xArbitrary和xArbitraryCorrected之间存在差异。

答案 1 :(得分:0)

好吧,我找到了解决这个问题的方法。当我看到关于这个问题的一些观点时,答案中可能会有一些兴趣,而有些人则处理同样的问题。

根据我的理解,您可以依赖两件事:

  1. 动态设备的变化。具体来说是CMDeviceMotion.rotationRate
  2. 设备对地球的态度。具体来说是CMDeviceMotion.gravity
  3. 看起来第一个通过读取某种当前力来使用当前位置的变化。这是一个当前值,并且不需要总结这些值 - 因此不会总结错误。

    第二个(重力)测量当前对地球的力量。再次:当前值,没有总结,没有错误总和,没有漂移。

    其他任何事情,特别是CMDeviceMotion.attitude,都会采取措施并加以补充。导致每个度量中的小错误相加,导致结果漂移。 我试图使用转速并通过累加来计算自己的态度。好吧,Apple在这方面并不完美,但比我的任何解决方案都要好: - )

    谈话很便宜。代码在哪里?这里是。在SpriteKit中update()期间调用此方法(对于每个帧)

    private func update(ship: SKSpriteNode) {
        // Orientation can be landscape left or right
        let orientation = UIApplication.sharedApplication().statusBarOrientation == UIInterfaceOrientation.LandscapeLeft ? -1.0 : 1.0
    
        // Get rotation rate
        let x = orientation*motionManager.deviceMotion.rotationRate.x
        let y = orientation*motionManager.deviceMotion.rotationRate.y
    
        // If user tilts device very slow it does not affect the ship
        let xf = CGFloat(abs(x) >= X_RESPONSIVNESS ? X_SENSITITVITY*x : 0.0)
        let yf = CGFloat(abs(y) >= Y_RESPONSIVNESS ? Y_SENSITITVITY*y : 0.0)
    
        // Apply as impulse
        ship.physicsBody?.applyImpulse(CGVectorMake(xf, yf))
    }
    

    由于我的游戏更多关于"用户如何倾斜设备让我知道您希望船舶前往何处?我只是用rotationRate来衡量这个并将其作为冲动来应用。作为附件,您可以旋转设备,这意味着朝向屏幕顶部的旋转实际上是旋转后向底部的旋转。所以我必须在旋转设备时反转脉冲。

    您现在可以向任何方向玩游戏。在汽车或火车等振动的环境中,景观向左,横向,在头顶。它就像一个魅力。我甚至期待下周六的2.5小时航班......