En las siguientes entradas que escribiré en el blog sobre esta temática estarán orientadas a explicar y mostrar a través de ejemplos ¿cómo mostrar Puntos de Interés (Point of Interest,POI) a través de la Realidad Aumentada con Wikitude?; esta primera entrada esta dedicada a introducir algunos conceptos claves y consideraciones sobre el uso de los proveedores de localización en Android y de los POI en Wikitude.
¿Qué es un Punto de Interés?
Un Punto de Interés es un lugar específico registrable a través de coordenadas geográficas (latitud, longitud y altitud) que es considerado de interesante por alguna persona: restaurantes, hoteles, edificios, etc son ejemplos de sitios de interés; para crear un Punto de Interés (POI) en Wikitude es necesario como mínimo la latitud y la longitud para ubicar un sitio en el espacio 2D, pero también es posible ubicar un sitio en un espacio 3D empleando la altitud.
Consideraciones sobre los proveedores de localización en Android
- Generalmente todos los dispositivos Android cuentan con al menos dos tipos de proveedores de localización:
- El conocido GPS: Que determina la ubicación del dispositivo a través de satélites.
- Por red móvil y WiFi: Que ubica al dispositivo mediante las antenas de telefonía móvil o mediante puntos de acceso Wi-Fi.
- Estos servicios que permite obtener la localización del dispositivo, en realidad, no devuelven la posición actual del dispositivo, si no la última posición válida que tengan registrado.
- Debes de habilitar al menos uno de ellos para poder trabajar con los Puntos de Interés, ve a Ajustes >> Acceso a tu ubicación, en tu dispositivo con Android:
- En todos los proveedores de datos existen márgenes de errores, en otras palabras; la precisión varía en metros e incluso kilómetros y esto puede deberse a muchos factores, cielo nublado, una obstrucción física entre el dispositivo y los satélites etc; por lo tanto no resulta de buena idea si deseas ubicar un sitio que requiera metros de precisión.
Consideraciones sobre los Puntos de Interés en Wikitude
- La API que permite trabajar con los Punto de Interés en Wikitude, está hecha para actualizarse constantemente según la posición del dispositivo; en otras palabras, debemos de estar cargando constantemente POIs cercanos a la posición del dispositivo, ya que es posible que este se desplace cierta cantidad de metros cada cierto tiempo, la aplicación que vayamos a diseñar debe de estar constantemente preguntando la posición del dispositivo y trayendo los Puntos de Interés cercanos a la posición del dispositivo; este tema lo trataremos en mayor detalle en la próxima entrada.
Primeros pasos con la API de Wikitude para definir un Punto de Interés en el ARchitect worlds
En esta sección creemos y mostraremos un simple POI desde el ARchitect worlds de Wikitude; no es necesario tener ninguno de los proveedores de localización habilitados, debido a que cargaremos sitios ficticios cercanos a la posición del dispositivo (la cual es cero si no hay una posición válida).
El método locationChangedFn para obtener la posición del dispositivo
Este método es invocado cada vez que haya una actualización en la posición del dispositivo; como podrás imaginar, recibe cuatro parámetros:
- Latitud de la localización.
- Longitud de la localización.
- Altitud de la localización.
- Precisión de la localización.
locationChanged: function locationChangedFn(lat, lon, alt, acc) {}
A partir de ahí, es posible crear todos los Puntos de Interés que deseamos; consultando mediante Servicios Web, HTTP, etc; para efecto de este artículo simplemente crearemos un Punto de Interés cercana a la posición del dispositivo:
var poiData = {
"id": 1,
"longitude": (lon + (Math.random() / 5 - 0.1)),
"latitude": (lat + (Math.random() / 5 - 0.1)),
"altitude": 100.0
};
Puede darse el caso que deseemos cargar los Puntos de Interés una única vez y que no se actualice sin importar el tiempo o la distancia transcurrida, para ello, empleamos una bandera:
World.initiallyLoadedData
La cual estableceremos en false
una vez que se realice la primera (y única) consulta a la posición del dispositivo; nuestro código quedaría de la siguiente manera:
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
}
}
El método loadPoisFromJsonData para construir y mostrar el Punto de Interés mediante la Realidad Aumentada
La función loadPoisFromJsonData es usada para crear objetos GeoObject, o objetos basados en la Realidad Aumentada según la posición:
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]
}
});
}
Analizando la función anterior...
Indicamos la imagen que funcionará como marcador o Punto de Interés:
World.markerDrawable = new AR.ImageResource("img/marker.png");
Creamos un objeto con una localización 3D en el espacio basada en coordenadas:
var markerLocation = new AR.GeoLocation(poiData.latitude, poiData.longitude, poiData.altitude);
Encapsulamos la imagen y le aplicamos ciertas operaciones a la misma:
var markerImageDrawable = new AR.ImageDrawable(World.markerDrawable, 2.5, {
zOrder: 0,
opacity: 1.0
});
Creamos un objeto virtual cuya posición está especificada a través del objeto markerLocation
:
// create GeoObject
var markerObject = new AR.GeoObject(markerLocation, {
drawables: {
cam: [markerImageDrawable]
}
});
Más información en la Wikitude SDK API Reference.
El código completo:
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;
En la siguiente entrada veremos cómo realizar la primera carga de datos obteniendo la ubicación del dispositivo desde el código nativo Java e invocar al JavaScript (locationChangedFn
) desde el código nativo Java con Android.
Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter