- 在您的情况下,我们可以说设备的旋转等于设备法线的旋转(围绕法线本身的旋转就像您指定的那样被忽略)
-
CMAttitude 你可以通过
CMMotionManager.deviceMotion 提供旋转
相对于参考框架。它的性质四元数,旋转
矩阵和欧拉角只是不同的表示。
- 当您使用CMMotionManager 的startDeviceMotionUpdatesUsingReferenceFrame 方法启动设备运动更新时,可以指定参考帧。在 iOS 4 之前,您必须使用 multiplyByInverseOfAttitude
将这些放在一起,当设备正面朝上放在桌子上时,您只需将四元数以正确的方式与法线向量相乘。现在我们需要这种表示旋转的四元数乘法的正确方法:根据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
但我更喜欢四元数方式,它可以为您省去所有三角函数的麻烦并且性能更好。