Reputation: 123
I'm trying to display geotracking status and camera tracking state on UI. I've tried func session(_ session: ARSession, didUpdate frame: ARFrame) and func session(_ session: ARSession, didChange geoTrackingStatus: ARGeoTrackingStatus) to obtain geotracking state, but it showed nothing. I also tried func session(_ session: ARSession, cameraDidChangeTrackingState camera: ARCamera) to display camera tracking state, but it showed nothing neither. Could someone help me out? Thanks.
ContentView
import SwiftUI
import ARKit
import RealityKit
struct ContentView: View {
@State var viewModel = ARViewContainer.ViewModel()
var body: some View {
ZStack {
ARViewContainer(viewModel: $viewModel)
.ignoresSafeArea(.all)
VStack(alignment: .leading) {
Text("Camera State: \(viewModel.cameraTrackingStatus)")
Text("GeoTracking State: \(viewModel.geoTrackingStatus)")
Text("Accuracy: \(viewModel.accuracy)")
}
.font(.system(size: 20))
.position(x: 92, y: 36)
}
}
}
struct ARViewContainer: UIViewRepresentable {
struct ViewModel {
var notAvailable = false
var geoTrackingStatus = ""
var cameraTrackingStatus = ""
var accuracy = ""
}
@Binding var viewModel: ViewModel
let arView = ARView(frame: .zero)
func makeUIView(context: Context) -> ARView {
if ARGeoTrackingConfiguration.isSupported {
ARGeoTrackingConfiguration.checkAvailability { available, error in
if !available {
viewModel.notAvailable = true
print("GeoTracking is not available at your location")
}
}
} else {
print("Your Decive support ARGeoTracking")
}
let config = ARGeoTrackingConfiguration()
arView.automaticallyConfigureSession = false
arView.session.run(config)
context.coordinator.addCoaching()
return arView
}
func makeCoordinator() -> Coordiantor {
Coordiantor(self)
}
func updateUIView(_ uiView: ARView, context: Context) {
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Coordinator
import ARKit
import RealityKit
class Coordiantor: NSObject, ARSessionDelegate, ARCoachingOverlayViewDelegate {
var parent: ARViewContainer
init(_ parent: ARViewContainer) {
self.parent = parent
}
func addCoaching() {
let coachingOverlay = ARCoachingOverlayView()
coachingOverlay.autoresizingMask = [.flexibleWidth, .flexibleHeight]
coachingOverlay.goal = .geoTracking
coachingOverlay.session = parent.arView.session
coachingOverlay.delegate = self
parent.arView.addSubview(coachingOverlay)
}
public func coachingOverlayViewDidRequestSessionReset(_ coachingOverlayView: ARCoachingOverlayView) {
let config = ARGeoTrackingConfiguration()
parent.arView.session.run(config, options: [.resetTracking, .removeExistingAnchors])
}
func session(_ session: ARSession, cameraDidChangeTrackingState camera: ARCamera) {
parent.viewModel.cameraTrackingStatus = camera.trackingState.description
}
func session(_ session: ARSession, didChange geoTrackingStatus: ARGeoTrackingStatus) {
switch geoTrackingStatus.state {
case .notAvailable:
parent.viewModel.geoTrackingStatus = "Not Available"
case .initializing:
switch geoTrackingStatus.stateReason {
case .none:
parent.viewModel.geoTrackingStatus = "No issue reported"
case .notAvailableAtLocation:
parent.viewModel.geoTrackingStatus = "Geotracking not available at this location"
case .needLocationPermissions:
parent.viewModel.geoTrackingStatus = "Geotracking requires location permission"
case .worldTrackingUnstable:
parent.viewModel.geoTrackingStatus = "World tracking is not stable"
case .waitingForLocation:
parent.viewModel.geoTrackingStatus = "ARKit waiting for location"
case .waitingForAvailabilityCheck:
parent.viewModel.geoTrackingStatus = "ARKit waiting for availablity check"
case .geoDataNotLoaded:
parent.viewModel.geoTrackingStatus = "Geo data not loaded, please check network connection"
case .devicePointedTooLow:
parent.viewModel.geoTrackingStatus = "Camera pointed too low"
case .visualLocalizationFailed:
parent.viewModel.geoTrackingStatus = "Visual localization failed"
@unknown default:
break
}
case .localizing:
switch geoTrackingStatus.stateReason {
case .none:
parent.viewModel.geoTrackingStatus = "No issue reported"
case .notAvailableAtLocation:
parent.viewModel.geoTrackingStatus = "Geotracking not available at this location"
case .needLocationPermissions:
parent.viewModel.geoTrackingStatus = "Geotracking requires location permission"
case .worldTrackingUnstable:
parent.viewModel.geoTrackingStatus = "World tracking is not stable"
case .waitingForLocation:
parent.viewModel.geoTrackingStatus = "ARKit waiting for location"
case .waitingForAvailabilityCheck:
parent.viewModel.geoTrackingStatus = "ARKit waiting for availablity check"
case .geoDataNotLoaded:
parent.viewModel.geoTrackingStatus = "Geo data not loaded, please check network connection"
case .devicePointedTooLow:
parent.viewModel.geoTrackingStatus = "Camera pointed too low"
case .visualLocalizationFailed:
parent.viewModel.geoTrackingStatus = "Visual localization failed"
@unknown default:
break
}
case .localized:
switch geoTrackingStatus.accuracy {
case .undetermined:
parent.viewModel.accuracy = "Undetermined"
case .low:
parent.viewModel.accuracy = "Low"
case .medium:
parent.viewModel.accuracy = "Medium"
case .high:
parent.viewModel.accuracy = "High"
@unknown default:
break
}
@unknown default:
break
}
}
}
extension ARCamera.TrackingState: CustomStringConvertible {
public var description: String {
switch self {
case .notAvailable:
return "Not Available"
case .limited(.initializing):
return "Limited-Initializing"
case .limited(.excessiveMotion):
return "Limited-Excessive motion"
case .limited(.insufficientFeatures):
return "Limited-Insufficient image input"
case .limited(.relocalizing):
return "Relocalizing"
case .normal:
return "Normal"
case .limited:
return "Unspecified Reason"
}
}
}
Upvotes: 0
Views: 206
Reputation: 11
I think you forgot to assign parent.arView.session.delegate = self
in your coordinator so the following function is never called
func session(_ session: ARSession, didChange geoTrackingStatus: ARGeoTrackingStatus) {
}
Upvotes: 1