Augmented Reality, iPhone and ArcGIS Server
I am a HUGE fan of Augmented Reality, and one of my favorite applications on the iPhone is Layar. In this post, I will "walk you" through how to setup a simple ArcGIS Layar Point Of Interests (POI) layer and how to expose it through the iPhone application. In addition, I created a small Flex application that will enable you to add POIs to that feature class through a python geo-processor task.
BTW - this is heavily geared to using ESRI desktop and server tools and I'm assuming that you are familiar with these tools.
First, request a developer key from http://dev.layar.com/. This might take a couple of hours to get to you.
So, in the meantime, let's get started. Using ArcCatalog, create a new point feature class called 'Layar' in a geodatabase with the following fields: Title (text), Line2 (Text), Line3 (Text), Line4 (Text), Attribution (Text), Type (Integer), ImageUrl (Text:512).

Import that layer into a map document using ArcMap. Save and publish the MXD as a Map Service. Just to be on the safe side, clear your REST endpoint service directory cache and list the available services. You should now see the new map service and you can now query using REST the newly created 'Layar' layer.
Next, we need to populate this 'Layar' layer. With the Advent of ArcGIS 10, this could easily be achieved using the new FeatureTask endpoint. However, I'm still using a 9.3.X server and I will have to rely on a geoprocessing task to add point features to the Layar feature class. For the sake of simplicity and quick deployment, I decided to implement this GP task using python. So, using ArcCatalog, create a new GP Toolbox and add to the toolbox a new python script. You can download the script from here. Again, I'm assuming that you are familiar with all these tools. This script will have two parameters. The first input parameter should be named 'featureSet' of type 'FeatureSet' and its schema should reference the Layar feature class. The second parameter should be named 'objectID'. It has an output direction and is of type LONG. Basically what the script does; it expects a feature set with one feature. That feature is read using a cursor and placed in memory. Next an insert cursor is created on the Layar feature class and populated with the in memory information and executed. Upon a successful execution, the OBJECTID of the last inserted feature is retrieved and returned back as a parameter. The whole script is surrounded by a try: except: in case of an exception, where a -1 as an OBJECTID value is returned back. Simple but not simplistic :-) Publish this Toolbox, clear the cache and now you should have new GPService task.
To use this GP task interactively, I created a Flex based web application.
This application consists of a side-by-side map and form component enabling the user by zooming and panning to click and define POI coordinates and to populate that POI attributes. By clicking the Save button, the above publish GP task is invoked and upon a successful completion, the map is refreshed to show the newly added POI. The Flex application source code can be downloaded from here.
Now that we have created and authored this Layar information, we need to publish and consume it on the iPhone Layar application. The Layar folks have described in detail the JSON publishing format - http://layar.pbworks.com/GetPointsOfInterest. So what we need now, is a middleware that accepts an HTTP request from an iPhone, convert the input parameters to an ArcGIS REST query, invoke a query task whose URL is the Layar layer URL in the above publish map service, read the ArcGIS JSON response and convert to a Layar JSON response. Easy, eh ? That is why we have computers :-) I accomplished all this using Java Web Application - you can download the source code from here. This web application is basically a servlet that relies on the Apache HTTPClient library for http communication and the Jackson JSON processor library for fast consumption and JSON production. You might wonder why I decided to write this in Java versus say python. well...First, I'm a Java nut. Two, I can whip this up fairly quickly, Three, wanted to experiment with Google Java App Engine so I can be "in the cloud man !" - LOL, last one is just an artifact of the first two - but it is cool ! When the iPhone Layar application requests POI, it does so on a predefined URL (more on this later) with the following HTTP GET parameters, lat: your current latitude location, lon: your current longitude location, radius: the search radius in meters plus other parameters. In this application I'm just decoding lat, lon and radius.
Now that you have an in-the-cloud POI Layar endpoint and assuming that you have gotten your Layar developer key, you can sign in to http://dev.layar.com/ and create your own layer. The form will request a POI URL, enter your in-the-cloud poi servlet endpoint. All of the above was leading this point. I highly recommend that you test your layer using the Layar test page http://dev.layar.com/api20test/layarTestPage/.
To test this on your iPhone, go to "Settings" add add your developer ID and key to the Layar application settings. Launch the Layar application, and you should see your newly published layer.
This is just the tip of the iceberg. There is so much more that you can do, adjust and customize. I just wanted to share this "little" experience with you. Hope you found it useful and tell me what you think.


Comments
what is the flexapiutils.swc?
1) might have been a conflict with sdk's I was on 3.2; dropped in 3.5 so no longer was getting the flex error:
(TypeError: Error #2007: Parameter blendMode must be non-null....)
2) i needed to edit the script to point to my geodatabase.
3) had one or two typos on my side so fixed those.
4) checked permissions on the arcgis server, however, this is not enabled, so my assumption is they are not needed. is that correct?
also, checked permissions on the file system and checked groups and those are good for all users.
so the error is: object has no attribute strerror, on the server for the script.. which is good.
I will try and figure out a simple python script and see if i can figure out what is going on...
oh, does the Layar feature class need to be in a feature data set? the reference to featureSet for the input is confusing.. but I do see this is required in the documenation.
I was able to run the example you provided and add a point to your server... so i must be close
for this:
cursor = gp.searchcursor(rFC,"","","OBJECTID","OBJECTID D")
mod to this:
cursor = gp.searchcursor(rFC,"","","OBJECTID")
but maybe that second argument is needed.
i had pointed the path to my gdb but left the r and didn't replace \ with / in my path:
rFC = r"C:\MyData\MyGeodatabase.gdb\Layar"
as I am using access gdb should be kind a like this:
rFC = "C:\MyData\MyGeodatabase.mdb\Layar"
But on my first test server i was able to add these and the previous changes... and Success... although my coordinate was stateplane not wgs84..
but should be able to resolve this in the morning..
cool home work.
no pain, no gain.
the AGS/ GP using modeling or scripts, is a better solution than pure arcobjects...
since it limits the people working on a problem to heavy programming and or for flex coding, to solutions like weborb. GP using modeling is more intuitive, and can help get things out of the black box for the clients.
AGS/GP, as well as documentation, has matured, this is a great intro back into it... so thanks for the lesson.
Layars, sign up ask which layers I am developing... ? testing or publishing is the only layers right, or do they want a description of an application?
here is the correct format..tested it on your REST GP tool:
{"features":
[
{
"geometry":
{
"x":-157.8284740447998,
"y":21.277835369110107
},
"attributes":
{
"ImageURL":"",
"Type":0,
"Line2":"",
"Attribution":"",
"Line3":"",
"Line4":"",
"Title":""
}
}
]
}
this i pulled from the debug console using the tracetarget in the flex code.
so that is good.
Unless someone is well versed in geoprocessing on a server, I found these links useful:
1) Adding a New Service
2) Using Python for the geoprocessing
3 Flex api - geoprocessing tasks
4) All of the server related geoprocessing docs
The basic poi flex app is now working. Yeah!
I started off with a complex web file structure. Now that I switched to a simple web file structure and the app is working, I can work back to a more secure file structure. Nice, I am a fan of geoprocessing on the web. Thanks for helping me.
1) Instead of just tossing all files into one folder GP Tool Share Folder Structure use tooldata, scripts, doc, and scratch folders.
2) The GP task automatically creates, for a short time, any scratch spaces on the web server in the jobs folder; where any data is going to be written. it is a similar structure, but a different url, this image
compares GP tool share folders to AGS file
3) The tooldata folder contains either non-sde gdb or connect.sde files
4) I was having trouble with UNC's related to the script and toolbox. what worked for me is, open the toolboxes within arcmap, then test scripts in ArcMap. Copy the toolbox to the mxd location so it is in the web project url, find it in the username/applicationdata/esri/toolboxes folder. more on GP script tools
5) However, it is supposed to work as long as the SOC user is on the machine and has access. this is the toughest part so read:
Data access considerations for geoprocessing tasks
Okay, that wraps it up.
Thanks for the great AR application! I think I also caught your UC2010 flex viewer session in San Diego :-) very motivating!
But:
* the mapservice works, the py gp script runs, but I keep getting the "attribute strerror", which I think has to do with the in_memory workspace..? Any hints..
* Could you elaborate a bit more on the LayarWeb src and what steps (I use Eclips) I need to take to get a webapp running?
BTW: I use ArcGIS 9.3.1 SP2.
Thanks very much for any info!
Johan
Just an idea.