Hoy presentamos una parte de la estructura básica del software del robot: el establecimiento de las conexiones Bluetooth con otros dispositivos y la gestión de la pila de los comandos que recibe de ellos. En la siguiente entrada, veremos cuáles son estos comandos que el robot puede ejecutar y cómo estructura sus prioridades.
Todo el software está programado en Java, utilizando como herramienta de desarrollo el Eclipse con el plugin de la plataforma leJOS. LeJOS es un proyecto open source: un firmware que reemplaza al original de Lego y nos permite programar el robot en Java. Incluye su propia JVM (Java Virtual Machine) y su propia API (Application Programming Interface) con muchas clases que pueden ser implementadas por los programadores para tener una mayor funcionalidad.
En el siguiente diagrama de bloques podemos ver cuáles son las clases que forman el software del robot y cómo se relacionan entre ellas:
A continuación pasamos a explicar con más detalle las clases marcadas en rojo en el diagrama:
- Main.java
Esta clase tiene dos objetivos principales: el primero de ellos es lanzar el hilo encargado de las comunicaciones Bluetooth; el segundo, lanzar un árbitro que se encargue de controlar el comportamiento del robot en función de unos niveles de prioridad. Este último aspecto mencionado será explicado con detalle en la próxima entrada del blog.
- DataExchange.java
La misión de esta clase es actuar como nexo de unión entre todos los comportamientos que puede tener el robot. Por un lado, almacena toda la información que han de compartir, como el estado de los sensores; por otro, se encarga de gestionar la pila de los comandos pendientes del robot.
Las variables de esta clase son:· Radio de acción del robot (distancia máxima a la que puede encontrarse un contenedor para ser detectado)
· Distancia de seguridad (margen que deja el robot al acercarse a un contenedor para detectar su color)
· Streams de datos de entrada y de salida (se importan las clases java.io.DataInputStream y java.io.DataOutputStream)
· Boolean “conectado” (se pone a “false” para cerrar la conexión Bluetooth)
· Pila de comandos pendientes de ser ejecutados
· Listado de contenedores detectados hasta el momento
· Factor de giro para las rotaciones de los motores
· Lectura del sensor de ultrasonidos
· Lecturas de los sensores de color: tanto el que apunta a los contenedores como el que detecta el color de los residuos.
Los métodos que encontramos en esta clase son:
· Getters y setters para leer o modificar los valores de las variables. De todos ellos, la única cuestión de interés es que para almacenar, leer o borrar un comando de la pila, es necesario usar el modificador “synchronized” para evitar accesos simultáneos en la pila.
· public static void avanza(int dist, boolean reverse): hace que el robot avance (reverse == false) o retroceda (reverse == true) la distancia en centímetros pasada como parámetro. Para que los motores muevan las ruedas, hay que expresar esta distancia en forma de ángulo que queremos que giren. Como cada rueda tiene un diámetro de 4,32 cm, el ángulo que tendrá que girar para avanzar una distancia “dist” y dejar un margen de seguridad “DIST_SEG” para no chocarse será: int rotar = (int) (360 * ((dist - DIST_SEG) / (4.32 * Math.PI)));
- Container.java
Un objeto de la clase Container representa un contenedor donde se pueden almacenar los residuos. Cada vez que el robot detecte un nuevo contenedor, se creará un objeto de esta clase. Las variables de esta clase son:
· Ángulo: ángulo que tiene que girar el robot desde su posición inicial para estar orientado hacia ese contenedor.
· Distancia: una vez que el robot se orienta hacia el contenedor, distancia de él a la que se encuentra.
· Color: color del contenedor.
- BTConnection.java
Es un hilo que se ejecuta en paralelo con el resto del programa y se encarga de la comunicación Bluetooth: espera una nueva conexión y, cuando la tiene, recibe bytes de comandos y datos de 4 en 4. Esto se realiza a través de dos métodos:· waitForConnection()
Es el método encargado de esperar a una conexión entrante y, cuando la encuentra, abrir los streams de datos de entrada y de salida, tal y como se ve en el siguiente diagrama de estados:· run()
Mientras haya una conexión activa, este método se encargará de leer los bytes de entrada de 4 en 4. El pseudocódigo de este método es:
while(DataExchange.isConnected()) {
if(“Hay datos del DataInputStream”) {
//Añadirlos a la pila de comandos }
}
//Cerrar el DataInputStream
//Cerrar el DataOutputStream
//Cerrar la NXTConnection
No hay comentarios:
Publicar un comentario