【问题标题】:I need help using the Gyro in swift我需要帮助快速使用陀螺仪
【发布时间】:2019-10-20 04:47:01
【问题描述】:

我现在已经编码了,所以当我翻转手机时,它会在一些文本中添加一个,但它会一直添加,直到完成翻转。有没有办法让我每次翻转都会增加一个。

更改 y > 代码

func startGyro() {
    motionManager.gyroUpdateInterval = 0.2
    motionManager.startGyroUpdates(to: OperationQueue.current!) { (data, Error) in
        if let myData = data {
            if myData.rotationRate.y > 3 {
                tiltOut = tiltOut + 1
                self.labelText = "\(tiltOut)"
            }
        }
    }
}

我希望它每次翻转都记录一个。

【问题讨论】:

  • 您可能可以使用myData.rotationRate 以及自陀螺仪更新开始以来经过的时间,通过积分计算自陀螺仪更新开始以来手机旋转了多少。您还需要确定什么是“翻转”。是从开始旋转180度吗?从开始旋转是 360 度吗?等等。
  • @RPatel99 我希望我的翻转从开始旋转到 = 360 度,我应该如何将它放在我的代码中?
  • 我现在很难用陀螺仪测试代码,所以我会发布一个答案,但把它当作你应该做的指南而不是复制 -粘贴示例。
  • @RPatel99 这很有帮助,但我收到一个错误“枚举案例'毫秒'不能用作实例成员”和“let dt = prevTime.distance(to: currTime)。毫秒”部分和“使用未解析的标识符 'dTheta'”,其中两个 dTheta 部分非常丢失,如果你能指出我的正确
  • 检查我的答案的编辑。另外,欢迎来到 Stack Overflow;将来,请评论有关该答案帖子评论部分答案的任何讨论。另外,我的意思是让我的代码更像是一个指南,而不是复制粘贴的东西。 “使用未解析的标识符 'dTheta'”错误是大多数编程语言中非常常见的错误,通常意味着未声明变量/变量名中有错字。 @Sprilz

标签: swift xcode


【解决方案1】:

将此代码视为指南而不是复制粘贴示例,因为与陀螺仪相关的代码有点难以测试,但这里的核心思想是跟踪经过的时间和旋转速率以确定旋转的距离设备已旋转。

var prevTime = DispatchTime.now()
var totalRotation: CGFloat = 0
var delta: CGFloat = 10

func startGyro() {
    motionManager.gyroUpdateInterval = 0.2
    motionManager.startGyroUpdates(to: OperationQueue.current!) { (data, Error) in
        if let myData = data {
            let currTime = DispatchTime.now()
            let dt = 0
            let interval = prevTime.distance(to: currTime)
            if case .nanoseconds(let value) = interval {
                dt = value
            }
            prevTime = currTime
            // assuming rotationRate is in degrees/millisecond.
            let dTheta: CGFloat = CGFloat(myData.rotationRate.y) * CGFloat(dt)
            // If not milliseconds, convert dt to correct time unit
            // If rotationRate is in radians, convert to degrees or make future comparison check for 2*pi instead of 360 degrees
            totalRotation += dTheta
            if totalRotation > 360 - delta && totalRotation < 360 + delta {
                tiltOut = tiltOut + 1
                self.labelText = "\(tiltOut)"
                totalRotation -= 360
            }
        }
    }
}

存在增量是因为不会在每次设备转动 1 度时调用startGyroUpdates,因此您必须提供一个缓冲区来确定“大约 360 度”的情况。在这里,我给出了一个范围,如果它已经转动了 350-370 度,它应该将标签增加一。当然,这使用了离散的时间块,但假设startGyroUpdates调用之间的时间间隔和该时间跨度内rotationRate的变化相对较好,应该不会有太大的误差。该代码还假设手机在startGyroUpdates 调用之间不会旋转超过 360 度,我认为这是一个公平的假设。

如果您知道旋转速度将相当恒定,您也可以只使用旋转速度的平均值并将其乘以经过的时间。

编辑:在 dTheta 之前忘记了let,并添加了将DispatchTimeInterval 转换为可用Int 的代码。您可以为秒、毫秒等添加大小写,并将dt 转换为rotationRate 的时间单位。有关将prevTime.distance(to: currTime) 的结果转换为您可以用来进行数学运算的Int 的更多信息,请参阅this SO link。确保在进行单位转换时不会丢失精度。

编辑 2:将 dTheta 指定为 CGFloat 类型

编辑 3:将 myData.rotationRate.ydt 转换为 CGFloat

【讨论】:

  • 感谢您的所有帮助,但我仍然收到“let dTheta = myData.rotationRate.y * dt”错误,错误提示“二进制运算符 '*' 不能应用于输入'Double'和'Int'”。我有一个 github,但我不知道这会有多大帮助。 "github.com/acllc/bestFlip"
  • dt 转换为 Double:Double(dt)
  • 感谢您的帮助,这解决了我的问题。它打开了“totalRotation += dTheta”的另一个问题,它说“二元运算符'+='不能应用于'CGFloat'和'Double'类型的操作数”。我不知道如何解决它。你帮了我很多忙,我一直在寻找像你这样的人来真正提供帮助而不是放弃。
  • @Spilz 每当它说类型不匹配时,请尝试从一种类型转换为另一种类型,或者在变量正在初始化时指定您想要的类型。检查我刚刚所做的编辑。
  • @Spilz 如果此答案对您有帮助,您可以接受它,以便其他人知道此解决方案有用和/或正确。如果没有,请随时澄清什么不起作用,或者如果这个答案完全不符合标准,请等待新的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多