问题描述
我开始使用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?
致谢
推荐答案
至少有六种方法可让您设置模型的起点.但是在您的ARS场景中完全不使用锚定被认为是不良的AR体验(尽管Apple的增强现实"应用模板的代码中没有任何ARAnchors.
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应用程序
模板中向我们推荐的方法.这种方法不使用锚定,因此您要做的就是将模型容纳在具有(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中,借助MapKit模块实现了新的 ARGeoTrackingConfiguration .因此,现在您可以使用预定义的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的起点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!