1

I'm using iPhone ARToolkit and I'm wondering how it works.

I want to know how with a destination location, a user location and a compass, this toolkit can know it user is looking to that destination.

How can I know the maths behind this calculations?

VansFannel
  • 45,055
  • 107
  • 359
  • 626

2 Answers2

7

The maths that AR ToolKit uses is basic trigonometry. It doesn't use the technique that Thomas describes which I think would be a better approach (apart from step 5. See below)

Overview of the steps involved.

The iPhone's GPS supplies the device's location and you already have the coordinates of the location you want to look at.

First it calculates the difference between the latitude and the longitude values of the two points. These two difference measurements mean you can construct a right-angled triangle and calculate what angle from your current position another given position is. This is the relevant code:

- (float)angleFromCoordinate:(CLLocationCoordinate2D)first toCoordinate:(CLLocationCoordinate2D)second {
    float longitudinalDifference = second.longitude - first.longitude;
    float latitudinalDifference = second.latitude - first.latitude;
    float possibleAzimuth = (M_PI * .5f) - atan(latitudinalDifference / longitudinalDifference);
    if (longitudinalDifference > 0) return possibleAzimuth;
    else if (longitudinalDifference < 0) return possibleAzimuth + M_PI;
    else if (latitudinalDifference < 0) return M_PI;

    return 0.0f;
}

At this point you can then read the compass value from the phone and determine what specific compass angle(azimuth) your device is pointing at. The reading from the compass will be the angle directly in the center of the camera's view. The AR ToolKit then calculates the full range of angle's currently displayed on screen as the iPhone's field of view is known.

In particular it does this by calculating what the angle of the leftmost part of the view is showing:

double leftAzimuth = centerAzimuth - VIEWPORT_WIDTH_RADIANS / 2.0;

if (leftAzimuth < 0.0) {
    leftAzimuth = 2 * M_PI + leftAzimuth;
}

And then calculates the right most:

double rightAzimuth = centerAzimuth + VIEWPORT_WIDTH_RADIANS / 2.0;

if (rightAzimuth > 2 * M_PI) {
    rightAzimuth = rightAzimuth - 2 * M_PI;
}

We now have:

  1. The angle relative to our current position of something we want to display
  2. A range of angles which are currently visible on the screen

This is enough to plot a marker on the screen in the correct position (kind of...see problems section below)

It also does similar calculations related to the devices inclination so if you look at the sky you hopefully won't see a city marker up there and if you point it at your feet you should in theory see cities on the opposite side of the planet. There are problems with these calculation in this toolkit however.

The problems...

Device orientation is not perfect

The value I've just explained the calculation of assumes you're holding the device in an exact position relative to the earth. i.e. perfectly landscape or portrait. Your user probably won't always be doing that. If you tilt the device slightly your horizon line will no longer be horizontal on screen.

The earth is actually 3D!

The earth is 3-dimensional. Few of the calculations in the toolkit account for that. The calculations it performs are only really accurate when you're pointing the device towards the horizon.

For example if you try to plot a point on the opposite side of the globe (directly under your feet) this toolkit behaves very strangely. The approach used to calculate the azimuth range on screen is only valid when looking at the horizon. If you point your camera at the floor you can actually see every single compass point. The toolkit however, thinks you're still only looking at compass reading ± (width of view / 2). If you rotate on the spot you'll see your marker move to edge of the screen, disappear and then reappear on the other side. What you would expect to see is the marker stay on screen as you rotate.

The solution

I've recently implemented an app with AR which I initially hoped AR Toolkit would do the heavy lifting for me. I came across the problems just described which aren't acceptable for my app so had to roll my own.

Thomas' approach is a good method up to point 5 which as I explained above only works when pointing towards the horizon. If you need to plot anything outside of that it breaks down. In my case I have to plot objects that are overhead so it's completely unsuitable.

I addressed this by using OpenGL ES to plot my markers where they actually are in 3D space and move the OpenGL viewport around according to readings from the gyroscope while continuously re-calibrating against the compass. The 3D engine handles all the hard work of determining what's on screen.

Hope that's enough to get you started. I wish I could provide more detail than that but short of posting a lot of hacky code I can't. This approach however did address both problems described above. I hope to open source that part of my code at some point but it's very rough and coupled to my problem domain at the moment.

Community
  • 1
  • 1
Dolbz
  • 2,078
  • 1
  • 16
  • 25
  • This is a very complete answer. Thank you. – VansFannel Oct 11 '11 at 17:53
  • I'm using AR Toolkit, but I'm not sure if it is working well or I have a problem with my iPhone. When I try to locate a point, I see its label on its right. It never points to that location. Do you have the same problem? – VansFannel Oct 11 '11 at 17:55
  • Are you having the same problems than I with iPhone AR Toolkit? Thanks. – VansFannel Oct 20 '11 at 07:09
  • I can't remember details of the problems I had when I tried. I gave up on it quite quickly. The codebase was out of date. I remember having to make changes just to get it to run but can't remember specific issues now. Sorry. – Dolbz Oct 21 '11 at 12:34
  • Hi! I've found this tutorial http://www.invasivecode.com/blog/archives/1435, but there it doesn't calculates beta like you here. Which is the right version or are both the same? – VansFannel Nov 14 '11 at 12:41
  • By the way, why do you multiplay atan by (M_PI *.5f) in float `possibleAzimuth = (M_PI * .5f) - atan(latitudinalDifference / longitudinalDifference);`? – VansFannel Nov 14 '11 at 12:43
  • That tutorial is interesting but make note of this sentence 'Now, since usually the distance between the POI and you is **much smaller** than the distance between the North Pole and you and the POI and you, you can assume that the two lines connecting the North Pole with the POI and the North Pole and you are parallel.' The 'much smaller' I've emphasised is key. It's fine to use these 2D simplified calculations if this is the case. In my case it wasn't which is why AR Toolkit wasn't a good fit for me. The AR Toolkit demo uses global cities which aren't close by so aren't suited to this either. – Dolbz Nov 14 '11 at 14:42
  • This simplified calculations doesn't work. I've asked another question, because I'm lost. http://stackoverflow.com/questions/8123049/calculate-bearing-between-two-locations-lat-long – VansFannel Nov 14 '11 at 14:49
  • As for the calculation question... the `(M_PI * .5f) - atan(etc)` code is subtracting the atan result from 90 degrees (Pi/2 radians = 90 degrees). In relation to the tutorial you linked, instead of calculating atan(a, b) the calculation performed in this code is atan(b, a) and atan(a, b) = 90deg - atan(b, a). I didn't write this code so don't know why the author didn't just use atan(a, b) but it ends up at the same result. – Dolbz Nov 14 '11 at 15:05
  • @Dolbz I know this is an old thread but do you have a tutorial/explanation of how you achieved this in OpenGLES to plot your markers and move the viewport around? Thanks! – rkh Nov 12 '13 at 03:01
  • @rkh No I don't at the moment. I probably should do something though. Thanks for the reminder... I'll try and get onto it. – Dolbz Nov 15 '13 at 11:58
  • @Dolbz thanks for your response, I'd greatly appreciate it if you can post an explanation of how you achieved this. – rkh Nov 15 '13 at 13:13
  • @Dolbz have you made any tutorial with OpenGLES here?? – Shivam Mishra Jul 25 '14 at 04:36
  • No :( I'm sorry to admit I haven't – Dolbz Nov 14 '14 at 13:37
  • Excellent answer! I Is it possible to do the reverse? i drag an image or marker in the AR view to a different position. Now is it possible to fetch the lat long of the marker? If it is possible (or impossible) can you please explain it how(or why) ? – rootcoder Jan 27 '17 at 12:00
3
  • that is all information needed. with iphone-location and destination-location you can calculate the destination-angle (with respect to true north).
  • The only missing thing is to know where the iPhone is currently looking at which is returned by the compass (magnetic north + current location -> true north).

edit: Calculations: (this is just an idea: there may exist a better solution without a lot coordinate-transformations)

  1. convert current and destination location to ecef-coordinates
  2. transform destination ecef coordinate to enu (east, north, up) local coordinate system with current location as reference location. You can also use this.
  3. ignore the height-value and use the enu-coordinate to get the direction: atan2(deast, dnorth)
  4. The compass returns already the angle the iPhone is looking at
  5. display the destination on the screen if
    dest_angle - 10° <= compass_angle <= dest_angle + 10°
    with respect to the cyclic-angle-space. The constant of 10° is just a guessed value. You should either try some values to find out a useful one or you have to analyse some properties of the iPhone-camera.

The coordinate-transformation-equations become much simpler if you assume that the earth is a sphere and not an ellipsoid. Most links if have postet are assuming an wgs-84 ellipsoid becasue gps also does afaik).

thomas
  • 5,637
  • 2
  • 24
  • 35
  • Thanks. But I want to know all the calculations made by ToolKit. I'm not asking if it works, I want to know how it could calculate if a location is visible or not. – VansFannel Oct 06 '11 at 12:20
  • Thanks for your answer. It's very helpful. If I want to learn more about this, how can I find more information about it? I don't know how I can call it: geolocation, geo location calculations... I don't know if I've explained well. – VansFannel Oct 07 '11 at 11:51
  • just follow the references included in the wikipedia-links I've posted. Or visit the category-page of wiki: http://en.wikipedia.org/wiki/Category:Geodesy or just search for research-papers / articles about navigation (especially aircraft-navigation is pretty good) – thomas Oct 07 '11 at 12:57
  • Thanks again. My problem is that I don't know how to called, but now i know. – VansFannel Oct 07 '11 at 13:48