如何将已知位置和方向设置为 ARKit 的起点 [英] How to set a known position and orientation as a starting point of ARKit

查看:23
本文介绍了如何将已知位置和方向设置为 ARKit 的起点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am starting to use ARKit and I have a use case where I want to know the motion from a known position to another one.

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

So I was wondering if it is possible (like every tracking solution) to set a known position and orientation a starting point of the tracking in ARKit?

问候

推荐答案

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

There are at least six approaches allowing you set a starting point for a model. But using no ARAnchors at all in your ARScene is considered as bad AR experience (although Apple's Augmented Reality app template has no any ARAnchors in a code).

这是 Apple 工程师在 Xcode 中的 Augmented Reality app 模板中向我们建议的方法.这种方法不使用锚定,所以你需要做的就是在空中容纳一个模型,坐标像 (x: 0, y: 0, z: -0.5) 或者换句话说你的模型距离相机 50 厘米.

This is the approach that Apple engineers propose us in Augmented Reality app template in Xcode. This approach doesn't use anchoring, so all you need to do is to accommodate a model in air with coordinates like (x: 0, y: 0, z: -0.5) or in other words your model will be 50 cm away from camera.

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 的锚点:

Second approach is almost the same as the first one, except it uses ARKit's anchor:

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 模块:

You can also create a pre-defined model's position pinned with ARAnchor using third approach, where you need to import RealityKit module as well:

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).

If you turned on a plane detection feature you can use Ray-casting or Hit-testing methods. As a target object you can use a little sphere (located at 0, 0, 0) that will be ray-casted.

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.

This approach is focused to save and share ARKit's 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 中,新的 ARGeoTrackingConfiguration 是在 MapKit 模块的帮助下实现的.所以现在您可以使用预定义的 GPS 数据.

In ARKit 4.0 a new ARGeoTrackingConfiguration is implemented with the help of MapKit module. So now you can use a pre-defined GPS data.

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

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

这篇关于如何将已知位置和方向设置为 ARKit 的起点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆