如何获得一个ARImageAnchor相对于给定的SCNNode的方向?



如何获得ARImageAnchor相对于ARKit中给定SCNNode的方向数据?这是基本的场景。

在AR会话开始后的某个点放置的节点。假设它名为originNode。然后用ARKit对放置在环境中的图像进行扫描。当相机检测到图像时,我想计算被检测图像相对于originNode的X, Y, Z和方向(tilt,pan,roll)。请注意设备固定在UIDeviceOrientation。

所以用户可以在水平手持设备,相机指向前方的情况下扫描图像,或者在水平手持设备,相机指向下方的情况下扫描图像。

当我扫描一张平放在桌子上的图像时,我用当前代码得到的值是准确的,我相信

配置:

let configuration = ARWorldTrackingConfiguration()
guard let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources",
bundle: nil)
else { fatalError("Missing expected asset catalog resources.") }
configuration.detectionImages = referenceImages
configuration.maximumNumberOfTrackedImages = 100

委托:

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
if let imageAnchor = anchor as? ARImageAnchor {
let anchorPositionRelativeToOrigin = node.convertPosition(SCNVector3Zero, to: originNode)

let euler2 = node.eulerAngles
print("Tilt: (euler2.x.rad2deg()), Pan: (euler2.y.rad2deg()), Roll: (euler2.z.rad2deg())")

let anchorTransformRelativeToHome = node.convertTransform(SCNMatrix4(), to: originNode)
let rotation = simd_float4x4(anchorTransformRelativeToHome)
let direction = SIMD3<Float>(-rotation.columns.2.x, -rotation.columns.2.y, -rotation.columns.2.z)

let tiltAngle = atan2(direction.y, direction.z)
let panAngle = atan2(direction.x, direction.z)
let rollAngle = atan2(-rotation.columns.1.x, rotation.columns.0.x)
print("Tilt: (tiltAngle.rad2deg()) Pan: (panAngle.rad2deg()) roll: (rollAngle.rad2deg())")  
}          
}

无论我把图像放在哪个方向,我都能得到这两个打印结果。

Tilt: 0.0, Pan: -0.0, Roll: 0.0
Tilt: -180.0 Pan: -180.0 roll: -0.0

任何帮助都将非常感激。

renderer(_:didUpdate:for:)实例方法

获得pitch,yawroll角度的精确值在这里几乎是不可能的,但是在这种情况下+/-5度是完全可以接受的。顺便说一下,你甚至不需要创建任何originNode,因为ARKit知道ARImageAnchor的世界方向相对于grid的初始方向,当场景正在构建。为了实验的纯度,将跟踪图片放在桌子上并运行应用程序。如果您正在跟踪墙上的图片,则+Y锚的轴指向观看者(当图像是水平的时,+Y轴指向向上)。试着移动/旋转图片

import ARKit
import SceneKit
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode,
for anchor: ARAnchor) {

guard let _ = anchor as? ARImageAnchor else { return }

let cylinderNode = SCNNode()
cylinderNode.geometry = SCNCylinder(radius: 0.05, height: 0.4)
node.addChildNode(cylinderNode)

let ea: SCNVector3 = node.eulerAngles  // anchor's base node orientation

print("Next value...")
print(convert(ea.x), convert(ea.y), convert(ea.z))
}

func convert(_ radiansToDegrees: Float) -> Float {
return radiansToDegrees * 180 / Float.pi
}

ARImageAnchor的base node具有与锚本身相同的方向。


renderer(_:didAdd:for:)实例方法

或者你可以使用renderer(_:didAdd:for:)委托的方法与asyncDispatchQueue

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode,
for anchor: ARAnchor) {

guard let _ = anchor as? ARImageAnchor else { return }

DispatchQueue.main.async {
let cylinderNode = SCNNode()
cylinderNode.geometry = SCNCylinder(radius: 0.05, height: 0.4)
node.addChildNode(cylinderNode)

let ea: SCNVector3 = node.eulerAngles  // registers a single value

print(self.convert(ea.x), self.convert(ea.y), self.convert(ea.z))
}
}

最新更新