我希望我的应用程序能够检测设备旋转,而设备保持水平。我可以使用罗盘的读数,但我相信陀螺仪的偏航值会更准确。给定偏航读数,确定360°旋转(顺时针或逆时针)的最佳算法是什么?它必须是一个完整的360°,而不仅仅是将手机在一个方向上转动180°,然后在相反的方向上转动180°。
您将使用CoreMotion来获得关于垂直轴的旋转。你需要添加旋转事件的增量。每当超过最小值的方向与前一个不同时,就重置起点。然后当你到达这个起始点的正负360度时,你就有了旋转
假设您可以在很短的时间间隔内获得读数,并且偏航可以在特定的起点归零。这与另一种方法不同,后者从一个连续调整的起点检测完整的圆。
在这种方法中,我们不断比较当前偏航和以前的偏航,询问是否通过了180度的检查点或PI
。最初,检查点标志cp_pi
是NO
,在任何方向通过它都会切换其状态。请注意,偏航在两个地方改变了它的符号,在零点和再次从PI
到-PI
。
假设你的对象有两个属性在检测器的tick
s (BOOL cp_pi;
和float prev_yaw;
)之间持久,我们认为d_yaw
在穿过0时小于PI
,在穿过圆的另一端时大于PI
。当穿过另一端时,我们切换cp_pi
。当cp_pi
是YES
而过0时,我们可以保证通过了一个完整的循环——否则,cp_pi
将被切换回NO
:
-(void)tick
{
float yaw = [self zeroedYaw];
if ((fabs(yaw) == PI) || (yaw == 0.0f)) return;
if (yaw * prev_yaw < 0)
{
float d_yaw = fabs(yaw - prev_yaw);
if (d_yaw > PI)
{
cp_pi = ! cp_pi;
}
else if (cp_pi)
{
// fire detection event
}
}
prev_yaw = yaw;
}
请注意,为了使我们的工作更容易,如果yaw
正好位于其中一个检查点上,我们将完全跳过检测器功能。