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

huangapple go评论66阅读模式
英文:

How to get orientation of an ARImageAnchor in relation to a given SCNNode?

问题

I'll provide the translation of the code portion:

如何获取与给定的`SCNNode``ARKit`中的`ARImageAnchor`的方向数据?这是基本的情景。

AR会话启动后某个时刻放置了一个节点。假设它的名称是*originNode*。然后,`ARKit`用于扫描环境中放置的图像。当摄像机检测到图像时,我想要计算检测到的图像相对于*originNode*XYZ和方向`tilt``pan``roll`)。请注意,从一开始,设备被固定在UIDeviceOrientation.landscapeRight

因此,用户可以在水平持设备并将摄像头指向前方的情况下扫描图像,或者设备水平放置并将摄像头直接指向下方。

当我扫描放在桌子上的图像时,我认为我当前的代码提供的数值是准确的。

配置:

```swift
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

希望这能帮助您。


<details>
<summary>英文:</summary>

How do I get orientation data of an `ARImageAnchor` in relation to a given `SCNNode` in `ARKit`? This is the basic scenario. 

A node placed at some point after the AR session has been started. Let&#39;s say its named *originNode*. Then `ARKit` is used to scan for image placed in the environment. When the camera detects an image, I want to calculate the X, Y, Z and the orientation (`tilt`, `pan`, `roll`) of the detected image relative to the *originNode*. Please note that the device is fixed at UIDeviceOrientation.landscapeRight from the start. 

So the user can either scan for images while holding the device horizontally and camera pointing forward, or device is horizontal and camera is pointing directly down.

When I scan an image placed flat on a table, the values I&#39;m getting with my current code is accurate I believe

Configuration:

    let configuration = ARWorldTrackingConfiguration()

    guard let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: &quot;AR Resources&quot;,
                                                                       bundle: nil)
    else { fatalError(&quot;Missing expected asset catalog resources.&quot;) }

    configuration.detectionImages = referenceImages
    configuration.maximumNumberOfTrackedImages = 100

Delegate:

    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(&quot;Tilt: \(euler2.x.rad2deg()), Pan: \(euler2.y.rad2deg()), Roll: \(euler2.z.rad2deg())&quot;)
            
            let anchorTransformRelativeToHome = node.convertTransform(SCNMatrix4(), to: originNode)
            let rotation = simd_float4x4(anchorTransformRelativeToHome)

            let direction = SIMD3&lt;Float&gt;(-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(&quot;Tilt: \(tiltAngle.rad2deg()) Pan: \(panAngle.rad2deg()) roll: \(rollAngle.rad2deg())&quot;)  
        }          
    }

These are the two print results I get no matter which orientation I place the image. 

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

Any help would be much appreciated.



</details>


# 答案1
**得分**: 1

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

获取 `pitch`、`yaw` 和 `roll` 角的精确值在这种情况下几乎不可能,但在此情况下,+/-5度是相当可接受的。顺便说一句,您甚至不需要创建任何 `originNode`,因为ARKit知道ARImageAnchor相对于`grid`初始方向的世界方向,当场景正在构建时。为了进行实验,请将一个跟踪图片放在桌子上并运行应用程序。如果您正在跟踪墙上的图片,那么+Y锚点的轴朝向观众(当图像水平时,+Y轴向上)。尝试移动/旋转一张图片。

```swift
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  // 锚点的基本节点方向
        
    print("下一个值...")
    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:) 实例方法

或者,您可以使用具有异步 DispatchQueuerenderer(_:didAdd:for:) 代理方法。

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  // 注册单个值
            
        print(self.convert(ea.x), self.convert(ea.y), self.convert(ea.z))
    }
}
英文:

renderer(_:didUpdate:for:) instance method

Getting precise values for pitch, yaw and roll angles are hardly possible here, but +/-5 degrees in this situation is quite acceptable. By the way, you do not even need to create any originNode, since ARKit knows the world orientation of the ARImageAnchor relative to the initial orientation of the grid when the scene is being built. For the purity of the experiment, put a tracking picture on the table and run the app. If you are tracking a picture on a wall, then the +Y anchor's axis is directed towards the viewer (when the image is horizontal, the +Y axis is directed upwards). Try to move/rotate a picture.

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&#39;s base node orientation
        
    print(&quot;Next value...&quot;)
    print(convert(ea.x), convert(ea.y), convert(ea.z))
}
    
func convert(_ radiansToDegrees: Float) -&gt; Float {
    return radiansToDegrees * 180 / Float.pi
}

ARImageAnchor's base node has the same orientation as the anchor itself.

<br></br>

renderer(_:didAdd:for:) instance method

Or you can use renderer(_:didAdd:for:) delegate's method with async DispatchQueue.

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))
    }
}

huangapple
  • 本文由 发表于 2023年4月7日 01:19:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75952160.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定