VisionOS RealityKit中HandAnchor旋转(Roll/Pitch/Yaw)计算匹配问题
问题描述
Apple的HandAnchor对象用于追踪手腕,其中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) }
内容的提问来源于stack exchange,提问作者Luke Xu
相关产品推荐
相关产品推荐

