You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 21:33:09