Tag Archives: apple

Building augmented reality layars

Layar is a free augmented reality (AR) app for iPhone and Android. Unlike other apps which fulfil a specific AR need (from finding bars near you selling Stella, to shooting your friends with lasers) Layar opens things up to let developers build their own AR views and run them in the Layar AR “browser”. It looks like the image below, which shows a wikipedia layer.

AR Browser

And yes, “browser” is kind of an apt description, because when you build a Layar layer (someone should really think of better terminology than this!) what you’re really doing is providing a webservice which gets displayed in a particular way.

Building a simple layer is actually pretty easy if you have some web development knowledge, such as PHP and MySQL. In fact, if you’re ever built a simple webservice before then all you need to build a simple layer is which parameters need to be passed in, and what the output should look like. The Layar people have provided a tutorial to help you if web development isn’t your main thing, and there’s some sample code there too. I found their wiki and tutorials useful for getting started, but in my opinion their PHP code samples are a little hacky.

Developer site

So, first you need to register as a developer. This takes just a minute. Once done, you need to start building your layer definition. This sets things like the URL of your webservice, and the name of the layer. You can also use the developer area to test your layers before submitting them for publication. Again, documentation is provided. But I found it all pretty straightforward and easy to work out anyway (they could do with some better web designers though!)

Webservice

Now the key part which makes the whole thing tick. The webservice. This can be hosted on your own site, although 3rd party sites exist, such as hoppala.eu, which in effect provide the webservice hosting for you. To be honest the hoppala service seemed great at first sight – you give it the url of a google map and it does the rest – but after various unsuccessful attempts at sending them my google map url, I gave up. Your webservice needs to provide a few key pieces of data about your layer. Basically the geo-coordinates of each point-of-interest in your layer, and a title and description for each.

Google Map

Getting geo-coordinates might sound scary, but if you’ve ever made a google map, you’ll have those to hand. If you haven’t made a google map, then it really is just an easy drag and drop exercise. There’s a little RSS button at the top right of your map where you can get the url of the RSS feed of your map. This contains all the coordinates, as well as the titles and descriptions you’ll have given when you were building up your map.

It would be cool if the Layar people would accept these RSS feeds. That way you’d not have to do anything else. To me this is the biggest oversight of the whole system. The google RSS really does contain everything they need, but hey…

OK so you just have to accept that you’re going to have to take that google map RSS feed, and modify it to put it in the format the Layar people need. In effect you’re creating a chained, 2-step, webservice. This is where your PHP and webservice skills come in.

Input data

When the Layar “browser” calls your webservice, it provides three GET parameters. The user’s current longitude, latitude, and the radius the user wants to be bothered with around them. Your webservice code therefore will need to capture these paremeters and use them to generate your output. Once again, it escapes me why Layar sends this data to your webservice, rather than doing the necessary calculations in the app itself. I can only guess it’s to do with performance issues.

SimpleXML

What I did was use PHP’s built in SimpleXML features to pull the google map RSS feed apart, and take out the longitude, latitude, title, and description data out.

Doing this is pretty easy. You call something like this:

$xml = simplexml_load_file('http://maps.google.co.uk/maps/ms?.......');

and go through each point-of-interest with a loop like this:

foreach ($xml->channel->item as $entry) {....

Scary maths bit

Remember those 3 input parameters? Longitude, latitude, and radius. The reason they’re passed to your webservice is that Layar needs to tell your webservice not to bother sending irrelevant results back to them. Suppose the user only wants results in a 1km radius. Layar doesn’t want a mass of data covering most of England. It’d just be too slow.

Soooooo…. you’re going to have to do some scary maths to calculate distance from a point. All that nasty trigonometry stuff you did at school.

Don’t panic! The Layar people provide you with the formula. In case you can’t find it, here it is:

$distance = (((acos(sin(($value['lat'] * pi() / 180)) * sin(($lat * pi() / 180))+cos(($value['lat'] * pi() / 180)) * cos(($lat * pi() / 180)) * cos(($value['lon']  - $lon) * pi() / 180))) * 180 / pi()) * 60 * 1.1515 * 1.609344 * 1000);

where $value['lat'] and $value['lon'] are the user’s coordinates, and $lat and $lon are the coordinates of the point-of-interest.

You just need to compare this $distance value with the user’s radius GET parameter sent by Layar.

JSON output

Your final output, then, is nearly ready. Build a PHP array containing the layer name and a list of the points-of-interest. Each point should have coordinates, a distance from the user, and other data like title, description, image URL, etc. Full details on these can be found in the Layar wiki and tutorials.

The last thing you need to do is make sure your webservice output is in JSON format. In PHP this is too easy: just call json_encode() with your array as the parameter.

Test and publish

Once your webservice is up and running, go and test it from the Layar developer area. I haven’t as yet published a layer, but it seems to involve a fairly straightforward submission process.

One cool (although thinking about it pretty essential) feature is that you can test your layer in the Layar app itself. Once you have a developer account you get an extra “test” tab in the app. This lists all your own layers, each of which will function exactly as though it’s been published.

Summary

The Layar augmented reality app is a really nice idea, and one which allows developers to build their own layers relatively easily. You do, however, have to be a developer with some knowledge of webservices and familiarity with APIs. It’s just a shame the Layar people didn’t think to allow very small-scale layers pulled directly from, say, Google Map RSS feeds. The only reason I think they’ve not done this is for performance reasons. But if all you want to do is build a layer with a couple of dozen points of interest in a limited area, the whole radius/distance calculation thing seems a waste of effort on the developer’s part.

On the plus side, once you’ve developed one simple layer it’s incredibly easy to modify your code to build other layers. In fact, all you really need do is pass in a different Google Maps RSS URL.

Another plus, of course, is that Layar removes the need for developers to get involved in actually building their own iPhone augmented reality apps. A far scarier prospect than that distance calculation.

iPhone dev image processing quirks

I had a lot of problems getting image processing to work properly on the iPhone. This isn’t so much because the image processing I was doing was very tricky; it was more because of some apparent quirks in how the iPhone works its image orientation.

Basically it seems that if you take a photo in portrait ie ‘up’ the iPhone thinks you’ve taken the photo in landscape ie ‘right’. Weird. But that’s how it seems to work.

In fact, no matter which way round you hold your iPhone, it always thinks the photo was taken 90 degrees clockwise from what it actually was.

In my app, I’m taking the raw image as a UIImage and converting it to a CGImage to do various things at the pixel level, and converting it back to a UIImage. As part of this I’m now therefore having to rotate the CGImage round, using code like this:

// iphone held up
if (uiimage.imageOrientation == UIImageOrientationRight) {
context1=CGBitmapContextCreate(m_imageData, m_width, m_height, 8, m_width*sizeof(uint32_t), colorSpace1, kCGBitmapByteOrder32Little|kCGImageAlphaNoneSkipLast);
CGContextSetInterpolationQuality(context1, kCGInterpolationHigh);
CGContextSetShouldAntialias(context1, YES);
CGContextTranslateCTM(context1, m_width/2, m_height/2);
CGContextRotateCTM(context1, -M_PI_2);
CGContextTranslateCTM(context1, -m_height/2, -m_width/2);
CGContextDrawImage(context1, CGRectMake(0, 0, m_height, m_width), [uiimage CGImage]);
}

This first detects which way round the iPhone thinks the photo is so we can do the right kind of rotation. It then uses CGContextTranslateCTM and CGContextRotateCTM to rotate and shift the image around in the image context space, before drawing the image into that space. Note that CGContextTranslateCTM is needed because CGContextRotateCTM rotates an image about its top left corner, not its centre. We therefore need to shift the image around if we’re ever going to see it.

The even weirder thing is that all this image rotation is unnecessary if you allow users to crop the image just after they’ve taken a photo, using the iPhone’s image picker. Obviously Apple built this kind of functionality into the image picker. The only problem with that route (which I used in my earlier Phlomo app) is that you end up with a rather small, poor quality image, and an extra unnecessary user step.

Phlomo

ok so I’ve renamed Flomo to Phlomo (there’s a toy company in the states called Flomo) and I’ve submitted the app to Apple. Fingers crossed. The whole testing and submission procedure was a bit of a pain. But now I’ve done it, it doesn’t seem too bad.

I can’t think why the app might not be accepted, although Apple are notorious for accepting the most incredible dross and rejecting perfectly good apps on minor technicalities (such as incorrect age ratings based on their bizarre criteria).

I’ve also set up Phlomo.com.

Oh and I’ve tried out this new theme, which I think is somewhat better than the last.

Beginning iPhone Development: Exploring the iPhone SDK

iPhone development isn’t really all that much fun, but the end results can be very cool. Dave Mark and Jeff LaMarche have written a really nice introduction which makes the whole process seem just about manageable. Almost cool and quirky even.

Importantly, it successfully captures the key to the iPhone’s success as a development platform: anyone with sufficient determination (yes, you!) can get through the unnecessary and bizarre horrors of Objective-C and the iPhone SDK, and can produce something that people might pay some money for. It’s something you can almost impress people with at parties. Almost.

Of course the book has an online forum and downloadable source code – de rigeur for coding books these days, but good to see nonetheless. In summary, if you want to try your hand at some simple iPhone apps, you really will need this book.