在iOS原型中,我使用CMDeviceMotion.deviceMotion.yaw和CLHeading.trueHeading的组合来制作响应准确且稳定的罗盘标题。当iPhone保持平坦时,这种方法很有效,我有一个指向稳定罗盘标题的图形箭头。
当iPhone在移植模式下保持垂直时,会出现问题。 UIDeviceOrientation不断从UIDeviceOrientationFaceDown更改为UIDeviceOrientationFaceUp并返回。这使得偏航值基于音调的微小变化来回跳跃+/- 180度。是否可以将设备锁定在一个方向上,该方向可以提供稳定的偏航值,预测变化时不会出现毛刺或以其他方式计算陀螺偏航(或以此方向滚动)?
这个可怜的家伙有同样的问题,没有答案。双点可能的人! :) https://stackoverflow.com/questions/10470938/euler-angle-yaw-not-working-when-iphone-orientation-changes
答案 0 :(得分:14)
我只是在寻找这个问题的答案。它让我心碎了一下,看到你在一年前发布了这个,但我想也许你或其他人可以从解决方案中受益。
问题是万向节锁定。当俯仰大约90度时,偏航和滚动匹配并且陀螺仪失去一定的自由度。四元数是避免万向节锁定的一种方法,但老实说,我并不想绕过它。相反,我注意到偏航和滚动实际上是匹配的,可以简单地总结为解决问题(假设你只关心偏航)。
<强> SOLUTION:强>
float yawDegrees = currentAttitude.yaw * (180.0 / M_PI);
float pitchDegrees = currentAttitude.pitch * (180.0 / M_PI);
float rollDegrees = currentAttitude.roll * (180.0 / M_PI);
double rotationDegrees;
if(rollDegrees < 0 && yawDegrees < 0) // This is the condition where simply
// summing yawDegrees with rollDegrees
// wouldn't work.
// Suppose yaw = -177 and pitch = -165.
// rotationDegrees would then be -342,
// making your rotation angle jump all
// the way around the circle.
{
rotationDegrees = 360 - (-1 * (yawDegrees + rollDegrees));
}
else
{
rotationDegrees = yawDegrees + rollDegrees;
}
// Use rotationDegrees with range 0 - 360 to do whatever you want.
我希望这有助于其他人!
答案 1 :(得分:2)
如果有人对iOS Swift中的实现感兴趣,则代码如下:
let queue = NSOperationQueue()
motionManager.startDeviceMotionUpdatesToQueue(queue) {
[weak self] (data: CMDeviceMotion!, error: NSError!) in
var yawDegrees: Double = self!.motionManager.deviceMotion.attitude.yaw * (180.0 / M_PI)
var pitchDegrees: Double = self!.motionManager.deviceMotion.attitude.pitch * (180.0 / M_PI)
var rollDegrees: Double = self!.motionManager.deviceMotion.attitude.roll * (180.0 / M_PI)
if(rollDegrees < 0 && yawDegrees < 0){
self!.rotationDegrees = 360 - (-1 * (yawDegrees + rollDegrees))
}
else {
self!.rotationDegrees = yawDegrees + rollDegrees
}
}
然而我遇到了一些问题,我希望@ blkhp19可以帮助我解决这个问题,因为在某些点上角度会变成负值,然后会影响整个计算,我无法弄清楚问题是什么。
答案 2 :(得分:0)
问题有点令人困惑,因为至少有两种不同的方式来考虑偏航。一种是从手机的角度来看,一种是从世界的角度来看。
我将使用此image from Apple进行进一步说明:
如果电话放在桌子上:
如果手机靠墙平坦:
使用blkhp19's code above来总结偏航。如果导入SwiftUI
,则可以利用Angle
结构简化弧度+度转换:
let yaw = Angle(radians: deviceMotion.attitude.yaw)
let roll = Angle(radians: deviceMotion.attitude.roll)
var compassHeading: Angle = yaw + roll
if roll.degrees < 0 && yaw.degrees < 0 {
compassHeading = Angle(degrees: 360 - (-1 * compassHeading.degrees))
}
您将需要使用atan2
并像this example一样检查重力。
let rotation = atan2(data.gravity.x,
data.gravity.y) - .pi
还要注意,如果您不需要实际角度,而只需要关系(例如isPhoneUpright),则可以简单地读取这些角度的重力值。