我正在使用 ARKit 构建一个简单的导航应用程序。该应用程序会在目的地(可能很远或附近)上显示图钉。用户能够走向图钉进行导航。
在我的ARSCNView
中,我有一个名为waypointNode
的SCNNode
,它表示目标位置的引脚。
为了确定waypointNode
的放置位置,我以米为单位计算了distance
到目的地的距离,并计算了bearing
(与北方的距离)。然后,我创建并乘以一些转换并将其应用于节点以将其放置在适当的位置。
还有一些逻辑可以确定waypointNode
的最大距离,因此对于用户来说,它的距离不能太小。
这就是我配置ARSCNView
的方式,因此轴与 real-world 罗盘方向对齐:
func setUpSceneView() {
let configuration = ARWorldTrackingConfiguration()
configuration.worldAlignment = .gravityAndHeading
configuration.planeDetection = .horizontal
session.run(configuration, options: [.resetTracking])
}
每次设备从 CoreLocation 获取新的 CLLocation 时,我都会更新distance
和bearing
,然后调用此函数来更新waypointNode
的位置:
func updateWaypointNode() {
// limit the max distance so the node doesn't become invisible
let distanceLimit: Float = 80
let translationDistance: Float
if navigationInfo.distance > distanceLimit {
translationDistance = distanceLimit
} else {
translationDistance = navigationInfo.distance
}
// transform matrix to adjust node distance
let distanceTranslation = SCNMatrix4MakeTranslation(0, 0, -translationDistance)
// transform matrix to rotate node around y-axis
let rotation = SCNMatrix4MakeRotation(-1 * GLKMathDegreesToRadians(Float(navigationInfo.bearing)), 0, 1, 0)
// multiply the rotation and distance translation matrices
let distanceTimesRotation = SCNMatrix4Mult(distanceTranslation, rotation)
// grab the current camera transform
guard let cameraTransform = session.currentFrame?.camera.transform else { return }
// multiply the rotation and distance translation transform by the camera transform
let finalTransform = SCNMatrix4Mult(SCNMatrix4(cameraTransform), distanceTimesRotation)
// update the waypoint node with this updated transform
waypointNode.transform = finalTransform
}
当用户第一次开始会话时,以及当用户移动不到 100m 时,这种方法都可以正常工作。
一旦用户覆盖相当长的距离,例如超过 100m 的步行或驾车,仅呼叫updateWaypointNode()
就不足以维持节点在目的地的正确位置。例如,当走向节点时,即使用户尚未到达目的地,用户也有可能最终到达该节点。注意:这种不正确的定位发生在会话始终打开的过程中,而不是如果会话被中断。
作为一种解决方法,每次设备更新位置信息时,我也会拨打 setUpSceneView().
即使这样可以正常工作,但对我来说还是错的。似乎我不必每次都用.resetTracking
选项调用run
。我想我可能只是忽略了翻译中的某些内容。我还看到,每次在运行会话时调用run
时,照相机中都会出现一些跳跃现象,因此,这比简单地更新翻译要少。
是否有其他方法可以避免在设备每次获取位置更新时避免调用会话运行并重置跟踪?