Apple 有一个用于跟踪手腕的对象,例如
anchor.originFromAnchorTransform
,在该对象上,有一个受保护的 rotation
字段,因此我无法访问它,但如果您像这样打印 anchor
,它会被打印出来。我试图重现 HandAnchor 从变换矩阵计算出的值,但我永远无法得到 HandAnchor 计算出的值
HandAnchor(
chirality: left,
id: F37E231E-ED08-4E3A-8888-AD99CA814F70,
isTracked: true,
originFromAnchorTransform:
<translation=(-0.124833 0.765254 -0.135481)
rotation=(76.86° -119.53° 144.82°)>,
handSkeleton: HandSkeleton(jointCount: 27))
这是原始的 4x4 矩阵。注意:Apple 使用列专业,因此每个数组都是一列。
simd_float4x4([
[-0.08531584, 0.13101268, -0.987703, 0.0],
[0.9765112, -0.18586183, -0.10900249, 0.0],
[-0.19785702, -0.97380245, -0.1120784, 0.0],
[-0.12483275, 0.7652545, -0.13548124, 1.0]])
这些是我根据下面的代码不断计算的数字
(-96.56549, 11.411671, 94.99314)
(94.99314, 11.411671, -96.56549)
(-173.70236, 6.522802, -101.485016)
但预期的是
(76.86° -119.53° 144.82°)
我尝试了很多不同的公式,但无论如何,我都无法得到与它相同的计算结果。
func getIntrinsicRotation(_ anchor: HandAnchor) -> (Float, Float, Float) {
let rotationMatrix = extractUpperLeft3x3(from: anchor.originFromAnchorTransform)
// Compute yaw, pitch, roll from rotationMatrix in intrinsic order
let sy = sqrt(rotationMatrix[0, 0] * rotationMatrix[0, 0] + rotationMatrix[1, 0] * rotationMatrix[1, 0])
let singular = sy < 1e-6 // If singularity is detected
let yaw: Float
let pitch: Float
let roll: Float
if !singular {
yaw = atan2(rotationMatrix[1, 0], rotationMatrix[0, 0])
pitch = atan2(-rotationMatrix[2, 0], sy)
roll = atan2(rotationMatrix[2, 1], rotationMatrix[2, 2])
} else {
yaw = atan2(-rotationMatrix[1, 2], rotationMatrix[1, 1])
pitch = atan2(-rotationMatrix[2, 0], sy)
roll = 0
}
// Convert radians to degrees
let yawDegrees = yaw * 180 / .pi
let pitchDegrees = pitch * 180 / .pi
let rollDegrees = roll * 180 / .pi
return (yawDegrees, pitchDegrees, rollDegrees)
}
func getExtrinsicRotation(_ anchor: HandAnchor) -> (Float, Float, Float) {
let rotationMatrix = extractUpperLeft3x3(from: anchor.originFromAnchorTransform)
// Compute roll, pitch, yaw from rotationMatrix in extrinsic order
let sy = sqrt(rotationMatrix[0, 0] * rotationMatrix[0, 0] + rotationMatrix[1, 0] * rotationMatrix[1, 0])
let singular = sy < 1e-6 // If singularity is detected
let roll: Float
let pitch: Float
let yaw: Float
if !singular {
roll = atan2(rotationMatrix[1, 2], rotationMatrix[0, 2])
pitch = atan2(-rotationMatrix[2, 2], sy)
yaw = atan2(rotationMatrix[2, 1], rotationMatrix[2, 0])
} else {
roll = atan2(-rotationMatrix[1, 0], rotationMatrix[0, 0])
pitch = atan2(-rotationMatrix[2, 0], sy)
yaw = 0
}
// Convert radians to degrees
let rollDegrees = roll * 180 / .pi
let pitchDegrees = pitch * 180 / .pi
let yawDegrees = yaw * 180 / .pi
return (rollDegrees, pitchDegrees, yawDegrees)
}
func getRotation(_ anchor: HandAnchor) -> (Float, Float, Float) {
let rotationMatrix = extractUpperLeft3x3(from: anchor.originFromAnchorTransform)
// Compute roll, pitch, yaw from rotationMatrix
let sy = sqrt(rotationMatrix[0, 0] * rotationMatrix[0, 0] + rotationMatrix[1, 0] * rotationMatrix[1, 0])
let singular = sy < 1e-6 // If singularity is detected
let x: Float
let y: Float
let z: Float
if !singular {
x = atan2(rotationMatrix[2, 1], rotationMatrix[2, 2])
y = atan2(-rotationMatrix[2, 0], sy)
z = atan2(rotationMatrix[1, 0], rotationMatrix[0, 0])
} else {
x = atan2(-rotationMatrix[1, 2], rotationMatrix[1, 1])
y = atan2(-rotationMatrix[2, 0], sy)
z = 0
}
// Convert radians to degrees
let rollDegrees = x * 180 / .pi
let pitchDegrees = y * 180 / .pi
let yawDegrees = z * 180 / .pi
return (rollDegrees, pitchDegrees, yawDegrees)
}
在完成 XYZ、YXZ、ZXY…等的每一个组合之后,我发现顺序是 YZX,而不是人们滚动、俯仰、偏航。它是俯仰、偏航、横滚。我还没弄清楚为什么我必须否定俯仰和滚动才能使其与 HandAnchor 的值相同。
func getRotationYZX(_ anchor: HandAnchor) -> (Float, Float, Float) {
let rotationMatrix = extractUpperLeft3x3(from: anchor.originFromAnchorTransform)
let roll = atan2(-rotationMatrix[0, 1], rotationMatrix[1, 1])
let pitch = atan2(rotationMatrix[2, 1], sqrt(rotationMatrix[2, 2] * rotationMatrix[2, 2] + rotationMatrix[2, 0] * rotationMatrix[2, 0]))
let yaw = atan2(rotationMatrix[2, 0], rotationMatrix[2, 2])
let rollDegrees = roll * 180 / .pi
let pitchDegrees = pitch * 180 / .pi
let yawDegrees = yaw * 180 / .pi
return (-pitchDegrees, yawDegrees, -rollDegrees)
}