我需要一些关于在 iPhone 上使用陀螺仪的帮助。我无法理解 CMAttitude 在特定情况下关于俯仰、滚动和偏航的读数。
这是我的代码
- (void)handleDeviceMotion:(CMDeviceMotion*)motion {
NSLog(@"Yaw %f ",attitude.yaw * 180 / M_PI);
NSLog(@"Pitch %f ",attitude.pitch * 180 / M_PI);
NSLog(@"Roll %f ",attitude.roll * 180 / M_PI);
}
假设 iPhone 平放在平面上,如下图所示:
俯仰、横滚和偏航(几乎)为 0 度,绕轴的任何转动都会返回可理解的读数。例如,向右转动设备,Yaw 减小,Pitch 和 Roll 保持为 0。
现在 iPhone 处于以下位置:
然后重新开始测量。
读数为:Yaw = 0,Pitch = 90,Roll = 0
由于设备绕着这个轴旋转,Pitch 增加。
将 iPhone 移动到这个位置:
读数为:Yaw = 30,Pitch = 90,Roll = 0
再一次,由于设备围绕 Yaw 轴旋转,因此该值发生变化而其他值不变。
围绕 Roll 轴移动设备:
读数为:Yaw = 0,Pitch = 90,Roll = -20。
现在我无法理解。将 iPhone 绕半径为 R(R > 0)的圆移动,如下图所示:
偏航改变,同时俯仰和滚转不改变。
我原以为 Yaw 保持不变而 Roll 发生了变化。
既然我只对用户绕 Yaw 轴的旋转感兴趣,该如何补偿呢?
我遇到的另一个问题是漂移。 iPhone在第二张图所描述的位置,手拿在手上静置了很长时间(1分钟以上)。偏航不断增加。知道如何补偿漂移吗?
提前致谢
更新 我遵循了凯的建议,但没有任何改变。关于我的代码的更多细节。我只想在用户绕 Yaw 轴旋转设备时使用 Yaw 来旋转 UIImage。 这行得通,但是当用户绕着自己的垂直轴旋转时,偏航会发生变化。我认为这是不正确的,因为当用户绕其垂直轴移动时,设备不会绕其自己的偏航轴旋转。可能是我错了。这是我的原始代码:
- (void)handleDeviceMotion:(CMDeviceMotion*)motion {
CMAttitude *attitude = motion.attitude;
NSLog(@"Yaw %f ",attitude.yaw * 180 / M_PI);
NSLog(@"Pitch %f ",attitude.pitch * 180 / M_PI);
NSLog(@"Roll %f ",attitude.roll * 180 / M_PI);
image.transform = CGAffineTransformMakeRotation(-attitude.yaw);
}
这是 Kay 建议后的代码:
- (void)handleDeviceMotion:(CMDeviceMotion*)motion {
CMAttitude *attitude = motion.attitude;
if (startAttitude == 0) {
startAttitude = attitude;
}
[attitude multiplyByInverseOfAttitude:startAttitude];
NSLog(@"Yaw %f ",attitude.yaw * 180 / M_PI);
NSLog(@"Pitch %f ",attitude.pitch * 180 / M_PI);
NSLog(@"Roll %f ",attitude.roll * 180 / M_PI);
image.transform = CGAffineTransformMakeRotation(-attitude.yaw);
}
我开始设备运动监控
[motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryZVertical toQueue:[NSOperationQueue currentQueue]
withHandler: ^(CMDeviceMotion *motion, NSError *error){
[self performSelectorOnMainThread:@selector(handleDeviceMotion:) withObject:motion waitUntilDone:YES];
}];
最佳答案
[完全修订]
(1) 奇怪的角度
乍一看,我误以为遇到了与 Euler Angles 相关的一些典型问题。 .因为它们接近这个问题区域并且非常重要,所以我保留了原始答案的这一部分。欧拉角问题有:
- 歧义,因为旋转状态和欧拉角表示之间的关系不是双射的,即一组角度描述一个旋转,但旋转可以由多组欧拉角表示。在您问题的图 3 中,您可以通过
1: Yaw=30°, 2: Pitch=90°
或通过1: Pitch=90°, 2: Roll= 实现相同的旋转30°
- Gimbal Lock问题:您可能会失去一个自由度,并且设备无法再围绕其中一个轴旋转。解决方案是使用四元数或旋转矩阵。
但正如您在评论中所述,真正的罪魁祸首似乎是引用框架。从 iOS 5.0 开始,Apple 增强了传感器融合算法并考虑了磁场数据来计算 CMAttitude。虽然还是老办法startDeviceMotionUpdates , 它现在使用默认引用 CMAttitudeReferenceFrameXArbitraryZVertical这样所有的测量都与“Z 轴是垂直的,X 轴指向水平面中的任意方向”有关。
为了在开始(或任何其他旋转)时获取与引用相关的数据,您需要存储您想要作为引用的 CMAttitude
实例,然后使用 CMAttitude
的 multiplyByInverseOfAttitude转换每个新态度的方法,即在 handleDeviceMotion
方法的开头。
(2) 偏航漂移
我认为这与 iOS 6 中的一个错误有关,就像我在 Drifting yaw angle after moving fast 中描述的那样。因为它在以前的版本中工作得很好。我提交了一个错误 - 让我们看看他们什么时候会修复它。
更新 2
正如评论和聊天显示的那样,目标是通过倾斜设备来控制机器人。在这种情况下,知道设备的完整旋转状态会在改变行走方向时搞乱控制。因此,使用 CMDeviceMotion.gravity 的纯加速度计方法方便多了。
关于iphone - iPhone 上的陀螺仪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14528156/