// initialising code run only once after each call to [motionManager startDeviceMotionUpdates];
CMAttitude firstAttitude = [motionManager deviceMotion].attitude;
CMQuaternion q = firstAttitude.quaternion;
inverseReferenceQuaternion = [[Quaternion alloc] initWithRe:q.w i:-q.x j:-q.y k:-q.z];
在计时器循环(或处理程序块)中,需要四元数乘法:
// on every update
CMAttitude attitude = [motionManager deviceMotion].attitude;
CMQuaternion current = attitude.quaternion;
Quaternion currentMultiplied = initAsProductOf:inverseReferenceQuaternion And:current
let firstAttitude: CMAttitude = ...
let attitude: CMAttitude = ...
attitude.multiply(byInverseOf: firstAttitude)
print("pitch: \(attitude.pitch); roll: \(attitude.roll); yaw: \(attitude.yaw)")
结构定义:
// structures for representing euler angles
struct EulerAngles {
var pitch: Double
var roll: Double
var yaw: Double
// base c-tor
init(pitch: Double, roll: Double, yaw: Double) {
self.pitch = pitch
self.roll = roll
self.yaw = yaw
}
}
// structure for representing quaternions
struct Quaternion {
var w: Double
var x: Double
var y: Double
var z: Double
// base c-tor
init(w: Double, x: Double, y: Double, z: Double) {
self.w = w
self.x = x
self.y = y
self.z = z
}
// c-tor using CMQuaternion from CoreMotion
init(_ quaternion: CMQuaternion) {
self.w = quaternion.w
self.x = quaternion.x
self.y = quaternion.y
self.z = quaternion.z
}
var inverse: Quaternion {
return Quaternion(w: w, x: -x, y: -y, z: -z)
}
static func * (lhs: Quaternion, rhs: Quaternion) -> Quaternion {
return Quaternion(
w: lhs.w * rhs.w - lhs.x * rhs.x - lhs.y * rhs.y - lhs.z * rhs.z,
x: lhs.w * rhs.x + lhs.x * rhs.w + lhs.y * rhs.z - lhs.z * rhs.y,
y: lhs.w * rhs.y - lhs.x * rhs.z + lhs.y * rhs.w + lhs.z * rhs.x,
z: lhs.w * rhs.z + lhs.x * rhs.y - lhs.y * rhs.x + lhs.z * rhs.w
)
}
// convert to euler angles
var eulerAngles: EulerAngles {
return EulerAngles(
pitch: atan2(2.0 * (w * x + y * z), 1.0 - 2.0 * (x * x + y * y)),
roll: asin(2.0 * (w * y - z * x)),
yaw: atan2(2.0 * (w * z + x * y), 1.0 - 2.0 * (y * y + z * z))
)
}
}
用法:
let inverseReferenceQuaternion = Quaternion(firstAttitude.quaternion).inverse
let currentMultiplied = inverseReferenceQuaternion * Quaternion(attitude.quaternion)
let angles = currentMultiplied.eulerAngles
print("pitch: \(angles.pitch); roll: \(angles.roll); yaw: \(angles.yaw)")
// output must be the same as after `multiply(byInverseOf:`
2条答案
按热度按时间eanckbw91#
因为你不允许自己创建CMAttitude的示例,唯一的方法是创建一个新的四元数,并将其用于任何进一步的计算。我建议使用你自己定制的四元数类,而不是简单的结构CMQuaternion。一个好的起点是cocoamath项目,在那里你可以将Quaternion.m,trunk中的Quaternion. h和QuaternionOperations.m,我将在此示例代码中使用它们。
首先,您必须保存参考四元数(取自
CMAttitude.quaternion
)复共轭的示例,以用于所有后续乘法,即MyClass.h
MyClass.c
在计时器循环(或处理程序块)中,需要四元数乘法:
现在
currentMultiplied
应该包含您要查找的内容。如果你是这个主题的新手,四元数是很漂亮的,但是值得阅读一些教程,比如OpenGL:Tutorials:Using Quaternions to represent rotation或Quaternion Powers。
mpbci0fu2#
最近我有同样的问题,目前的答案不满意我,因为我仍然需要学习很多东西。所以这里是我的下降在这个问题的答案。
假设我们有这样的代码:
结构定义:
用法: