AR Screen - GhostBusters-APM/GhostHouse GitHub Wiki

La tarea de Realidad Aumentada hace uso de la cámara del dispositivo móvil para reconocer una etiqueta QR establecida como target. Sobre su superficie superpone un modelo 3D de un botón que al presionarlo llama a un método en Android que envía una petición MQTT para activar el dispositivo deseado y previamente asociado a la aplicación.

Para la implementación se ha hecho uso de 4 plataformas.

  • Autodesk Maya 2018: Utilizada para la creación del modelo del botón y su animación.
  • Vuforia: Plataforma que proporciona las herramientas de AR necesarias.
  • Unity: Creación de la aplicación de AR con las herramientas proporcionadas por Vuforia. Además de las tareas específicas de AR, también se encarga de la detectar la pulsación sobre el botón, reproducir la animación del botón en los momentos adecuados, y generar la petición MQTT.
  • Android/Android Studio: Tras su creación en Unity, la aplicación se embebe a su vez en la aplicación de Android.

Maya

A través de Autodesk Maya 2018 se crea el modelo 3D y se configuran las diferentes animaciones que se llevarán a cabo cuando el usuario pulse el botón.

Modelo 3D

Vuforia

Se ha empleado vuforia para la generacion de los marcadores, en particular el marcador empleado es el siguiente

Marcador

Se ha intentado emplear los frame markers de vuforia, sin embargo estos se encuentran descontinuados por parte del equipo y ya no son soportados, en su lugar existen una nueva variante pero estos son de pago y no se pueden emplear actualmente de forma gratuita.

Unity

Detección de la pulsación

Para detectar cuando el usuario pulsa en el botón para encender o apagar el dispositivo, se utiliza un rayo (Raycast) que comprueba si se ha colisionado con el modelo. El rayo guarda los objetos con los que ha colisionado, por lo que se comprueba si el objeto con el que ha colisionado es el Switch.

    if ((Input.touchCount > 0) && (Input.GetTouch(0).phase == TouchPhase.Began))
    {
        Ray raycast = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
        RaycastHit raycastHit;
        if (Physics.Raycast(raycast, out raycastHit))
        {
            Debug.Log("Something Hit");
            if (raycastHit.collider.name == "Switch")
            {
                [...]
            }
                           
        }
    }

Petición MQTT

Si el usuario ha pulsado el botón, en función de su estado (apagado o encendido), se llama a una función correspondiente en Android que a través del estado que recibe como parámetro realiza la llamada MQTT bien para encender el dispositivo, o bien para apagarlo.

Esto es posible mediante la creación de un plugin android que se conecte con unity. Este plugin requiere de 3 parámetros, el contexto, el callback y el encendido o apagado.

Para invocar al método se genera la llamada a java mediante el siguiente proxy

 //Instanciacion de la clase ArPlugin que ha de estar definida en el proyecto Android
 AndroidJavaObject arPlugin = new AndroidJavaObject ("com.github.ghostbusters.ghosthouse.helper.unity.ArPlugin");
// Invocación del metodo no estático call, con los parametros, callback, context y la variable de encendido
 arPlugin.Call ("call", new AndroidPluginCallback (),context,off);

Obtención del contexto de ejecución en unity

//Obtiene la clase de utilidad UnityPlayer
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
//Invoca al método estatico currentActivity y recupera la actividad
AndroidJavaObject activity = unityPlayer.GetStatic("currentActivity");
//Para la actividad obtiene el contexto
AndroidJavaObject context = activity.Call("getApplicationContext");

Creación del callback, en este caso es un androidProxy que implementa la interfaz ArPluginCallback

  class AndroidPluginCallback : AndroidJavaProxy
    {
        public AndroidPluginCallback() : base("com.github.ghostbusters.ghosthouse.helper.unity.ArPluginCallback") { }

        public void onSuccess(string message)
        {
            Debug.Log("ENTER callback onSuccess: " + message);
        }
        public void onError(string errorMessage)
        {
            Debug.Log("ENTER callback onError: " + errorMessage);
        }
    }

Animación

Además de comunicarse con la aplicación Android, cuando se pulsa el botón también se activa la animación del modelo, como se puede ver en el fragmento de código que se muestra a continuación. Para esto se tiene en cuenta el estado del dispositivo, es decir, si este se encuentra encendido o apagado, y además se enciende una luz verde o roja en función en uno u otro estado.

            if (raycastHit.collider.name == "Switch")
            {
                if (off) 
                {
                    Debug.Log ("Switch On");
                    anim.SetTrigger ("SwitchOn");
                    off = false;
                } else 
                {
                    Debug.Log ("Switch Off");
                    anim.SetTrigger ("SwitchOff");
                    off = true;
                }
            }

También es necesario un controlador de la animación en Android, que establece las transiciones entre las animaciones activándolas cuando de manera programática se activa el Trigger oportuno, como puede verse en el fragmento anterior. En la siguiente imagen se muestra el esquema de animación utilizado.

Animacion Unity

Android

Una vez creada la aplicación en Unity, esta se exporta en forma de proyecto Android, y desde el proyecto generado (que contiene tan solo la parte de Realidad Aumentada), se genera un archivo aar que se importa en el proyecto de la aplicación completa, permitiendo de esta manera embeber la aplicación Unity en la aplicación de Android del proyecto.

⚠️ **GitHub.com Fallback** ⚠️