VisionOS RealityKit 如何计算其旋转(横滚、俯仰、偏航)?

问题描述 投票:0回答:1

问题

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)
  }
swift matrix rotation transform visionos
1个回答
0
投票

在完成 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)
  }
© www.soinside.com 2019 - 2024. All rights reserved.