You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中基于ARKit稳定USDZ模型位置:漂移问题解决方案求助

ARKit USDZ模型与实物对齐的漂移问题咨询

我正在用Swift开发一款基于ARKit的质量检测APP,需求是将USDZ模型和现实中的对应实物精准对齐(效果类似通过图像锚点辅助的实时对齐视频)。

试过图像跟踪和平面检测两种方法,初始对齐能实现,但存在漂移问题:用户围绕物体移动时,模型会随时间偏移。我想尝试先通过平面检测放置模型(这似乎是锚定物体的最佳方式),再在检测到图像锚点时重置模型位置。但我搞不懂视频里随意放置的扑克牌怎么发挥作用——我能理解它们可以用于Z方向重锚定,但它们本身没有已知坐标,真的能帮助校准X和Y方向吗?

恳请各位提供建议或方案,或许我忽略了更适合这个任务的其他方法。


更新

我采用了基于状态的流程,需要用户完成以下操作:

  • 选择平面
  • 在平面上选择第一个点
  • 在平面上选择第二个点

之后会把模型添加到所选平面,并根据两点间的角度旋转模型。

USDZ模型的原点位于中心线,但用户通常希望将对应表面与所选平面对齐,因此需要通过GUI控件手动上下左右移动模型来调整到最终位置。

以下是我目前用于初始放置模型的代码:

选择目标平面

func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
    guard
        let updatedAnchor = anchor as? ARPlaneAnchor,
        let selectedAnchor = selectedPlaneAnchor,
        updatedAnchor.identifier == selectedAnchor.identifier
    else {
        return
    }
    
    self.selectedPlaneAnchor = updatedAnchor
}

获取定义旋转的第一和第二点

@objc func handleTap(_ gestureRecognizer: UITapGestureRecognizer) {
    // 获取点击在sceneView中的位置
    let tapLocation = gestureRecognizer.location(in: sceneView)
    
    // 执行命中测试,找到点击位置的ARPlaneAnchor
    let hitTestResults = sceneView.hitTest(tapLocation, types: .existingPlaneUsingExtent)
    
    if let result = hitTestResults.first {
        if let detectedPlaneAnchor = result.anchor as? ARPlaneAnchor {
            let p3 = result.worldTransform.columns.3
            
            switch currentState {
                case .initial, .loading, .ready:
                    break
                case .surface:
                    if selectedPlaneAnchor == nil {
                        selectedPlaneAnchor = detectedPlaneAnchor
                        currentState = .point1
                    }
                case .point1:
                    if detectedPlaneAnchor.identifier == selectedPlaneAnchor?.identifier {
                        firstPoint = SCNVector3(p3.x,p3.y,p3.z)
                        addPointNode(location: firstPoint!)
                        currentState = .point2
                    }
                case .point2:
                    if detectedPlaneAnchor.identifier == selectedPlaneAnchor?.identifier {
                        secondPoint = SCNVector3(p3.x,p3.y,p3.z)
                        addPointNode(location: secondPoint!)
                        addAssemblyNode()
                        currentState = .ready
                    }
            }
        }
    }
}

将模型添加到平面并相应旋转

func addAssemblyNode() {
    guard
        let usdzURL = Bundle.main.url(forResource: "art.scnassets/assembly", withExtension: "usdz"),
        let p1 = firstPoint,
        let p2 = secondPoint
    else {
        return
    }
    
    let assemblyScene = try! SCNScene(url: usdzURL, options: nil)
    
    let directionVector = SCNVector3(p2.x - p1.x, p2.y - p1.y,p2.z - p1.z)
    let rotationAngle = atan2f(directionVector.z, directionVector.x)
    
    if let node = assemblyScene.rootNode.childNode(withName: "main", recursively: true) {
        node.name = "main"
        
        node.position = p1
        node.eulerAngles.y = -rotationAngle
        //node.scale = SCNVector3(x: 0.125, y: 0.125, z: 0.125)
        sceneView.scene.rootNode.addChildNode(node)
        
        assemblyNode = node
    }
}

另有视频展示了漂移效果:当回到初始位置时,末端的蓝色大平板会回到原位。


内容的提问来源于stack exchange,提问作者Joel S.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 18:32:16