如何使用CoreMotion获取设备在空间中的方向?

5

我在思考和搜索中遇到了问题,无法找到好的方向去搜索......我想开发一个算法,在使用设备动作的情况下在360度图像(类似球体)中移动。

所以,如果用户将设备指向他的前面,他会得到图像的确定原点。当他在身边移动设备时,全景图像会相应移动。

有什么想法或资源可以供我参考吗?

谢谢,祝大家用Swift好运:)


360度或全景图像,其结构是怎样的?球体意味着三维,即天空和地面被整合在一起。360度表示一个圆柱形,就像你用iPhone拍全景照片时一样。 - Kay
你说得对。我只谈论360度全景和仅在x轴周围移动的问题。 之后我可能会更深入地探讨,但为了逐步进行,我想先完成这一步骤。 - TanguyAladenise
我开始通过存储参考姿态并基于先前的姿态获取新的横滚来获得一些结果: [currentAttitude multiplyByInverseOfAttitude: self.referenceAttitude]; 这使得我可以无限制地在全景中移动。 您觉得这听起来怎么样? 我现在需要将无限图像处理为无限滚动视图。 此外,这种行为无法处理用户指向地面的情况。如果他向右或向左旋转,无论他朝哪个方向,全景都会移动...我还需要修复这个问题。 - TanguyAladenise
2个回答

2

多亏了Kay,我才能找到正确的方法来实现这个效果。

我写这篇答案是为了为那些寻找同样东西的人提供更多细节。

首先,你需要创建一个CMMotionManager对象。

然后使用startDeviceMotionUpdatesToQueue来处理运动事件。

[self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
    [self processMotion];
}];

在 processMotion 中,你只需要根据之前的姿态获取当前的姿态:
// Get attitude difference with previous one
CMAttitude *currentAttitude = self.motionManager.deviceMotion.attitude;
[currentAttitude multiplyByInverseOfAttitude:self.referenceAttitude];

感谢这个功能,你可以知道用户自上次更新以来的新角度。 然后,在处理视图时,将新的欧拉角转换为需要移动图像的像素数量。 只要注意欧拉角在-180、180之间变化,并由苹果以弧度给出。这可能会很方便:

#define RADIANS_TO_DEGREES(radians) ((radians) * (180.0 / M_PI))

在我的情况下,我只计算新的x偏移量,因为我只是在x轴上移动。

希望这可以帮助你。


1
我看到这是一个旧答案,你能提供更多关于如何实现它的细节吗?你使用什么作为参考姿态? - dev296

1
我看到两种简单的实现方式,不需要太多的数学麻烦:
  1. 使用欧拉角,即CMAttitude的roll属性。定义图像宽度和测量角度之间的映射,并注意180° / -180°处的奇异性。这种方法的缺点是:
    • 当用户以混乱的方式移动其设备时,可能存在万向节锁定的危险。
    • 对于完整的3D视图,同样适用。
  2. 使用来自CMDeviceMotion的磁场,它对万向节锁定具有鲁棒性。磁力计比加速度计/陀螺仪慢一些,但我认为CoreMotion的融合算法将提供合理的估计,因此这不是问题。这里的缺点是:
    • 磁场并非始终可用或倾向于略微不准确。
    • 将其扩展到3D视图可能会很麻烦。
两种方法都很容易实现,因此我建议从其中一种开始。如果您想要更复杂的解决方案,则需要深入了解数学知识。在这种情况下,可能的解决方案是使用当前设备法线(例如见Finding normal vector to iOS device),将其投影到地球表面平面上,并为圆柱形全景图采取角度差。对于球形投影,在这种情况下甚至更容易,因为您可以直接使用法线向量。

谢谢你的回答。我想我理解了你所解释的事情。我会进行调查,并在让事情正常工作时告诉你。 - TanguyAladenise

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接