Inicio > Realidad Aumentada > Creando una capa de Realidad Aumentada

Creando una capa de Realidad Aumentada

La cuestión es montar una capa de Realidad Aumentada (AR) en nuestra base de datos de nuestro servidor web con la que consigamos funcionar con Layar, la app más utilizada de AR.

Esta capa se puede escribir en varios lenguajes, pero voy a utilizar PHP. Es necesario:

  • Un servidor web con PHP (5.3 o superior) que soporte JSON.
  • Una base de datos MySQL (preferiblemente con phpMyAdmin).
  • El servidor web debe poder alcanzarse desde Internet (para poder hacer las  pruebas desde Layar), no podemos estar trabajando on un servidor local que no sirva a Internet.

Crear una capa en Layar.com

En primer lugar debemos crear la capa en Layar.com. Para ello debemos registrarnos en la web.

001CreandoCapa

Al final, como el nombre «capapruebas» estaba ya cogido, he utilizado «capaprugrx». Sólo permite letras en minúscula y números para los nombres de las capas.

Al crear la capa, podremos añadir muchos detalles, pero por ahora no entro, porque lo podremos editar más adelante.

Podremos cambiar iconos, banners, localización, categoría, etc.

002CreandoCapa

Una vez guardada la capa, nos aparecerá en el listado de Layers:

003CreandoCapa

El botón Request approval lo utilizaremos cuando tengamos la capa construida, para que los evaluadores de Layar nos la aprueben.

Preparando la Base de Datos

Con phpMyAdmin creamos un usuario exclusivamente para el acceso a esta base de datos, distinto al del acceso web y creamos una base de datos exlusiva para almacenar la información de la capa.

Esta base de datos será la que almacene la información de los POI (Point of Interest).

En principio sólo crearemos una tabla llamada POI, aunque se deben crear más tablas para habilitar características avanzadas, como acciones u objetos en 3D.

La estructura de la tabla debe ser la siguiente:

Éstos son los campos básicos, pueden ser añadidos más para otras características.

Creando tabla POI

Resultando la siguiente consulta de creación:

CREATE TABLE `POI` (
`id` VARCHAR( 255 ) NOT NULL ,
 `footnote` VARCHAR( 150 ) NOT NULL ,
 `title` VARCHAR( 150 ) NOT NULL ,
 `lat` DECIMAL( 13, 10 ) NOT NULL ,
 `lon` DECIMAL( 13, 10 ) NOT NULL ,
 `imageURL` VARCHAR( 255 ) NOT NULL ,
 `description` VARCHAR( 150 ) NOT NULL ,
 `biwStyle` ENUM( 'classic', 'collapsed' ) NOT NULL ,
 `alt` INT( 10 ) NOT NULL ,
 `doNotIndex` TINYINT( 1 ) NOT NULL ,
 `showSmallBiw` TINYINT( 1 ) NOT NULL ,
 `showBiwOnClick` TINYINT( 1 ) NOT NULL ,
 `poiType` ENUM( 'geo', 'vision' ) NOT NULL ,
 PRIMARY KEY ( `id` )
) TYPE = MYISAM

Recopilando información

Una vez creada la tabla, vamos a insertarle algún POI.
Para calcular la latitud y longitud, usamos el Qué hay aquí de Google Maps: Abrimos Google Maps, nos situamos sobre el punto en el que queremos localizar nuestro POI, pulsamos el botón derecho del ratón sobre el mismo y seleccionamos Qué hay aquí.
Qué hay aquí GoogleMaps Caleta
Con lo que obtenemos la latitud y longitud del punto:
GoogleMaps Que Hay Aqui
Y ahora añadiremos la información el POI a la base de datos:
Insertando POI La Caleta
Que resulta en la siguiente consulta INSERT de SQL:
 
INSERT INTO `cgim_ar`.`poi` (
`id` ,
 `footnote` ,
 `title` ,
 `lat` ,
 `lon` ,
 `imageURL` ,
 `description` ,
 `biwStyle` ,
 `alt` ,
 `doNotIndex` ,
 `showSmallBiw` ,
 `showBiwOnClick` ,
 `poiType`
)
VALUES (
'geo_1', 'Creado por @guirado_', 'La plaza de la Caleta de Granada', '37.187318', '-3.610399', 'http://www.movilidadgranada.com/images/maps/inicio.png', 'La localización de la plaza de la Caleta en Granada', 'classic', '', '', '', '', 'geo'
);

Construyendo un Servicio Web (WebService)

Ahora que ya tenemos un POI en la base de datos, debemos construir un webservice para que la plataforma de Layar pueda recoger la información. Necesita que se envíe la información como JSON, si tenemos PHP 5.2 o superior tendremos por defecto instalada esta opción.

Necesitaremos crear dos ficheros PHP para habilitar el webservice:

  • config.inc.php – Contiene la información de configuración de la base de datos
  • capapruebas.php – Es el fichero php principal. Será llamado por el servidor de Layar. Debe ser el mismo fichero que el definido en el campo API ENDPOINT URL cuando dimos de alta la capa.

config.inc.php

El primer fichero (config.inc.php) debe contener algo parecido a lo siguiente:

<?php
/* Pre-define connection to the MySQL database, please specify these fields based on your database configuration.*/
  define('DBHOST', 'localhost');
  define('DBDATA', 'database_name');
  define('DBUSER', 'database_username');
  define('DBPASS', 'database_password');
?>

Debemos cambiar el nombre del servidor, base de datos, usuario y contraseña.

Fichero principal (capapruebas.php)

En el script principal debemos:

Leer la petición GetPOIs (GetPOIs Request)

Basada en la definición de capa que hemos hecho, una petición HTTP GET con parámetros definidos ha sido enviada al POI URL.

Una lista completa de los parámetros de la petición puede encontrarse en la página de GetPOIs-Request.

Un ejemplo sería:

http://custom.layar.nl/FirstTutorial_POI.php?lang=en&countryCode=NL&lon=4.887339
&userId=6f85d06929d160a7c8a3cc1ab4b54b87db99f74b&developerId=4441
&developerHash=26ec094e19db2c4a82ebafa200ea2a5e87a7d671&version=4.0
&radius=2500&timestamp=1286357071952&lat=52.377544&layerName=layaroffice&accuracy=100

El código para esta implementación básica es el siguiente (más info en la documentación de layar):

<?php

// Incluimos el fichero de configuración de la base de datos
// Contiene el servidor, bd, usuario, contraseña.  
require_once('config.inc.php');

/*** Funciones ***/

// Ponemos los parámetros de la petición getPOI y sus valores en un array asociativo

function getRequestParams($keys) {

  $paramsArray = array();
  try {
    // En $keys tenemos los nombres de los parámetros GET
    // Para cada parámetro, almacenamos su valor correspondiente: $paramsArray['layarName'] = 'capaprugrx' 
    foreach( $keys as $key ) {
      if ( isset($_GET[$key]) )
        $paramsArray[$key] = $_GET[$key]; 
      else 
        throw new Exception($key .' el parámetro no se ha pasado en la GetPOI request.');
    }
    return $paramsArray;
  }
  catch(Exception $e) {
    echo 'Mensaje: ' .$e->getMessage();
  }
}// fin de la función getRequestParams 

// Conectamos con la base de datos
function connectDb() {
  try {
    $dbconn = 'mysql:host=' . DBHOST . ';dbname=' . DBDATA ; 
    $db = new PDO($dbconn , DBUSER , DBPASS , array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
    // set the error mode to exceptions
    $db->setAttribute(PDO::ATTR_ERRMODE , PDO::ERRMODE_EXCEPTION);
     return $db; 
  }// try
  catch(PDOException $e) {
    error_log('message:' . $e->getMessage());
  }// catch
}// fin de la función connectDb

// Pasar string a float
// Devuelve:
//   float ; Si la cadena está vacía devuelve NULL.
//
function changetoFloat($string) {
  if (strlen(trim($string)) != 0) 
    return (float)$string;
  return NULL;
}//changetoFloat

// Coloca los POIs recibidos en un array asociativo. los valores devueltos son asignados a
// $reponse['hotspots'].
//
// Argumentos:
//   db ; El manejador de la base de datos.
//   value ; Un array que contiene los parámetros que se necesitan recuperados desde
//           la GetPOI request. 
//
// Devuelve:
//   array ; Un array de POIs recuperados.
//
function getHotspots( $db, $value ) {
  // Definimos un array vacío llamado $hotspots.
  $hotspots = array();
/* Creamos la consulta SQL para recuperar los POIs que se encuentran dentro
   del 'radius' enviado desde la GetPOI request. 
   Los primeros 50 POIs son seleccionados.
*/

  // Se utiliza PDO::prepare() para preparar la sentencia SQL. Esta sentencia se utiliza por
  // motivos de seguridad, para combatir ataques de inyección SQL.
  // ':lat1', ':lat2', ':long' y ':radius' son marcadores de parámetros con nombre para
  // los que los valores reales serán sustituidos cuando la sentencia se ejecute.
  // $sql es devuelto como un objeto sentencia PDO. 
  $sql = $db->prepare( '
              SELECT id,
               imageURL,
               title,
               description,
               footnote,
               lat,
               lon,
               (((acos(sin((:lat1 * pi() / 180)) * sin((lat * pi() / 180)) +
                        cos((:lat2 * pi() / 180)) * cos((lat * pi() / 180)) * 
                      cos((:long  - lon) * pi() / 180))
                      ) * 180 / pi()
               )* 60 * 1.1515 * 1.609344 * 1000
               ) as distance
                FROM POI
         WHERE POI.poiType = "geo" 
       HAVING distance < :radius
      ORDER BY distance ASC
         LIMIT 0, 50 ' );

  // sentenciaPDO::bindParam() enlaza los marcadores de parámetros con nombre a los valores del parámetro específico   
  $sql->bindParam( ':lat1', $value['lat'], PDO::PARAM_STR );
  $sql->bindParam( ':lat2', $value['lat'], PDO::PARAM_STR );
  $sql->bindParam( ':long', $value['lon'], PDO::PARAM_STR );
  $sql->bindParam( ':radius', $value['radius'], PDO::PARAM_INT );
  // Utilizamos PDO::execute() para ejecutar la sentencia preparada $sql. 
  $sql->execute();
  // Iterador para el array response.
  $i = 0; 
  // Utilizamos fetchAll para devolver un array que contiene todas las filas restantes en
  // el result set.
  // Usamos PDO::FETCH_ASSOC para extraer los resultados de la consulta $sql y devolver cada fila como un
  // array indexado por nombre de columna.
  $rawPois = $sql->fetchAll(PDO::FETCH_ASSOC);

  /* Procesamos el resultado de $pois  */
  // si el array $rawPois no está vacío 
  if ($rawPois) {
    // Poner cada POI en el array $hotspots.
       foreach ( $rawPois as $rawPoi ) {
       $poi = array();
      $poi['id'] = $rawPoi['id'];
      $poi['imageURL'] = $rawPoi['imageURL'];
      // geolocalizamos el punto
      $poi['anchor']['geolocation']['lat'] = changetoFloat($rawPoi['lat']);
      $poi['anchor']['geolocation']['lon'] = changetoFloat($rawPoi['lon']);
      // obtenemos la información textual del objeto
      $poi['text']['title'] = $rawPoi['title'];
      $poi['text']['description'] = $rawPoi['description'];
      $poi['text']['footnote'] = $rawPoi['footnote'];
     // Ponemos el poi en el array $hotspots.
     $hotspots[$i] = $poi;
     $i++;
    }//foreach
  }//if
  return $hotspots;
}//getHotspots

/*** Inicio del programa principal ***/

/* Pone los parámetros de la GetPOI request en un array asociativo llamado $requestParams */
// Pone los nombres de los parámetros de la GetPOI request en un array llamado $keys. 
$keys = array( 'layerName', 'lat', 'lon', 'radius' );

// Inicializa $requestParams con un array vacío.
$requestParams = array(); 
// Llama a la función getRequestParams() para rellenar $requestParams con pares como 'layerName' -> 'capaprugrx'  
$requestParams = getRequestParams($keys);

/* Conecta con el servidor MySQL. Se utiliza PDO para conectar con la base de datos.
     Para más información sobre PDO: http://php.net/manual/en/book.pdo.php. 
 */    
// Conecta con la base de datos en MySQl.  
$db = connectDb(); 

/* Construimos la respuesta en un array asociativo.*/

// Crear array llamado response.
$response = array();

// Asignamos los valores correspondientes a las claves de respuesta obligatorias JSON.
$response['layer'] = $requestParams['layerName'];

// Utilizamos la función Gethotspots() para obtener los POIs en el rango de búsqueda.  
$response['hotspots'] = getHotspots($db, $requestParams);

// Si no se ha encontrado ningún POI, devolvemos un mensaje de error.
if (!$response['hotspots'] ) {
    $response['errorCode'] = 20;
     $response['errorString'] = 'Ning&uacute;n POI ha sido encontrado. Por favor, ajuste el filtro de b&uacute;squeda.';
}//if
else {
  $response['errorCode'] = 0;
  $response['errorString'] = 'ok';
}//else

    /* Todos los datos están en $response, los pasamos al formato JSON.*/

    // Ponemos la representación en JSON de $response en $jsonresponse.
    $jsonresponse = json_encode( $response );

    // Declaramos el tipo de contenido correcto en la cabecera de la respuesta HTTP.
    header( 'Content-type: application/json; charset=utf-8' );

    // Devolvemos la respuesta Json.
    echo $jsonresponse;

?>

Comprobando la capa

Ya estaría construido el webservice. Ahora debemos Testear la capa antes de publicar.

Tenemos dos métodos para probarla:

Página de testeo de la API

Abrimos la página de testeo, seleccionamos la API, el país, el idioma. Centramos el mapa en un punto en el que queramos probar la aplicación (en este caso me he ido a Granada) y pulsamos LOAD POI para probarla.

Testeando la capa

Desde el móvil, utilizando la aplicación Layar

Abrimos la aplicación Layar, nos debemos identificar con nuestro usuario y contraseña de desarrollador, nos vamos a la pestaña Desarrollador y estará nuestra capa, con lo que podremos probarla.

Por último, antes de poder enviar la petición de aprobación, habrá que añadir algunos detalles, como el icono de la aplicación (que será de 128×128), información detallada sobre la descripción de la capa, etc.

… (Continuará)

  1. David Rodríguez Naranjo
    27 de diciembre de 2013 a las 11:05

    Muchas gracias. Una información muy completa y útil.

  2. 18 de enero de 2015 a las 3:52

    y la continuación???

  3. 18 de enero de 2015 a las 8:04

    Y la continuación??

  1. No trackbacks yet.

Deja un comentario