iOS - Calculating distance, azimuth, elevation and relative position (Augmented Reality)

后端 未结 2 843
醉梦人生
醉梦人生 2020-12-12 18:03

I am starting to build an augmented reality app where you can place an image on the screen on your augmented reality camera view and it stays in that position on the Earth,

2条回答
  •  囚心锁ツ
    2020-12-12 18:04

    I'm working on two AR iOS apps which do the following: convert azimuth (compass, horizontal angle) and elevation (gyroscope, vertical angle) to a position in 3D space (e.g. spherical to cartesian).

    The frameworks you need are:

    • CoreLocation
    • CoreMotion

    Getting the geolocation (coordinates) is pretty straightforward for latitude, longitude, and altitude. You can easily find this information in several online sources, but this is the main call you need from the CLLocationManagerDelegate after you call startUpdatingLocation:

    - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
    {
        latitude = (float) manager.location.coordinate.latitude;
        longitude = (float) manager.location.coordinate.longitude;
        altitude = (float) manager.location.altitude;
    }
    

    Getting the azimuth angle is also pretty straightforward, using the same delegate as the location after calling startUpdatingHeading:

    - (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
    {
        azimuth  = (float) manager.heading.magneticHeading;
    }
    

    Elevation is extracted from the gyroscope, which doesn't have a delegate but is also easy to set up. The call looks something like this (note: this works for my app running in landscape mode, check yours):

    elevation = fabsf(self.motionManager.deviceMotion.attitude.roll);
    

    Finally, you can convert your orientation coordinates into a 3D point like so:

    - (GLKVector3)sphericalToCartesian:(float)radius azimuth:(float)theta elevation:(float)phi
    {
        // Convert Coordinates: Spherical to Cartesian
        // Spherical: Radial Distance (r), Azimuth (θ), Elevation (φ)
        // Cartesian: x, y, z
    
        float x = radius * sinf(phi) * sinf(theta);
        float y = radius * cosf(phi);
        float z = radius * sinf(phi) * cosf(theta);
        return GLKVector3Make(x, y, z);
    }
    

    For this last part be very wary of angle and axis naming conventions as they vary wildly from source to source. In my system, θ is the angle on the horizontal plane, φ is the angle on the vertical plane, x is left-right, y is down-up, and z is back-front.

    As for distance, I'm not sure you really need to use it but if you do then just substitute it for "radius".

    Hope that helps

提交回复
热议问题