Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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, so someone else with their camera view can come by and see it on the augmented reality camera view. For this I know I need to calculate some sort of distance factor along with azimuth and elevation.

So, I have already figured out how to send the object's graphics up to a server and retrieve it back, but how can I place it back on its original position, relative to Earth. I know I need to calculate its:

  • Altitude
  • Coordinates
  • Azimuth
  • Elevation
  • Distance

But how would I calculate these and account for them/piece them together. I hope you understand what I mean.

To refine your understanding let me give you a short demo of the app:

A man is in his house, he decides to place an image of a painting on one of his walls. He opens up the app which defaults to the augmented reality screen, he presses the plus button and adds an image from his photo library. Behind the scenes, it saves the location and positional data up to a server, someone with the app and its augmented reality screen comes by, it goes up to the server and finds images saved nearby, it then downloads the image and places it up on the wall so the other man can see it with his phone when he moves it by.

What approach should I take to achieve this? Any outline, links, resources, tutorials, thoughts, experience etc. Thanks! This was a generally hard question to write down, I hope you can understand. If not please tell me and I will reword.

Rohan

like image 731
MCKapur Avatar asked Dec 28 '12 14:12

MCKapur


2 Answers

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

like image 177
Ricardo RendonCepeda Avatar answered Oct 20 '22 00:10

Ricardo RendonCepeda


Swift 3

Gyroscope code update:

import CoreMotion
...
        motionManager.deviceMotionUpdateInterval = 0.1
        motionManager.startDeviceMotionUpdates(to: OperationQueue.current!) { deviceManager, error in
            guard let dm = deviceManager else { return }
            let roll = dm.attitude.roll
            let pitch = dm.attitude.pitch
            let yaw = dm.attitude.yaw

            print("r: \(roll), p: \(pitch), y: \(yaw)")
        }
like image 20
Sébastien REMY Avatar answered Oct 19 '22 23:10

Sébastien REMY