将加速度数据调整为全局参考系



使用Core Motion时,加速度似乎总是相对于设备返回。这意味着,如果你向上摇晃设备屏幕,它将在+/-Z(取决于初始参考(。如果你把设备转向一边,像以前一样上下摇晃,加速度将在+/-X或Y。

我想将这个特定于设备的加速度转换回"全局"帧。这意味着设备的相同物理运动导致加速度数据在同一轴上返回,而与设备在震动时的方向无关。

例如,如果我们上下摇晃设备,屏幕向上,它在z轴上,如果你旋转设备,使屏幕朝前,并进行同样的摇晃,z轴仍然显示加速度,即使相对于设备是Y轴。

我一直在尝试将加速度旋转回初始姿态,看起来有时有效,有时无效。我不相信轮换是正确的方法。我不确定这是正确的数学,还是有时只是随机看起来正确。

extension CMQuaternion {
var toSIMD: simd_quatd {
return simd_quatd(ix: x, iy: y, iz: z, r: w)
}
}
extension CMAcceleration {
var toSIMD: SIMD3<Double> {
return SIMD3<Double>(x,y,z)
}
}

然后这样计算:

var reference: simd_quatd?
motionManager.startDeviceMotionUpdates(using: .xArbitraryZVertical, to: .main) { deviceMotion, error in
guard let deviceMotion = deviceMotion else { return }
let userAcceleration = deviceMotion.userAcceleration.toSIMD
let adjusted: SIMD3<Double>
if let ref = reference {
// rotate the userAccel by the inverse of the reference times the current attitude. 
adjusted = simd_act(simd_mul( simd_inverse(ref.quaternion.toSIMD),deviceMotion.attitude.quaternion.toSIMD), userAcceleration)
} else {
reference = deviceMotion.attitude.quaternion.toSIMD
adjusted = userAcceleration
}
...
}

最终目标是将"向上/向下"分量放入FFT,以尝试找到移动的频率。

旋转加速度矢量是正确的方法吗?有没有更好的方法来实现与姿态无关的加速?或者更好的是,无论方向如何,都要找到设备运动的频率!

我能够验证这确实是一种"旋转"加速度数据的方法。

注意,我没有使用第一帧作为参考,而是简化了它,并使用了四元数

let referenceFrame = simd_inverse(simd_quatd(ix: 0,iy: 0,iz: 0,r: 1))

然后为了处理调整后的加速度,我做:

let userAcceleration = motion.userAcceleration.toSIMD
let adjusted = simd_act(simd_mul(referenceFrame, motion.attitude.quaternion.toSIMD), userAcceleration)

adjusted的Z分量将在全局帧中向上/向下。

我一直在实时地做这件事,没有任何问题。

最新更新