Creating a Point of Interest with Augmented Reality in Wikitude Part 1

- Andrés Cruz

En español
Creating a Point of Interest with Augmented Reality in Wikitude Part 1

In the following blog posts that I will write on this subject, they will be oriented to explain and show through examples how to show Points of Interest (POI) through Augmented Reality with Wikitude?; this first entry is dedicated to introducing some key concepts and considerations about the use of location providers in Android and POIs in Wikitude.

What is a Point of Interest?

A Point of Interest is a specific place that can be registered through geographic coordinates (latitude, longitude and altitude) that is considered interesting by someone: restaurants, hotels, buildings, etc. are examples of places of interest; To create a Point of Interest (POI) in Wikitude you need at least latitude and longitude to locate a site in 2D space, but it is also possible to locate a site in 3D space using altitude.

Considerations for location providers in Android

Generally, all Android devices have at least two types of location providers:

  • The well-known GPS: Which determines the location of the device through satellites.
  • By mobile network and WiFi: Which locates the device through mobile phone antennas or through Wi-Fi access points.
  • These services that allow obtaining the location of the device, in reality, do not return the current position of the device, but the last valid position that they have registered.
  • You must enable at least one of them to be able to work with Points of Interest, go to Settings >> Access to your location, on your Android device:
  • In all data providers there are margins of error, in other words; the precision varies in meters and even kilometers and this can be due to many factors, cloudy skies, a physical obstruction between the device and the satellites etc; therefore it is not a good idea if you want to locate a site that requires precision meters.

Wikitude Points of Interest Considerations

  • The API that allows working with Points of Interest in Wikitude is made to be constantly updated according to the position of the device; In other words, we must constantly be loading POIs close to the position of the device, since it is possible that it moves a certain number of meters every so often, the application that we are going to design must constantly ask for the position of the device and bring the Points of Interest close to the position of the device; we will discuss this topic in greater detail in the next entry.

First steps with the Wikitude API to define a Point of Interest in the ARchitect worlds

In this section we create and display a simple POI from Wikitude's ARchitect worlds; it is not necessary to have any of the location providers enabled, as we will load dummy sites close to the device's position (which is zero if there is no valid position).

The locationChangedFn method to get the position of the device

This method is called every time there is an update on the device's position; as you can imagine, it receives four parameters:

  • Latitude of the location.
  • Location longitude.
  • Location altitude.
  • Location accuracy.
locationChanged: function locationChangedFn(lat, lon, alt, acc) {}

From there, it is possible to create all the Points of Interest that we want; consulting through Web Services, HTTP, etc; for the purpose of this article we will simply create a Point of Interest close to the position of the device:

    var poiData = {
       "id": 1,
       "longitude": (lon + (Math.random() / 5 - 0.1)),
       "latitude": (lat + (Math.random() / 5 - 0.1)),
       "altitude": 100.0
    };

It may be the case that we want to load the Points of Interest only once and that it is not updated regardless of the time or distance elapsed, for this, we use a flag:

World.initiallyLoadedData

Which we will set to false once the first (and only) query to the device position is made; our code would be as follows:

locationChanged: function locationChangedFn(lat, lon, alt, acc) {
    // valido que es la primera vez que estoy recibiendo datos (lat, lon, alt, acc)
    if (!World.initiallyLoadedData) {
        var poiData = {
            "id": 1,
            "longitude": (lon + (Math.random() / 5 - 0.1)),
            "latitude": (lat + (Math.random() / 5 - 0.1)),
            "altitude": 100.0
        };
        World.loadPoisFromJsonData(poiData);
        World.initiallyLoadedData = true;// recibi datos, no me interesa actualizar los datos segun la posicion del dispositivo
    }
}

The loadPoisFromJsonData method to build and display the Point of Interest using Augmented Reality

The loadPoisFromJsonData function is used to create GeoObject objects, or Augmented Reality based objects based on position:

	loadPoisFromJsonData: function loadPoisFromJsonDataFn(poiData) {
		World.markerDrawable = new AR.ImageResource("img/marker.png");
		var markerLocation = new AR.GeoLocation(poiData.latitude, poiData.longitude, poiData.altitude);
		var markerImageDrawable = new AR.ImageDrawable(World.markerDrawable, 2.5, {
			zOrder: 0,
			opacity: 1.0
		});

		// create GeoObject
		var markerObject = new AR.GeoObject(markerLocation, {
			drawables: {
				cam: [markerImageDrawable]
			}
		});
	}

Analyzing the previous function...

We indicate the image that will work as a marker or Point of Interest:

World.markerDrawable = new AR.ImageResource("img/marker.png");

We create an object with a 3D location in space based on coordinates:

var markerLocation = new AR.GeoLocation(poiData.latitude, poiData.longitude, poiData.altitude);

We encapsulate the image and apply certain operations to it:

		var markerImageDrawable = new AR.ImageDrawable(World.markerDrawable, 2.5, {
			zOrder: 0,
			opacity: 1.0
		});

We create a virtual object whose position is specified via the markerLocation object:

		// create GeoObject
		var markerObject = new AR.GeoObject(markerLocation, {
			drawables: {
				cam: [markerImageDrawable]
			}
		});

More info Wikitude SDK API Reference.

Complete code:

var World = {
	initiallyLoadedData: false,

	markerDrawable: NULL,

	loadPoisFromJsonData: function loadPoisFromJsonDataFn(poiData) {

		World.markerDrawable = new AR.ImageResource("img/marker.png");

		var markerLocation = new AR.GeoLocation(poiData.latitude, poiData.longitude, poiData.altitude);
		var markerImageDrawable = new AR.ImageDrawable(World.markerDrawable, 2.5, {
			zOrder: 0,
			opacity: 1.0
		});

		var markerObject = new AR.GeoObject(markerLocation, {
			drawables: {
				cam: [markerImageDrawable]
			}
		});
	},
	locationChanged: function locationChangedFn(lat, lon, alt, acc) {

		if (!World.initiallyLoadedData) {
			var poiData = {
				"id": 1,
				"longitude": (lon + (Math.random() / 5 - 0.1)),
				"latitude": (lat + (Math.random() / 5 - 0.1)),
				"altitude": 100.0
			};

			World.loadPoisFromJsonData(poiData);
			World.initiallyLoadedData = true;
		}
	},
};
AR.context.onLocationChanged = World.locationChanged;

In the next entry we will see how to perform the first data load by obtaining the location of the device from the native Java code and calling the JavaScript (locationChangedFn) from the native Java code with Android.

Andrés Cruz

Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz In Udemy

I agree to receive announcements of interest about this Blog.