未经许可将SCNNode旋转到北方以进行位置跟踪

时间:2019-04-26 17:04:13

标签: ios augmented-reality arkit compass-geolocation

我们想旋转makeWindowControllers()以使其与北向匹配。

Arkit允许将其z轴与北方对齐,但这需要用户许可才能进行位置跟踪,我们也不想提出这个要求。 参见gravityandheading

因此,我们试图使用CMDeviceMotion的磁场属性。但是我们不知道该怎么做。 可能有一些矩阵计算,但是我们暂时不掌握它们。 参见magneticfield

任何帮助将不胜感激!谢谢!

1 个答案:

答案 0 :(得分:0)

  

未经用户许可,您不能使用位置跟踪。

以下是有关如何为 AR应用非AR应用正确设置的一些提示:

iOS 11或更高版本中,您需要执行以下操作才能使位置正常工作:

  • 在您的info.plist中添加密钥,并向位置管理器请求授权以要求其启动。 info.plist中有两个Property List Keys用于位置授权。 这两个键中的一个或两个都是必需的。在非AR应用程序中,如果没有按键,则可以调用 startUpdatingLocation 方法,但位置管理器实际上不会启动。它也不会向代理发送失败消息(因为它从未启动,所以不会失败)。 如果您添加一个或两个密钥但忘记显式请求授权,也会失败
  

Property List Keys文件中使用这两个info.plist。自iOS 11发行以来就使用了它们

<key>NSLocationWhenInUseUsageDescription</key>
  <string>App needs an access to your location (in foreground)</string>

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
  <string>App needs an access to your location (in background)</string>
  

这两个Property List Keys早于不推荐使用请勿使用这些键):

    <key>NSLocationUsageDescription</key>
      <string>App needs an access to your location (in background)</string>

    <key>NSLocationAlwaysUsageDescription</key>
      <true/>

您的 AR应用程序代码如下所示:

let configuration = ARWorldTrackingConfiguration()

func session(_ session: ARSession, didFailWithError error: Error) {

    switch error.code {
    case 101:
        configuration.worldAlignment = .gravity
        restartSession()
    default:
        configuration.worldAlignment = .gravityAndHeading
        restartSession()
    }
}   
func restartSession() {    
    self.sceneView.session.pause()
    self.sceneView.session.run(configuration, options: [.resetTracking, 
                                                        .removeExistingAnchors])
}

对于非AR应用程序,请使用以下两种实例方法:requestAlwaysAuthorization()(请求在应用程序运行时使用位置服务的权限)和requestWhenInUseAuthorization()(请求在应用程序处于运行状态时使用位置服务的权限)前景)。

您的用于非AR应用程序的代码应如下所示:

import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

    var locationManager = CLLocationManager()

    func updateMyLocation() {

        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers

        if locationManager.respondsToSelector(#selector(CLLocationManager.requestWhenInUseAuthorization)) {
            locationManager.requestWhenInUseAuthorization()
        } else {
            locationManager.startUpdatingLocation()
        }
    }
}

此外,您可以请求Always Authorization

let locationManager = CLLocationManager()   

func enableLocationServices() {

    locationManager.delegate = self

    switch CLLocationManager.authorizationStatus() {

        case .notDetermined:
            // Request when-in-use authorization initially
            locationManager.requestWhenInUseAuthorization()
            break

        case .restricted, .denied:
            // Disable location features
            disableMyLocationBasedFeatures()
            break

        case .authorizedWhenInUse:
            // Enable basic location features
            enableMyWhenInUseFeatures()
            break

        case .authorizedAlways:
            // Enable any of your app's location features
            enableMyAlwaysFeatures()
            break
    }      
}

希望这会有所帮助。