Ios 如何将ARKit SCNNode保持在适当的位置

Ios 如何将ARKit SCNNode保持在适当的位置,ios,swift,arkit,Ios,Swift,Arkit,嘿,我在想办法。如何将简单节点保持在适当的位置。当我在ARKit里绕着它走的时候 代码: 这将添加SCNNode func addPlane(node: SCNNode, anchor: ARPlaneAnchor) { // We add the anchor plane here let showDebugVisuals = Bool() let plane = Plane(anchor, showDebugVisuals) planes[anch

嘿,我在想办法。如何将简单节点保持在适当的位置。当我在ARKit里绕着它走的时候

代码:

这将添加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)
我尝试添加一个平面/锚节点,并将“Body”节点放入其中,但它仍在移动。我想可能跟更新功能有关

 func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
 }
最有可能是位置设置

wrapperNode.position = SCNVector3.positionFromTransform(anchor.transform)
Iv'e浏览了互联网上的每一个来源/项目文件/视频,没有人能找到解决这个简单问题的简单方法

这里可能会发生两种“移动”


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

除了希望苹果能制造出具有更好的传感器、更好的摄像头或更好的CPU/GPU的设备,并提高世界跟踪的科学性之外,你真的做不了什么。(在充分的时间内,这可能是一个安全的赌注,尽管这可能对您当前的项目没有帮助。)


既然你也在处理飞机检测,还有一个问题。ARKit正在不断完善对被探测飞机位置的估计。因此,即使飞机的真实位置没有改变,它在ARKit/SceneKit坐标空间中的位置也会改变

这种移动通常是一件好事——如果希望虚拟对象显示为锚定到真实世界的曲面,则需要确定该曲面的位置。随着平面检测更加确定曲面的位置,您将看到一些移动,但在短时间后,与仅在世界空间中浮动的虚拟对象相比,在移动平面定位虚拟对象的摄影机时,您应该会看到较少的“滑动”


但是,在代码中,您没有利用平面检测使自定义内容(来自“PlayerModel.scn”)粘附到平面锚点:

wrapperNode.position = SCNVector3.positionFromTransform(anchor.transform)
wrapperNode.addChildNode(Body)
scnView.scene.rootNode.addChildNode(wrapperNode)
此代码使用平面定位点的初始位置来定位世界空间中的
wrapperNode
(因为您将其设置为根节点的子节点)。如果改为将
wrapperNode
作为平面锚点节点的子节点(您在
渲染器(u:didAdd:for:)
中收到的节点),则在ARKit细化其对平面位置的估计时,它将保持与平面的连接。最初,您将获得更多的运动,但随着平面检测的“稳定”,您的虚拟对象将更少地“滑动”


(当您将节点设置为平面的子节点时,不需要设置其位置-零的位置表示它就在平面所在的位置。如果需要,则只需要设置其相对于平面的位置-即,在平面上方/下方/沿平面的距离。)

要保持SCNNode在适当位置,您可以在获得所需结果后禁用sceneView平面检测

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


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

没有简单的解决方案。为了获得更好的结果,您应该使用表面检测,但对象仍然会移动一点。好的,感谢您确认这实际上不是一个简单的解决方案。Apple Dev在本项目中提供了更多详细的示例,它正确而简单地解释了一切。@rickster非常感谢您富有洞察力的回答。我也有同样的问题作为OP,因为我的3D模型有时漂移20厘米,每当我移动1-3米远离它。这是预期的吗?为什么宜家家居的家具不经常搬家?谢谢@阿维吉亚诺,在我们的一个AR项目中,我也面临着这样的问题。我只是想确认一下,你找到了同样的解决方案吗?@a.palo没有,我没有找到解决方案,但因为我不再做AR应用程序,我停止了尝试嘿@Rickster,非常感谢你的详细回答!我和我的团队在一个问题上纠缠了好几天啊:/我发布了一个有趣的问题:会喜欢你的建议的!
wrapperNode.position = SCNVector3.positionFromTransform(anchor.transform)
wrapperNode.addChildNode(Body)
scnView.scene.rootNode.addChildNode(wrapperNode)