34

我需要一些关于在 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 and Roll 保持为 0。

现在 iPhone 处于以下位置:

在此处输入图像描述

并重新开始测量。

读数为:Yaw = 0,Pitch = 90,Roll = 0

由于设备围绕该轴旋转,因此间距增加。

将 iPhone 移动到这个位置:

在此处输入图像描述

读数为:Yaw = 30,Pitch = 90,Roll = 0

再一次,由于设备围绕 Yaw 轴旋转,因此该值会发生变化,而其他值不会发生变化。

围绕滚动轴移动设备:

在此处输入图像描述

读数为:Yaw = 0,Pitch = 90,Roll = -20。

现在我无法理解。围绕半径为 R (R > 0) 的圆移动 iPhone,如下图所示:

在此处输入图像描述

Yaw 改变,而 Pitch 和 Roll 没有改变。

我本来预计 Yaw 保持不变,而 Roll 改变了。

由于我只对用户绕偏航轴的旋转感兴趣,如何弥补这一点?

我遇到的另一个问题是漂移。iPhone 处于第二个图中描述的位置,长时间(1 分钟或更长时间)握在我手中。Yaw 不断增加。知道如何补偿漂移吗?

先感谢您

更新 我遵循了 Kay 的建议,但没有任何变化。关于我的代码的更多细节。我只想在用户围绕 Yaw 轴旋转设备时使用 Yaw 来旋转 UIImage。这是可行的,但是当用户围绕自己的垂直轴旋转时,Yaw 会发生变化。我认为这是不正确的,因为当用户围绕其垂直轴移动时,设备不会围绕其自己的 Yaw 轴旋转。可能是我错了。这是我的原始代码:

- (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);
}

这是凯建议后的代码:

- (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];
                                                           }];
4

1 回答 1

6

[完全修改]

(1) 奇怪的角度

乍一看,我误以为遇到了一些与欧拉角有关的典型问题。因为它们靠近这个问题区域并且牢记非常重要,所以我保留了原始答案的这一部分。欧拉角问题是:

  • 多义性,因为旋转状态和欧拉角表示之间的关系不是双射的,即一组角度描述一个旋转,但一个旋转可以由一组以上的欧拉角表示。在您的问题的图 3 中,您可以通过1: Yaw=30°, 2: Pitch=90°或通过1: Pitch=90°, 2: Roll=30°
  • 云台锁定问题:您可能会失去一个自由度,并且设备无法再围绕其中一个轴旋转。解决方案是使用四元数或旋转矩阵。

但正如您在评论中所说,真正的罪魁祸首似乎是参考框架。从 iOS 5.0 开始,Apple 增强了传感器融合算法,并考虑了磁场数据来计算 CMAttitude。虽然仍然有旧方法startDeviceMotionUpdates,但它现在使用默认参考CMAttitudeReferenceFrameXArbitraryZVertical,以便所有测量都与“ Z 轴垂直且 X 轴指向水平面中的任意方向”相关。

为了在开始时(或任何其他旋转)获取关于参考的数据,您需要存储CMAttitude您想要作为参考的实例,然后使用CMAttitude' multiplyByInverseOfAttitude方法来转换每个新的姿态,即在您的handleDeviceMotion方法开始时。

(2) 偏航漂移

我认为这与 iOS 6 中的一个错误有关,就像我在快速移动后漂移偏航角中描述的那样,因为它在以前的版本中可以正常工作。我提交了一个错误 - 让我们看看他们什么时候修复它。


更新 2

正如评论和聊天显示的那样,目标是通过倾斜设备来控制机器人。在这种情况下,知道设备的完整旋转状态会在改变行走方向时弄乱控制。因此,使用CMDeviceMotion.gravity的纯加速度计方法要方便得多。

于 2013-01-25T20:24:56.203 回答