【问题标题】:How to set a known position and orientation as a starting point of ARKit如何将已知位置和方向设置为 ARKit 的起点
【发布时间】:2019-07-05 09:47:31
【问题描述】:

我开始使用 ARKit,我有一个用例,我想知道从已知位置到另一个位置的运动。

所以我想知道是否有可能(就像每个跟踪解决方案一样)在 ARKit 中设置一个已知的位置和方向作为跟踪的起点?

问候

【问题讨论】:

  • 检查位置、旋转、方向和 eulerangles 属性developer.apple.com/documentation/scenekit/scnnode/… git 上有示例源代码可用于计算长度/距离
  • 您能否澄清一下“已知职位”的含义?你的意思是:一个标记图像;与场景的世界原点相关的节点;特定的地理位置;平面上的节点?还是“映射”环境中的特定位置?

标签: swift computer-vision augmented-reality arkit realitykit


【解决方案1】:

至少有六种方法可以让您为模型设置起点。但是在您的 ARScene 中根本不使用 ARAnchors 被认为是糟糕的 AR 体验(尽管 Apple 的增强现实应用程序模板在代码中没有任何 ARAnchors)。

第一种方法

这是 Apple 工程师在 Xcode 中的Augmented Reality app 模板中向我们建议的方法。这种方法不使用锚定,因此您需要做的就是将模型放置在空中,其坐标类似于 (x: 0, y: 0, z: -0.5),或者换句话说,您的模型将距离相机 50 厘米。

override func viewDidLoad() {
    super.viewDidLoad()
    
    sceneView.scene = SCNScene(named: "art.scnassets/ship.scn")!
    let model = sceneView.scene.rootNode.childNode(withName: "ship", 
                                                recursively: true)
    model?.position.z = -0.5
    sceneView.session.run(ARWorldTrackingConfiguration())
}


第二种方法

第二种方法与第一种几乎相同,只是它使用了 ARKit 的锚点:

guard let sceneView = self.view as? ARSCNView 
else { return }

if let currentFrame = sceneView.session.currentFrame {
        
    var translation = matrix_identity_float4x4
    translation.columns.3.z = -0.5
    let transform = simd_mul(currentFrame.camera.transform, translation)
        
    let anchor = ARAnchor(transform: transform)
    sceneView.session.add(anchor: anchor)
}


第三种方法

您还可以使用第三种方法创建使用 ARAnchor 固定的预定义模型位置,您还需要导入 RealityKit 模块:

func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {
            
    let model = ModelEntity(mesh: MeshResource.generateSphere(radius: 1.0))

    // ARKit's anchor
    let anchor = ARAnchor(transform: simd_float4x4(diagonal: [1,1,1]))
    
    // RealityKit's anchor based on position of ARAnchor
    let anchorEntity = AnchorEntity(anchor: anchor)

    anchorEntity.addChild(model)
    arView.scene.anchors.append(anchorEntity)
}


第四种方法

如果您启用了平面检测功能,则可以使用光线投射或命中测试方法。作为目标对象,您可以使用一个小球体(位于0, 0, 0),该球体将进行射线投射。

let query = arView.raycastQuery(from: screenCenter,
                            allowing: .estimatedPlane,
                           alignment: .any)

let raycast = session.trackedRaycast(query) { results in

    if let result = results.first {
        object.transform = result.transform
    } 
}


第五种方法

这种方法专注于保存和分享 ARKit 的worldMaps

func writeWorldMap(_ worldMap: ARWorldMap, to url: URL) throws {

    let data = try NSKeyedArchiver.archivedData(withRootObject: worldMap, 
                                         requiringSecureCoding: true)
    try data.write(to: url)
}

func loadWorldMap(from url: URL) throws -> ARWorldMap {

    let mapData = try Data(contentsOf: url)
    guard let worldMap = try NSKeyedUnarchiver.unarchivedObject(ofClass: ARWorldMap.self, 
                                                                   from: mapData) 
    else { 
        throw ARError(.invalidWorldMap) 
    }
    return worldMap
}


第六种方法

在 ARKit 4.0 中,借助 MapKit 模块实现了一个新的ARGeoTrackingConfiguration。所以现在您可以使用预定义的 GPS 数据了。

func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
   
    for geoAnchor in anchors.compactMap({ $0 as? ARGeoAnchor }) {

        arView.scene.addAnchor(Entity.placemarkEntity(for: geoAnchor)
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-20
    • 1970-01-01
    • 2019-12-07
    • 1970-01-01
    • 1970-01-01
    • 2017-12-05
    • 1970-01-01
    相关资源
    最近更新 更多