ios - 查找 iOS 设备的法向量

标签 ios gyroscope core-motion

我想使用 CMAttitude 来了解垂直于 iPad/iPhone 屏幕玻璃的矢量(相对于地面)。因此,我会得到如下向量:

enter image description here

请注意,这与方向不同,因为我不关心设备如何绕 z 轴旋转。因此,如果我将 iPad 面朝下举过头顶,它会显示 (0,-1,0),即使我在头顶旋转它(像直升机一样),它也会继续显示 (0,- 1,0):

enter image description here

我觉得这可能很容易,但由于我是四元数的新手并且不完全理解设备运动的引用框架选项,所以它一直在逃避我一整天。

最佳答案

  1. 在您的情况下,我们可以说设备的旋转等于设备法线的旋转(像您指定的那样,围绕法线本身的旋转被忽略)
  2. CMAttitude你可以通过 CMMotionManager.deviceMotion提供旋转 相对于引用系。其性质四元数,旋转 矩阵和欧拉角只是不同的表示。
  3. 当您使用 CMMotionManager 的 startDeviceMotionUpdatesUsingReferenceFrame 启动设备运动更新时,可以指定引用帧。方法。在 iOS 4 之前,您必须使用 multiplyByInverseOfAttitude

综合起来,当设备面朝上放在 table 上时,您只需以正确的方式将四元数与法向量相乘。现在我们需要这种表示旋转的四元数乘法的正确方法:根据Rotating vectors这是由以下人员完成的:

n = q * e * q' 其中 q 是由 CMAttitude [w, (x, y, z)], q' 是它的共轭 [w, (-x, -y, -z)] 和 e 是面朝上法线 [0, (0, 0, 1)] 的四元数表示.不幸的是,Apple 的 CMQuaternion 是结构化的,因此您需要一个小的辅助类。

Quaternion e = [[Quaternion alloc] initWithValues:0 y:0 z:1 w:0];
CMQuaternion cm = deviceMotion.attitude.quaternion;
Quaternion quat = [[Quaternion alloc] initWithValues:cm.x y:cm.y z:cm.z w: cm.w];
Quaternion quatConjugate = [[Quaternion alloc] initWithValues:-cm.x y:-cm.y z:-cm.z w: cm.w];
[quat multiplyWithRight:e];
[quat multiplyWithRight:quatConjugate];
// quat.x, .y, .z contain your normal

四元数.h:

@interface Quaternion : NSObject {
    double w;
    double x;
    double y;
    double z;
}

@property(readwrite, assign)double w;
@property(readwrite, assign)double x;
@property(readwrite, assign)double y;
@property(readwrite, assign)double z;

四元数.m:

- (Quaternion*) multiplyWithRight:(Quaternion*)q {
    double newW = w*q.w - x*q.x - y*q.y - z*q.z;
    double newX = w*q.x + x*q.w + y*q.z - z*q.y;
    double newY = w*q.y + y*q.w + z*q.x - x*q.z;
    double newZ = w*q.z + z*q.w + x*q.y - y*q.x;
    w = newW;
    x = newX;
    y = newY;
    z = newZ;
    // one multiplication won't denormalise but when multipling again and again 
    // we should assure that the result is normalised
    return self;
}

- (id) initWithValues:(double)w2 x:(double)x2 y:(double)y2 z:(double)z2 {
        if ((self = [super init])) {
            x = x2; y = y2; z = z2; w = w2;
        }
        return self;
}

我知道四元数一开始有点奇怪,但一旦你有了想法,它们就会非常棒。它帮助我将四元数想象成围绕向量 (x, y, z) 的旋转,而 w 是角度的(余弦)。

如果您需要对它们进行更多操作,请查看 cocoamath开源项目。类 Quaternion 及其扩展 QuaternionOperations 是一个很好的起点。

为了完整起见,是的,您也可以使用矩阵乘法来完成:

n = M * e

但我更喜欢四元数方式,它可以为您省去所有三角函数的麻烦并且性能更好。

关于ios - 查找 iOS 设备的法向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10827401/

相关文章:

iphone - iOS 陀螺仪 API

ios - 尝试根据设备的角度旋转图像

ios - iOS-脏内存持续增长

ios - 是否有任何 Swift 的生命周期图看起来与我们所知道的 Objective-C 相同?

iphone - 有 AVMutableComposition 视频创建问题

ios - 自动续订订阅和非消耗性 IAP

iphone - Core Location 和 Core Motion 设备标题

ios - Adobe Air 的 DeviceOrientationEvent

iOS9 ActivityManager.startActivityUpdatesToQueue 错误

ios - 从 GLKQuaternion 中提取的意外滚动和俯仰