Todavía no mostraremos el aspecto de la aplicación en el blog, pues hemos partido de una interfaz con botones muy sencilla que sólo utilizamos para hacer pruebas del software del robot y una primera monitorización básica de los sensores. Ya estamos trabajando en la mejora del aspecto de la interfaz y próximamente la presentaremos.
En el siguiente diagrama tenemos las cuatro clases de la aplicación Android:
MyAdapter.java
Nuestra aplicación estará formada por al menos 3 pantallas distintas: la relacionada con la monitorización de sensores, la de comandos que se pueden enviar al robot y la del control remoto. Esta clase es el Adapter que vamos a utilizar para acceder a nuestra colección de Views, es decir, nos permite hacer el cambio entre una pantalla y otra.
La clase MyAdapter.java implementa la interfaz TitleProvider y extiende la clase PagerAdapter. De esta manera, el cambio entre las pantallas se realizará de forma muy sencilla: a través de unas pestañas en la parte superior de la interfaz (tal y como se puede ver en la imagen) o simplemente deslizando el dedo hacia un lado de la pantalla.
El constructor de la clase toma como argumentos el contexto y un ArrayList de Linear Layouts (los títulos de las distintas páginas o pantallas que se pueden mostrar).
Los métodos más importantes que se implementan de PagerAdapter y TitleProvider en esta clase son:
- getTitle(): es el único método de TitleProvider, al que se le pasa como parámetro un entero que indica la posición de una página y devuelve el título de esa página.
- getCount(): devuelve el número de páginas que hay.
- instantiateItem(): crea las Views de la página correspondiente a una determinada posición
- destroyItem(): destruye Views que han sido creadas anteriormente.
Mientras el dispositivo móvil está conectado por Bluetooth al robot, recibe de él 3 bytes: el primero de ellos es la distancia a la que el sensor de ultrasonidos detecta un objeto, el segundo es el color de la siguiente pelota a disparar y el tercero el color del contenedor que tiene delante (en caso de que lo haya).
El método run() del hilo lee estos 3 bytes y los almacena en las variables “distance”, “ballColor” y “containerColor”. Posteriormente llama a distintos métodos de la actividad principal (pasando estas variables como parámetro) para que se muestre la información al usuario en la pantalla del dispositivo Android.
Las variables que encontramos dentro de esta Activity son:
- Todos los botones que aparecen en la interfaz: connectBtn, avanzarBtn, rotarBtn, parartBtn, disparartBtn, mapearBtn, procesarBtn.
- Un array de botones “buttons”, en el que se almacenarán todos los correspondientes a los comandos.
- Un ArrayList de Linear Layouts “layouts”.
- Una barra de progreso “pg” para mostrar la medida del sensor de distancia.
- Un TitlePageIndicator “titleIndicator”, que permite al Adapter saber qué página mostrar.
Los métodos más importantes dentro de esta actividad son los siguientes:
- public void onCreate(Bundle savedInstanceState): Llama al método setContentView() para dibujar por pantalla, configurando la aplicación para que se muestre en la pantalla entera (mediante la constante FLAG_FULLSCREEN de LayoutParams) y sin título en la parte superior (requestWindowFeature(Window.FEATURE_NO_TITLE)). Inicializa el ArrayList de LinearLayouts, con los layouts correspondientes a la página de comandos, de sensores y de control remoto. Crea un nuevo objeto de la clase MyAdapter para que se encargue de crear las Views correspondientes.
- private void initComponents(): Inicializa todos los botones de la aplicación y determina cómo deben responder los Listeners cuando se hace click sobre cada botón. En el caso de los botones asociados a comandos, se mandará por el stream de datos de salida el byte con los 3 bits de comandos que el robot debe interpretar.
- public void setBallColor(int color) y public void setContainerColor(int color): Ambos métodos hacen que se activen los indicadores que muestran de qué color es la pelota o el contenedor respectivamente que los sensores de color están detectando. Estos métodos son llamados desde el hilo Robot.java, que pasa como parámetro un entero asociado al color correspondiente (0 para el rojo, 1 para el verde, 3 para el amarillo y 4 para el azul).
- public void setDistanceSensor(int distance): Hace que la barra de progreso muestre la lectura del sensor de ultrasonidos, dando un valor entre 0 y 255. También se muestra como texto por la pantalla. Como ocurría con los dos métodos anteriores, el hilo Robot.java llama a este método pasando como parámetro el entero correspondiente a la distancia.
- public void onCreate(Bundle savedInstanceState): llama al método setContentView() para que se muestre por pantalla el layout de “control”. Crea un objeto del tipo DisplayMetrics, que nos permitirá obtener información sobre el tamaño y otras propiedades de la pantalla. Además, invoca a los métodos initComponents() y addListener() de esta actividad.
- private void initComponents(): Inicializa los botones de “disparar” y “parar”, así como la imagen sobre la que se podrá deslizar el dedo para indicar la dirección en que se debe mover el robot (denominada “joystick” a partir de ahora).
- private void addListener(): Este método determina cómo deben responder los Listeners a las interacciones del usuario. Al accionar el botón de disparar, se envía al robot el comando correspondiente (los bits de comando han de ser 011 para dar el control al behavior Shoot(), por lo que el byte enviado es 0x60). Al pulsar el botón de parar, se finaliza el control remoto poniendo a 0 la velocidad de ambos motores (Byte de comando = 0x20 para que se accione el behavior MotorSpeed() y bytes de velocidad 0x00 para parar los dos motores). Al tocar la imagen “joystick”, se calcula la velocidad y la dirección a la que se debe mover el robot y se le envía también por el stream de salida (el primer byte indicará el comando, el segundo la velocidad del motor derecho y el tercero la del motor izquierdo).
- Sacamos las coordenadas del centro de la imagen cenX y cenY, teniendo en cuenta que el origen del sistema de referencia se encuentra en la esquina superior izquierda de la pantalla del móvil.
- Obtenemos también las coordenadas x e y del punto donde se ha producido el evento de tocar la pantalla.
- Establecemos como el origen de coordenadas de nuestro nuevo sistema de referencia el centro de la imagen. Las nuevas coordenadas del punto donde se había producido el evento serán longX= x – cenX y longY= cenY – y.
- Expresamos este punto en coordenadas polares, obteniendo el módulo dist (proporcional al valor absoluto de la velocidad) y el ángulo arg (indica la dirección en la que se debe mover el robot; el robot avanzará si pertenece al primer y el segundo cuadrante y en otro caso retrocederá).
- Cuando estemos en el primer y el cuarto cuadrante, el motor A (derecho) debe rotar más despacio que el C (izquierdo), para poder girar hacia la derecha. Por este motivo, la velocidad del motor A irá multiplicada por el seno del ángulo ang.
- En cambio, en el segundo y el tercer cuadrante es el motor C el que debe girar más despacio para girar hacia la izquierda. En esta ocasión, la velocidad del motor C se multiplica por el seno del ángulo ang.
Aunque posteriormente iremos añadiendo alguna clase más en la aplicación Android para el reconocimiento de gestos, estas 4 son las clases fundamentales de la misma.
No hay comentarios:
Publicar un comentario