【问题标题】:How to keep ARKit SCNNode in place如何保持 ARKit SCNNode 就位
【发布时间】:2017-12-14 16:03:07
【问题描述】:

嘿,我想弄清楚。如何保留一个简单的节点。当我在 ARKit 中走动时

代码:

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

    if let planeAnchor = anchor as? ARPlaneAnchor {

    if planeDetected == false { // Bool only allows 1 plane to be added
            planeDetected = true
        self.addPlane(node: node, anchor: planeAnchor)
    }

    }
}

这会添加 SCNNode

    func addPlane(node: SCNNode, anchor: ARPlaneAnchor) {

    // We add the anchor plane here

    let showDebugVisuals = Bool()
    let plane = Plane(anchor, showDebugVisuals)
    planes[anchor] = plane
    node.addChildNode(plane)



    // We add our custom SCNNode here 

    let scene = SCNScene(named: "art.scnassets/PlayerModel.scn")!
    let Body = scene.rootNode.childNode(withName: "Body", recursively: true)!

    Body.position = SCNVector3.positionFromTransform(anchor.transform)
    Body.movabilityHint = .movable
    wrapperNode.position = SCNVector3.positionFromTransform(anchor.transform)

    wrapperNode.addChildNode(Body)

    scnView.scene.rootNode.addChildNode(wrapperNode)

我尝试添加一个平面/锚节点并将“身体”节点放入其中,但它仍然移动。我想也许它与更新功能有关。

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

或者很可能是位置设置

wrapperNode.position = SCNVector3.positionFromTransform(anchor.transform)

我浏览了互联网上的每个源/项目文件/视频,没有人能简单地解决这个简单的问题。

【问题讨论】:

  • 没有简单的解决方案。您应该使用表面检测以获得更好的结果,但物体仍然会移动一点。
  • 好的,感谢您确认这实际上不是一个简单的解决方案。

标签: ios swift arkit


【解决方案1】:

这里可能发生两种“四处走动”。


其中一个原因是 ARKit 不断改进其对设备在现实世界中的位置如何映射到您放置虚拟内容的抽象坐标空间的估计。例如,假设您将虚拟对象放置在 (0, 0, -0.5),并且然后将您的设备向左移动 10 厘米。仅当 ARKit 精确跟踪移动时,虚拟对象才会看起来锚定在物理空间中。但是视觉惯性里程计并不是一门精确的科学,所以 ARKit 可能认为你向左移动了 10.5 厘米——在这种情况下,你的虚拟对象看起来会向右“滑动”5 毫米,尽管它的ARKit/SceneKit 坐标空间中的位置保持不变。

除了希望 Apple 制造具有更好传感器、更好摄像头或更好 CPU/GPU 的设备并改进世界追踪科学之外,你真的无能为力。 (在时间充裕的情况下,这可能是一个安全的选择,尽管这可能对您当前的项目没有帮助。)


由于您还要处理平面检测,因此还有另一个问题。 ARKit 不断完善其对检测到的平面位置的估计。所以,即使平面的真实世界位置没有改变,它在 ARKit/SceneKit 坐标空间中的位置是变化的。

这种移动通常是一件好事——如果您希望虚拟对象看起来锚定在现实世界的表面上,您需要确定该表面的位置。当平面检测更确定表面的位置时,您会看到一些移动,但在短时间内,您应该看到更少的“滑动”,因为您移动相机以寻找平面锚定的虚拟对象,而不是那些只是漂浮在世界中的对象空间。


不过,在您的代码中,您并没有利用平面检测来使您的自定义内容(来自“PlayerModel.scn”)坚持到平面锚点:

wrapperNode.position = SCNVector3.positionFromTransform(anchor.transform)
wrapperNode.addChildNode(Body)
scnView.scene.rootNode.addChildNode(wrapperNode)

此代码使用平面锚点的初始 位置将wrapperNode 定位在世界空间中(因为您将其设为根节点的子节点)。如果您改为将wrapperNode 设置为平面锚节点的子节点(您在renderer(_:didAdd:for:) 中收到的那个),它将保持连接到平面,因为 ARKit 会改进其对平面位置的估计。最初您会获得更多的运动,但随着平面检测“稳定”,您的虚拟对象将“滑动”更少。

(当您将节点设置为平面的子节点时,您不需要设置它的位置 - 零位置意味着它正好在平面所在的位置。无论如何,您只需要设置它相对于平面的位置平面——即上面/下面/沿着它多远。)

【讨论】:

  • Apple Dev 在这个项目中提供了更多细节示例github.com/gao0122/ARKit-Example-by-Apple 它解释一切正确而简单。
  • @rickster 非常感谢您富有洞察力的回复。我也遇到了与 OP 相同的问题,因为每当我离开 1-3 米时,我的 3D 模型有时会漂移 20 厘米。这是预期的吗?为什么 IKEA Place 的家具物品没有那么大的移动?谢谢!
  • @aviggiano,我在我们的一个 AR 项目中也面临这样的问题。只是想确认您是否找到任何解决方案?
  • @a.palo 不,我没有找到解决方案,但由于我不再使用 AR 应用程序,所以我停止尝试
  • 嘿@Rickster,非常感谢您的详细回答!我和我的团队在一个问题上停留了好几天啊:/我发布了一个有趣的问题:stackoverflow.com/questions/63662318/…希望您提出建议!
【解决方案2】:

要保持 SCNNode 就位,您可以在获得所需结果后禁用场景视图平面检测。

let configuration = ARWorldTrackingConfiguration(); configuration.planeDetection = [] self.sceneView.session.run(configuration)

原因是 ARKit 不断地重新估计检测到的平面的位置,导致 SCNNode 移动。

【讨论】:

    猜你喜欢
    • 2019-01-30
    • 2017-12-22
    • 2018-01-30
    • 2018-02-22
    • 2018-09-01
    • 2018-08-04
    • 2018-08-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多