如何使用 CoreMotion 在空间中获取设备方向
Posted
技术标签:
【中文标题】如何使用 CoreMotion 在空间中获取设备方向【英文标题】:How to use CoreMotion for getting device orientation in space 【发布时间】:2014-07-23 23:18:54 【问题描述】:我在这里有一个思考和搜索的问题,找不到好的方向... 我正在寻找一种算法,通过使用设备运动在 360 度图像(类似球体)中移动。
因此,如果用户将设备指向他面前,他将获得图像的确定原点。当他在他周围移动设备时,全景图像会随之移动。
任何想法或来源我可以研究?
感谢所有使用 Swift 的人,祝你好运 :)
【问题讨论】:
360还是球体,图片的结构如何?球体意味着 3 维,即天空和地面是一体的。 360 度表示一个圆柱体,就像你用 iPhone 拍摄全景照片时一样 您指出这一点是对的。我只谈论 360 全景并且仅围绕 x 轴移动。之后我可能会走得更远,但为了一步一步地做这件事,我想先得到这个。 我确实开始获得一些结果,方法是存储参考姿态并根据先前使用 [currentAttitude multiplyByInverseOfAttitude: self.referenceAttitude];这让我无限期地在全景中移动。那些这听起来不错?我知道需要将无限图像处理成我猜的无限滚动视图。另外,此行为无法处理用户指向地面的事实。无论他指向哪个方向,如果他向右或向左旋转,全景就会移动......我也需要解决这个问题。 【参考方案1】:感谢 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 之间变化,Apple 以 rad 为单位给出。这可能很方便:
#define RADIANS_TO_DEGREES(radians) ((radians) * (180.0 / M_PI))
所以在我的例子中,我只是计算新的 x 偏移量,因为我只是在 x 轴上移动。
希望这会有所帮助。
【讨论】:
我看到这是一个旧答案,您能否提供有关如何实现它的更多详细信息。你用什么作为参考态度?【参考方案2】:我看到了两种简单的方法来实现这一点,而不需要太多的数学麻烦:
-
使用欧拉角,即roll property of CMAttitude。定义图像宽度和测量角度之间的映射,并注意 180° / -180° 处的奇点。这种方法的缺点:
当用户开始以混乱的方式移动他们的设备时,Gimbal Lock 可能存在危险。
这同样适用于完整 3D 视图的可扩展性。
使用magnetic field from CMDeviceMotion,它对 Gimbal Lock 具有很强的抵抗力。磁力计比加速度计/陀螺仪慢一点,但我认为 CoreMotion 的融合算法将提供合理的估计,因此这不是重点。这里的缺点:
磁场并不总是可用或往往不太精确。
将其扩展到 3D 视图可能很麻烦。
这两种方法都应该很容易实现,因此我将从其中一种开始。如果你想有一个更复杂的解决方案,你需要更深入地研究数学。在这种情况下,可能的解决方案是使用当前设备法线(例如Finding normal vector to ios device),将其投影到地球表面平面上,并为圆柱全景图获取角度增量。
在这种情况下,球体投影更加容易,因为您可以直接使用法线向量。
【讨论】:
感谢您的回答。我想我明白你解释的事情。我会进行调查,并在一切正常后告诉你。以上是关于如何使用 CoreMotion 在空间中获取设备方向的主要内容,如果未能解决你的问题,请参考以下文章
Apple Watch 和 Swift 在使用 CoreMotion 计算设备运动时崩溃