首页 > 解决方案 > ARAnchor 到底是什么?

问题描述

我正在尝试理解和使用 ARKit。但是有一件事我不能完全理解。

Apple 谈到 ARAnchor:

可用于在 AR 场景中放置对象的真实位置和方向。

但这还不够。所以我的问题是:

标签: swiftaugmented-realityarkitrealitykit

解决方案


更新日期:2022 年 2 月 11 日

TL;博士


锚点

ARAnchor是一个不可见的空对象,可以在世界空间中的锚点位置保存 3D 模型。想想ARAnchor它是一个transform node带有局部轴的模型(您可以平移、旋转和缩放它)。每个 3D 模型都有一个枢轴点,对吧?所以这个枢轴点必须满足一个ARAnchor.

如果您不在ARKit/ RealityKitapp 中使用锚点,您的 3D 模型可能会偏离它们放置的位置,这将极大地影响您的应用程序的真实性和用户体验。因此,锚点是 AR 场景的关键元素。

根据 ARKit 文档 2017:

ARAnchor是一个真实世界的位置和方向,可用于在 AR 场景中放置对象。在会话中添加锚点有助于 ARKit 优化该锚点周围区域的世界跟踪精度,以便虚拟对象相对于现实世界似乎保持在原位。如果虚拟对象移动,则从旧位置移除相应的锚点,并在新位置添加一个。

ARAnchor是 ARKit 框架中存在的所有其他类型锚的父类,因此所有这些子类都继承自ARAnchor类,但不能直接在代码中使用它。我也必须这么说,ARAnchor没有Feature Points任何共同点。Feature Points而是用于成功跟踪和调试。

ARAnchor不会自动跟踪现实世界的目标。如果您需要自动化,则必须使用renderer(...)session(...)实例化方法,如果您符合协议ARSCNViewDelegateARSessionDelegate分别调用这些方法。

这是具有平面锚点视觉表示的图像。但请记住:默认情况下,您既看不到检测到的平面,也看不到其对应的ARPlaneAnchor. 因此,如果您想在场景中看到任何锚点,您必须使用三个薄SCNCylinder图元“可视化”它。


在此处输入图像描述


在 ARKit 中,您可以ARAnchors使用不同的场景自动添加到场景中

  • ARPlaneAnchor

    • 如果水平和/或垂直planeDetection实例属性为ON,则 ARKit 能够将 ARPlaneAnchors 添加到当前会话。有时启用会planeDetection大大增加场景理解阶段所需的时间。
  • ARImageAnchor符合ARTrackable协议

    • 这种类型的锚点包含有关在世界跟踪会话中检测到的图像(锚点位于图像中心)的位置和方向的信息。对于激活使用detectionImages实例属性。在 ARKit 2.0 中,您最多可以跟踪 25 张图像,在 ARKit 3.0 和 ARKit 4.0 中,最多分别为 100 张图像。但是,在这两种情况下,同时不超过 4 张图像。有人承诺,在 ARKit 5.0 中,您一次可以检测和跟踪多达 100 张图像(但尚未实现)。
  • ARBodyAnchor符合ARTrackable协议

    • 在最新版本的 ARKit 中,您可以通过使用ARBodyTrackingConfiguration(). 您将在Root JointCG Skeleton 或被跟踪角色的骨盆位置获得 ARBodyAnchor。
  • ARFaceAnchor符合ARTrackable协议

    • Face Anchor 存储有关拓扑和姿势的信息,以及您可以使用前置 TrueDepth 摄像头或常规 RGB 摄像头检测到的面部表情。当检测到人脸时,人脸锚点将被附加在鼻子后面,人脸中央。在 ARKit 2.0 中,您只能跟踪一张人脸,在 ARKit 3.0 中,最多可以同时跟踪 3 张人脸。在 ARKit 4.0 中,许多人脸跟踪取决于 TrueDepth 传感器和 CPU:配备 TrueDepth 摄像头的智能手机最多可以跟踪 3 个人脸,配备 A12+ 芯片组但没有 TrueDepth 摄像头的智能手机也可以跟踪最多 3 个人脸。
  • ARObjectAnchor

    • 此锚点的类型保留有关在世界跟踪会话中检测到的真实世界 3D 对象的 6 个自由度(位置和方向)的信息。请记住,您需要为会话配置ARReferenceObject的属性指定实例。detectionObjects
  • AREnvironmentProbeAnchor

    • Probe Anchor 为世界跟踪会话中的特定空间区域提供环境照明信息。ARKit 的人工智能使用它为反射着色器提供环境反射。
  • AR参与者锚

    • 这是多用户 AR 体验不可或缺的锚类型。如果要使用它,请在框架中使用实例属性的true值。isCollaborationEnabledMultipeerConnectivity
  • ARMeshAnchor

    • ARKit 和 LiDAR 将用户周围重建的真实世界场景细分为具有相应多边形几何形状的网格锚点。随着 ARKit 改进对现实世界的理解,网格锚点会不断更新其数据。尽管 ARKit 会更新网格以反映物理环境的变化,但网格的后续变化并不旨在实时反映。有时,您重建的场景可能有多达50 anchors甚至更多。这是因为每个分类对象(墙壁、椅子、门或桌子)都有自己的个人锚。每个 ARMeshAnchor 存储有关相应顶点的数据,八种分类案例之一,其面和顶点法线。
  • ARGeoAnchor(符合ARTrackable协议)

    • 在 ARKit 4.0+ 中,有一个地理锚(又名位置锚),它使用 GPS、Apple 地图和来自 Apple 服务器的其他环境数据来跟踪地理位置。这种类型的锚标识了应用程序可以引用的世界特定区域。当用户在场景中移动时,会话会根据地理锚点的坐标和设备的罗盘方向更新位置锚点的变换。查看支持的城市列表。
  • ARAppClipCodeAnchor(符合ARTrackable协议)

    • 这个锚点在 ARKit 4.0+ 的物理环境中跟踪App Clip Code的位置和方向。您可以使用 App Clip Codes 让用户在现实世界中发现您的 App Clip。有 NFC 集成的 App Clip Code 和仅扫描 App Clip Code。

在此处输入图像描述


还有其他常规方法可以在 AR 会话中创建锚点

  • 命中测试方法

    • 点击屏幕,将一个点投影到一个不可见的检测平面上,将 ARAnchor 放置在假想光线与该平面相交的位置。顺便说一句,ARHitTestResultARSCNView 和 ARSKView 的类及其对应的命中测试方法将在 iOS 14 中被弃用,因此您必须习惯 Ray-Casting。
  • 光线投射方法

    • 如果您使用的是光线投射,点击屏幕会在一个不可见的检测平面上生成一个投影的 3D 点。但您也可以在 3D 场景中的 A 和 B 位置之间执行光线投射。Ray-Casting 与 Hit-Testing 的主要区别在于,当使用第一个 ARKit 时,它可以不断细化光线投射,因为它了解更多关于检测到的表面,并且 Ray-Casting 可以是 2D-to-3D 和 3D-to- 3D。
  • 特征点

    • ARKit 在现实世界对象的高对比度边缘上自动生成的特殊黄点可以为您提供放置 ARAnchor 的位置。
  • ARCamera 的变换

    • iPhone 的摄像头位置和方向simd_float4x4可以很容易地用作 ARAnchor 的位置。
  • 任意世界位置

    • 将自定义ARWorldAnchor放置在场景中的任何位置。你可以在 RealityKit 中生成类似 ARKit 的world anchor版本AnchorEntity(.world(transform: mtx))


此代码片段向您展示了如何在委托的方法中使用 ARPlaneAnchor renderer(_:didAdd:for:)::

func renderer(_ renderer: SCNSceneRenderer, 
             didAdd node: SCNNode, 
              for anchor: ARAnchor) {
    
    guard let planeAnchor = anchor as? ARPlaneAnchor 
    else { return }

    let grid = Grid(anchor: planeAnchor)
    node.addChildNode(grid)
}



锚实体

AnchorEntity 是 RealityKit 中的 alpha 和 omega。根据 RealityKit 文档 2019:

AnchorEntity是在 AR 会话中将虚拟内容与现实世界对象联系起来的锚点。

RealityKit框架和Reality Composer应用程序于 WWDC'19 发布。他们有一个名为AnchorEntity. 您可以使用 AnchorEntity 作为任何实体层次结构的根点,并且必须将其添加到场景锚点集合中。AnchorEntity 自动跟踪现实世界的目标。在 RealityKit 和 Reality ComposerAnchorEntity中,位于层次结构的顶部。这个锚可以容纳一百个模型,在这种情况下,它比为每个模型使用 100 个个人锚更稳定。

让我们看看它在代码中的样子:

func makeUIView(context: Context) -> ARView {
    
    let arView = ARView(frame: .zero)
    let modelAnchor = try! Experience.loadModel()
    arView.scene.anchors.append(modelAnchor)
    return arView
}

AnchorEntity包含三个组成部分:

要找出两者之间的区别ARAnchorAnchorEntity查看THIS POST

以下是适用于 iOS 的 RealityKit 2.0 中可用的九个 AnchorEntity 案例:

// Fixed position in the AR scene
AnchorEntity(.world(transform: mtx)) 

// For body tracking (a.k.a. Motion Capture)
AnchorEntity(.body)

// Pinned to the tracking camera
AnchorEntity(.camera)

// For face tracking (Selfie Camera config)
AnchorEntity(.face)

// For image tracking config
AnchorEntity(.image(group: "GroupName", name: "forModel"))

// For object tracking config
AnchorEntity(.object(group: "GroupName", name: "forObject"))

// For plane detection with surface classification
AnchorEntity(.plane([.any], classification: [.seat], minimumBounds: [1, 1]))

// When you use ray-casting
AnchorEntity(raycastResult: myRaycastResult)

// When you use ARAnchor with a given identifier
AnchorEntity(.anchor(identifier: uuid))

// Creates anchor entity on a basis of ARAnchor
AnchorEntity(anchor: arAnchor) 

以下是适用于 macOS 的 RealityKit 2.0 中只有两个 AnchorEntity 的案例:

// Fixed world position in VR scene
AnchorEntity(.world(transform: mtx))

// Camera transform
AnchorEntity(.camera)

此外,您可以根据需要使用任何子类也不是多余ARAnchorAnchorEntity

func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {

    guard let faceAnchor = anchors.first as? ARFaceAnchor 
    else { return }

    arView.session.add(anchor: faceAnchor)

    let anchor = AnchorEntity(anchor: faceAnchor)
    anchor.addChild(model)        
    arView.scene.anchors.append(anchor)
}


Reality Composer 的主播:

目前(2022 年 2 月)Reality Composer 只有 4 种类型的 AnchorEntities:

在此处输入图像描述

// 1a
AnchorEntity(plane: .horizontal)

// 1b
AnchorEntity(plane: .vertical)

// 2
AnchorEntity(.image(group: "GroupName", name: "forModel"))

// 3
AnchorEntity(.face)

// 4
AnchorEntity(.object(group: "GroupName", name: "forObject"))


AR USD 模式

当然,关于初选主播,我应该说几句。对于那些喜欢为 USDZ 模型编写 Python 脚本的人,有 3 种初步锚定类型(2022 年 2 月)——它们是planeimage初步face锚定。查看此代码片段以了解如何以 Python 方式实现模式。

def Cube "ImageAnchoredBox" (prepend apiSchemas = ["Preliminary_AnchoringAPI"])
{
    uniform token preliminary:anchoring:type = "image"
    rel preliminary: imageAnchoring:referenceImage = <ImageReference>

    def Preliminary_ReferenceImage "ImageReference"
    {
        uniform asset image = @somePicture.jpg@
        uniform double physicalWidth = 45
    }
}


可视化 AnchorEntity

这是一个如何在 RealityKit(mac 版)中可视化锚点的示例。

import AppKit
import RealityKit

class ViewController: NSViewController {
    
    @IBOutlet var arView: ARView!
    var model = Entity()
    let anchor = AnchorEntity()

    fileprivate func visualAnchor() -> Entity {

        let colors: [SimpleMaterial.Color] = [.red, .green, .blue]

        for index in 0...2 {
            
            let box: MeshResource = .generateBox(size: [0.20, 0.005, 0.005])
            let material = UnlitMaterial(color: colors[index])              
            let entity = ModelEntity(mesh: box, materials: [material])

            if index == 0 {
                entity.position.x += 0.1

            } else if index == 1 {
                entity.transform = Transform(pitch: 0, yaw: 0, roll: .pi/2)
                entity.position.y += 0.1

            } else if index == 2 {
                entity.transform = Transform(pitch: 0, yaw: -.pi/2, roll: 0)
                entity.position.z += 0.1
            }
            model.scale *= 1.5
            self.model.addChild(entity)
        }
        return self.model
    }

    override func awakeFromNib() {
        anchor.addChild(self.visualAnchor())
        arView.scene.addAnchor(anchor)
    }
}

在此处输入图像描述


推荐阅读