Augmented Reality – Create your own Layar Layer!

Want to create a Layar layer with a PHP backend?

So you have seen the cool augmented reality applications for iPhone and Andriod! Now you want to make use of this technology in your project. With the Layar application you are not far from that goal.
The Layar API is pretty straight forward but this post might get you up to speed even faster.
The backend we are going to build is based on MySQL and on PHP ver. 5.2. If you don’t have 5.2 you can build the JSON manually.

Layar API

I’ll assume that you have read the instructions at http://dev.layar.com/publishing/ and received your developer account.
At the developer site login and add a new layer. The “POI URL” should point to the PHP file below in this post. Fill in as much information you can and save the layer.
Example: http://your_site.net/my_layer.php

The database

You could store your locations in a XML file or in whatever you like. But the good thing about SQL is that you can query for a radius. This means that you let the query do the actual calculation on which position to send back to the Layar API. So this is where the backend magic actually happens.

1. Create the database

create table layar(id INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(id), title VARCHAR(30), lat FLOAT(10,6), lng FLOAT(10,6));

2. Add some destinations

insert into layar (id, title, lat, lng) values ('','Location 1', '55.375153', '13.157624');
insert into layar (id, title, lat, lng) values ('','Location 2', '55.374065', '13.158255');
insert into layar (id, title, lat, lng) values ('','Location 3', '55.374943', '13.160877');

All these positions are within a small city in southern Sweden called Trelleborg (Google maps link). So when you do your layer API testing you need to drag the API person to Trelleborg.

The code

The file you are about to create should be on the server and with the name you stated in “POI URL” during the Layar layer setup.

3. Now some PHP

<?php
header('Content-type: application/json');

// Please change these settings!
$config[“server_ip”] = “your_server_ip”;
$config[“db_user”] = “your_db_user”;
$config[“db_password”] = “your_super_password”;
$config[“db_sid”] = “your_database_name”;
$config[“layer_name”] = “your_layer_name”; // You get/set this when you setup your layer.

// Get parameters from the Layar API.
// Please look at the API documentation for full information on these parameters.
$center_lat = $_GET[“lat”];
$center_lng = $_GET[“lon”];
$radius = ($_GET[“radius”]/1000); // From KM down to meters as this is what we use for our SQL call.
$timestamp = $_GET[“timestamp”];
$developerId = $_GET[“developerId”];
$developerHash = $_GET[“developerHash”];

// Opens a connection to a mySQL server
$connection=mysql_connect ($config[“server_ip”], $config[“db_user”], $config[“db_password”]);

// Set the active mySQL database
$db_selected = mysql_select_db($config[“db_sid”], $connection);

// Search the rows in the markers table
// 6357 km at the pole
// 6371 – default
// 6378 KM at the equator

$query = “SELECT id, title, lat, lng, (6378*acos(cos(radians(‘” . mysql_real_escape_string($center_lat) . “‘))*cos(radians(lat))*cos(radians(lng)-radians(‘” . mysql_real_escape_string($center_lng) . “‘))+sin(radians(‘” . mysql_real_escape_string($center_lat) . “‘))*sin(radians(lat)))) AS distance FROM layar WHERE id HAVING distance<‘” . mysql_real_escape_string($radius) . “‘ LIMIT 0, 10”;
$result = mysql_query($query);
$num_rows = mysql_num_rows($result);

// If we don’t get any hits lets send back error/nothing.
if (!$result or $num_rows==0)
{
$arr = array(“hotspots”=> “”, “layer”=>$config[“layer_name”], “errorString”=>”Sorry, no destinations close to you right now!”, “morePages”=>false, “errorCode”=>21, “nextPageKey”=>null);
echo json_encode($arr);
exit; // Exit as we don’t want to run code below this if error/nothing.
}

// Lets start building valid return.
$returnJSONArray = array(“layer”=>$config[“layer_name”], “errorString”=>”ok”, “morePages”=>false, “errorCode”=>0, “nextPageKey”=>null);

while ($row = @mysql_fetch_assoc($result))
{
$returnJSONArray[“hotspots”][] = array(
“actions” => array(),
“attribution” => “Teknograd AB”,
“distance” => $row[‘distance’]*1000, // km back to meter!
“id” => $row[‘id’],
“imageURL” => null,
“lat” => (int) str_replace(“.”, “”, $row[‘lat’]), // API wants clean INT we store in FLOAT.
“lon” => (int) str_replace(“.”, “”, $row[‘lng’]), // API wants clean INT we store in FLOAT.
“line2” => null,
“line3” => null,
“line4” => null,
“title” => $row[‘title’],
“type” => 0);
}
echo json_encode($returnJSONArray);
?>

Lets sum up

We are done. This is really all you need to get the backend to work.

4. Whats next?

Make sure the PHP code is correct before starting to do test calls through the API test (which is a great tool). Don’t forget to move the API test person to Trelleborg, Sweden.

Any thoughts or ideas in conenction with this please let me know!

What are we using Layar for?

We are using Layar for our open communication platform WAYD. We let users store locations through our free iPhone application WAYD (download from iTunes Store). When a location is stored everybody else can see the photo through Layar. This enables people to experince the same thing as previous people and see what they wrote at that location.

Reblog this post [with Zemanta]

62 Replies to “Augmented Reality – Create your own Layar Layer!”

  1. Hey,
    Good post! Thanks for sharing this code with us. Just a couple of comments that might help some users of this:
    – $radius = ($_GET[“radius”]/1000); // The comment should be: from meters down to km as the database query uses km
    – “lat” => (int) str_replace(“.”, “”, $row[‘lat’]), // This works only because you specifically store the floats as FLOAT(10,6) with 6 decimals in the database. If you use an existing database where the lat/lon are saved differently, make sure you first convert to a float with 6 decimals before the str_replace. Or multiply the float by 10^6 and then convert to int.

  2. Very nice post, by the way, something I’ve experienced in some of our applications is that 6 decimals is not accurate enough in some cases. The Google documentation states that you have to set your lat and lon field to FLOAT(10,6) but when you geolocate the result will return op to 7 decimals. So you lose accuracy when saving to a database.

    So if you want to place your markers extra accurate on the map you should make sure you save up to 7 decimals instead of 6.

    Gr,
    Jasper

  3. thats goods posting, i have try it, but i have one problem, how i add the action like mailto,tel,sms,url on the code, maybe you can help me, thanks

    yunus

    1. Hi Yunus,

      Thanks for your feedback.
      To add actions change the “action” array in the code above as follows:

      —————————
      “actions” => array(array(“uri”=>”tel:”.$row[‘telno’], “label”=>”Call POI”)),
      —————————

      The actions supported can be found on Layars homepage ( http://L2W.no/f297 ).

    2. Hi fdqps,

      I was wondering how the code is if you want to make 2 actions, for example tel. and open website. Can “uri” be used 2 times in the same array?

    3. Hi Edwin,

      Yes, you can.
      Example:
      “actions” => array(array(“uri”=>”http://wayd.no/”.$row[‘id’], “label”=>”Web”)),

      See documentation on the different “actions” you can call.

      Hope this helps.

    4. Hey fdqps,

      Thnx for the fast reply.

      I am new to this, how do I place two actions, “link to website” and “Call me” for one POI.

      Do I make

      1. Two arrays?
      “actions” => array(array(“uri”=>”http://wayd.no/”.$row[‘id’], “label”=>”Web”)),
      “actions” => array(array(“uri”=>”Tel:/”.$row[‘telno’], “label”=>”Call”)),

      2. One array
      “actions” => array(array(“uri”=>”Tel:/”.$row[‘telno’], “label”=>”Call”, “uri”=>”http://wayd.no/”.$row[‘id’], “label”=>”Web”)),

      my question is what is the proper way to set up this array so I can make an array with multiple actions.

      Hope it is clear now, thnx in advance.

      Edwin

    5. Hi Edwin,

      One array with two arrays in it ;-).

      “actions” => array(array(“uri”=>”tel:”.$row[‘telno’], “label”=>”Call”), array(“uri”=>”mailto:fredrik@teknograd.no”, “label”=>”Email”)),

      Hope this helps.
      You will fins which actions you can use at this URL: http://L2W.no/r0sj

  4. hmm.. this very helpful…
    thanks for remind me…

    hmm.. know layar update the structure into v3, thats more feature and more funciton, like 3D AR, i think it will be helpful, if you try to post 3D AR, thanks

    1. Thanks for your comment.

      The v2 Layars, and above code, will work in v3 as well. We will post any “howto” as soon as we have taken a deeper look into v3 news.

  5. Thanks Fredrik for turorial! But I have error below in API test page, Anybody can help? Current PHP version: 5.2.112.0

    Loading layer…

    found layer = zgcityLoading POIs…
    loading POIs for page – null

    zgcity – passed authorization check

    oauth disabled…

    POI fwd url = http://www.janus-network.com/ar/web/test.php?countryCode=NL&lon=13.157624&timestamp=1261134778308&userId=6f85d06929d160a7c8a3cc1ab4b54b87db99f74b&developerId=1241&developerHash=98a7a7a3575894c03e90fc0f4b091e70d863a25b&radius=1500&lat=55.375153&layerName=zgcity&phoneId=6f85d06929d160a7c8a3cc1ab4b54b87db99f74b&accuracy=100

    Response received from provider, validating…

    error validating provider response – Traceback (most recent call last): File “/base/data/home/apps/layarservice/live303.338444705044286435/webapi20/apitesthandler.py”, line 167, in validate_response pois = json.loads(provider_response) File “/base/python_lib/versions/third_party/django-0.96/django/utils/simplejson/__init__.py”, line 232, in loads return cls(encoding=encoding, **kw).decode(s) File “/base/python_lib/versions/third_party/django-0.96/django/utils/simplejson/decoder.py”, line 251, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File “/base/python_lib/versions/third_party/django-0.96/django/utils/simplejson/decoder.py”, line 270, in raw_decode raise ValueError(“No JSON object could be decoded”) ValueError: No JSON object could be decoded

    JSON parse error( most likely)!, validate your response at http://www.jsonlint.com/

    Error validating response…

    Error:Layer not available

    1. Hi Kruno: exact same error info here, could you pls post what is wrong and how you fix it?

    2. The comment from Timo Elliot fixed it 🙂

      I did notice another error though: When you are out of range the error function doesnt work.

      You should replace this:

      if (!$result or $num_rows==0)
      {
      $arr = array(“hotspots”=> “”, “layer”=>$config[“layer_name”], “errorString”=>”Sorry, no destinations close to you right now!”, “morePages”=>false, “errorCode”=>21, “nextPageKey”=>null);
      echo json_encode($arr);
      exit; // Exit as we don’t want to run code below this if error/nothing.
      }

      with this:

      if (!$result or $num_rows==0)
      {
      $arr = array(“hotspots”=>$config[“”], “layer”=>$config[“layer_name”], “errorString”=>”Sorry, no destinations close to you right now!”, “morePages”=>false, “errorCode”=>21, “nextPageKey”=>null);
      echo json_encode($arr);
      exit; // Exit as we don’t want to run code below this if error/nothing.
      }

  6. MANY thanks, great code to get me started. Just an fyi for folks — remember to convert ALL the fancy double AND single quotes to simple double and single quotes for this code to work. 🙂

  7. I’m having the following error –

    Loading layer…

    found layer = eishitalayer1Loading POIs…
    loading POIs for page – null

    eishitalayer1 – passed authorization check

    oauth disabled…

    POI fwd url = http://192.168.2.4/~Eishita/MyFolder/Test.php?countryCode=NL&lon=4.887339&timestamp=1264741634682&userId=6f85d06929d160a7c8a3cc1ab4b54b87db99f74b&developerId=2076&developerHash=971d669bbded81572450446fb7e6ae266d1e1ae3&radius=15000000&lat=52.377544&layerName=eishitalayer1&phoneId=6f85d06929d160a7c8a3cc1ab4b54b87db99f74b&accuracy=100

    Unable to reach POI provider.

    Error:Layer provider not available

    Can anyone help please??

    1. Without looking to much into the code it seems strange that you try to call a local server (192.168.2.4). Your layer must be available over the internet, otherwise Layar.com can’t access your layer.

  8. While testing from the API test page, I’m having the following error in spite of taking the person at Trelleborg, Sweden.

    Can anyone help me please????

    Loading layer…

    found layer = eishitalayer1Loading POIs…
    loading POIs for page – null

    eishitalayer1 – passed authorization check

    oauth disabled…

    POI fwd url = http://128.233.104.84/t1.php?countryCode=NL&lon=13.157624&timestamp=1266090996348&userId=6f85d06929d160a7c8a3cc1ab4b54b87db99f74b&developerId=2076&developerHash=cdcef735554d55486afac95bb5f44e9dff98f4a0&radius=5000000&lat=55.375153&layerName=eishitalayer1&phoneId=6f85d06929d160a7c8a3cc1ab4b54b87db99f74b&accuracy=100

    Response received from provider, validating…

    Response validated, sending it back…

    Error:Sorry, no destinations close to you right now!

    1. I have created the web server using linux Mandriva. Still having this problem … Please help me 🙁

  9. Can anyone suggest me whether is it possible to add object/transform in here for adding 3d object [V3]??

  10. I get the following errors when I try to run the example above. Any idea what I am doing wrong? I changed the single and double quotes already.

    oauth disabled…

    POI fwd url = http://theminutewaltz.com/layer/poi1.php?countryCode=NL&lon=4.887339&timestamp=1267492034603&userId=6f85d06929d160a7c8a3cc1ab4b54b87db99f74b&developerId=1&developerHash=9f4be0118cce75777a0b2400f32d8dff16f24b25&radius=1500&lat=52.377544&layerName=testone&phoneId=6f85d06929d160a7c8a3cc1ab4b54b87db99f74b&accuracy=100

    Response received from provider, validating…

    Value u” for field ‘hotspots’ is not of type ‘array’

    Error validating response…

    Error:Layer not available

    1. Sorry, I dragged the icon to Sweden. My error looks like this now.

      Response received from provider, validating…

      Value {u’distance’: 246.470335396, u’attribution’: u’Teknograd AB’, u’title’: u’Location 3′, u’line3′: None, u’imageURL’: None, u’line4′: None, u’lon’: 13160877, u’line2′: None, u’actions’: [], u’lat’: 55374943, u’type’: 0, u’id’: u’3′} for field ‘hotspots’ is not of type ‘array’

      Error validating response…

      Error:Layer not available

  11. I have the following problem and i can’t figure out what it is can someone help me?

    OUTPUT layar API Test page: (i adjusted the coordinates)

    Edit Delete 1 Location 1 52.047642 4.476317
    Edit Delete 2 Location 2 52.050392 4.476693
    Edit Delete 3 Location 3 52.052444 4.469987

    POI fwd url = http://www.marcelvankleef.nl/layar/layar.php?countryCode=NL&lon=4.4757270813&timestamp=1267701663982&userId=6f85d06929d160a7c8a3cc1ab4b54b87db99f74b&developerId=4995&developerHash=cf0cf809fc5cb49896fae894f5c541362351d448&radius=5000&lat=52.049323524&layerName=taizegroep&phoneId=6f85d06929d160a7c8a3cc1ab4b54b87db99f74b&accuracy=100

    Response received from provider, validating…

    error validating provider response – Traceback (most recent call last): File “/base/data/home/apps/layarservice/live3092.340279941731361482/webapi20/apitesthandler.py”, line 167, in validate_response pois = json.loads(provider_response) File “/base/python_lib/versions/third_party/django-0.96/django/utils/simplejson/__init__.py”, line 232, in loads return cls(encoding=encoding, **kw).decode(s) File “/base/python_lib/versions/third_party/django-0.96/django/utils/simplejson/decoder.py”, line 251, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File “/base/python_lib/versions/third_party/django-0.96/django/utils/simplejson/decoder.py”, line 270, in raw_decode raise ValueError(“No JSON object could be decoded”) ValueError: No JSON object could be decoded

    JSON parse error( most likely)!, validate your response at http://www.jsonlint.com/

    Error validating response…

    Error:Layer not available

    1. That’s what i saw yes… but could it be script? because i copy pasted it… or is it the database?

      Line 31:
      $query = “SELECT id, title, lat, lng, (6378*acos(cos(radians(‘” . mysql_real_escape_string($center_lat) . “‘))*cos(radians(lat))*cos(radians(lng)-radians(‘” . mysql_real_escape_string($center_lng) . “‘))+sin(radians(‘” . mysql_real_escape_string($center_lat) . “‘))*sin(radians(lat)))) AS distance FROM layar WHERE id HAVING distance<’” . mysql_real_escape_string($radius) . “‘ LIMIT 0, 10″;

    2. It’s in the syntax so probably not in the DB.
      Please make sure quote marks are correct. They often get messed up when you cut&paste code.

  12. Hi
    i get the same error than eishita but with an internet adress

    Loading layer…

    found layer = layer01
    Loading POIs…
    loading POIs for page – null

    layer01 – passed authorization check

    oauth disabled…

    POI fwd url = http://91.121.12.81:8080/layar.php?countryCode=NL&lon=3.88306617737×tamp=1269963303974&userId=6f85d06929d160a7c8a3cc1ab4b54b87db99f74b&developerId=2750&developerHash=6544e244c3b63c2d6e0cccbfd27af8e80dccf491&lat=43.6093580971&layerName=layer01&phoneId=6f85d06929d160a7c8a3cc1ab4b54b87db99f74b&accuracy=100

    Unable to reach POI provider.

    Error:Layer provider not available

    i’m using easyphp 5.3.2 with apache 2.2.14 server on port 8080 and mysql 5.1.43
    with json support version 1.2.1

    Any help please

    1. When I click on the link I can’t establish a connection to the server. Verify that you have the right IP and that you can access the port from the outside world.

  13. Thanks for your great tutorial. I used it and have managed to upload some test POIs on the API test page and on my iPhone. However I have an issue with Nordic characters. They don’t seem to work well with POI ‘title’. When nordic characters in title the value becomes ‘none’ on both API test page and iPhone. How have you solved this?

    I think the language handling should be in the (php) code. So I’ve tried setting “lang” => ‘SV’ (and some variations) but it seems to be ignored by layar. I even tried changing db from latin1_swedish_ci to UTF8_swedish_ci. And if I hardcode for example ex Ö for Ö, then it looks good on API test page but not on iPhone (it shows Ö instead of Ö).

    Cheers!

    1. Thanks for your answer, conversion on string level solved the issue.

      I think it would be cool testing the solution you describe in the post about your coming geo query wp plugin.

  14. hi,there thanks for the tutorial, it seems simple, i will try it soon. I need to built a very simple layer for dissertation purpose. Can i still use this tutorial albeit layar already has a newer version?

    Also, i found a tutorial in this page..

    http://layar.pbworks.com/First+Layar+Tutorial+-+Create+a+simple+layer

    it looks different and more complicated than the one you gave above, what’s the difference between these two? for my purpose can i use yours instead of this?

    I am sorry if my question sounds stupid i am a noob in programming world. The purpose of my dissertation is just to conduct an user experience study about augmented reality suitability for shopping experience

    1. Thanks for your comment.

      Our tutorial will work with the current Layar version. We still use the same code base for commercial use.
      The other tutorial is probably better if you start from scratch and have never worked with Layar before. Our tutorial assumes pretty much and skip everything but the actual technical code.

      If you do have POI (Points Of Interest / addresses) and would like to prove a concept please let me know. We host Layar layers and setting up a new basic one is done within a couple of hours of work. This could save you time and money not only in the initial stages but also over time.

    2. Hi, thanks for the reply. i do have poi and yes i’m doing this for a prove of concept/fitness purpose test. So how can i host my layers on you? how much is the cost? thanks

  15. i got this error

    oauth disabled…

    POI fwd url = http://202.43.164.198/rizkidislayer.php?countryCode=NL&lon=-0.129089355469&timestamp=1278938137580&userId=6f85d06929d160a7c8a3cc1ab4b54b87db99f74b&developerId=21812&developerHash=e4282517c1d4636c1f513826ead36e4abaca9bbb&radius=4516&lat=51.4957059654&layerName=rizkidissertation&phoneId=6f85d06929d160a7c8a3cc1ab4b54b87db99f74b&accuracy=100

    Response received from provider, validating…

    error validating provider response – Traceback (most recent call last): File “/base/data/home/apps/layarservice/live313.343243777559663853/webapi20/apitesthandler.py”, line 168, in validate_response pois = json.loads(provider_response) File “/base/python_runtime/python_lib/versions/third_party/django-0.96/django/utils/simplejson/__init__.py”, line 232, in loads return cls(encoding=encoding, **kw).decode(s) File “/base/python_runtime/python_lib/versions/third_party/django-0.96/django/utils/simplejson/decoder.py”, line 251, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File “/base/python_runtime/python_lib/versions/third_party/django-0.96/django/utils/simplejson/decoder.py”, line 270, in raw_decode raise ValueError(“No JSON object could be decoded”) ValueError: No JSON object could be decoded

    JSON parse error( most likely)!, validate your response at http://www.jsonlint.com/

    Error validating response…

    Error:Layer not available

    What did i do wrong?

    1. The error responses gives you loads of clues on where to start searching.
      1. JSON parse error.
      2. Layer not available.

      If I try the actual URL I get PHP errors so I would take a look into php error log as well.

  16. Hey there,

    Good tutorial, I followed it but am getting an error alert in the API test page – it just says: parse error.

    Any ideas why this might be happening?

    Best

    Jim

    1. Parse error is probably just that, a parse error in your PHP code.
      Copy and paste the URL (which you should see in the API test page) into your browser.
      Then monitor Apache error_log to see what is causing the error.

    2. Hey,

      Thanks for replying again…I’m still getting the same error in the api test page.

      I also followed the on site tutorial for a simple Layar and get the same issue.

      J

  17. Hi,

    I got this error…

    Loading POIs
    Loading POIs for page #1
    oauth disabled…
    oauth disabled…
    POI fwd url = http://www.coart.nl/clients/layar/coartlayar.php?lang=en&countryCode=NL&lon=13.1554412842&userId=6f85d06929d160a7c8a3cc1ab4b54b87db99f74b&developerId=0&developerHash=3179c35ef1104dedbc9b211c3ac0e134fe1193ff&version=4.0&radius=4460&timestamp=1294330213578&lat=55.3812560135&layerName=coartstudio2&accuracy=100
    Response received from provider, validating…
    response code : 200
    error validating provider response – Traceback (most recent call last): File “/var/www/dev.layar.com/layar/publishing/api_testpage_mainproxy.py”, line 50, in validate_response data = validator.validate(data, schema) File “/var/www/dev.layar.com/layar/util/jsontransmogrifier.py”, line 524, in validate raise ValidationError(message=”, “.join(self.errors), errors=self.errors) ValidationError: Value u” for field ‘hotspots’ is not of type ‘array’
    JSON parse error( most likely)!, validate your response at http://www.jsonlint.com/
    error : Value u” for field ‘hotspots’ is not of type ‘array’
    error : Value u” for field ‘hotspots’ is not of type ‘array’
    Error: No content available

    Can someone help me please??

    1. Seems like you are working on it right now and you are closer to to a solution, right?
      When trying your URL I now get a valid JSON back.
      The error is obviously a JSON error and you need to make sure that what you return is valid JSON and that it conforms to what Layar expects.

Comments are closed.