jueves, 5 de enero de 2012

Replicant: Mi proyecto final de carrera.

Bueno, llevo desconectado y va siendo hora de contarles exactamente porqué.
He estado trabajando en mi proyecto final de carrera y se ha llevado gran parte de mi tiempo fuera del trabajo por no decir casi todo.

Como sabía que esto iba a ser así decidí intentar atacar un problema que me interesara mucho para no perder la motivación por el camino (Cosa que me pasa con mucha frecuencia ;)) Así que comencé a desarrollar una idea que ha tomado forma bajo el nombre de Replicant.

El nombre proviene de la película BladeRunner, sí sí, de los replicantes, esas pobres máquinas que buscan sentido a su existencia mientras un poli, Deckard los persigue, también es verdad que se cargan a un par de personas por el camino, pero ... Bueno, da igual. Dudo mucho de que no la hayan visto aún, pero como de todo hay en la viña del Señor no les cuento el final.

Replicant se llama así porque pretende que las máquinas sean capaces de contar a quien les pregunte cuáles son sus capacidades, qué cosas saben hacer y que permitan, bajo determinadas condiciones, que otras máquinas o aplicaciones puedan tomar el control sobre ellas para poder desarrollar actividades más complejas.

La idea era desarrollar un pequeño protocolo que pudiera implementarse en pequeños dispositivos embebidos de manera que cualquier cacharrito pudiera entender qué se le pide y hacerlo. Suena bien ¿no?

Para ponerle la guinda al pastel el proyecto no consiste sólo en desarrollar el lenguaje sino en construir un dispositivo que lo interprete adecuadamente y una aplicación Android que sirva para controlar "replicantes". Ahí es nada.

Evidentemente esto ha tenido un precio, tenía que entregar el 9 de Enero y lo voy a dejar para Junio, ha sido imposible terminar las tres cosas a la vez. Me falta la aplicación Android ;).

¿Sobre qué plataforma funcionará Replicant?
Arquitectura básica Replicant.

Ahora mismo está diseñado para funcionar sobre Arduino, estoy escribiendo una librería que implementa toda la funcionalidad, de manera que con un include y un par de líneas de código en la función setup() de cualquier código Arduino podríamos transformar cualquier cosa en un Replicante.

Ahí va un primer ejemplo del primer código que utiliza Replicant:

#include "Replicant.h"
Replicant r = Replicant("rachel", "home", 200, response);

void setup() {
  pinMode(LLED_PIN, OUTPUT);
  r.attachActuator("Left LED", LOW, HIGH, false, NULL, setLeftLED);
  pinMode(RLED_PIN, OUTPUT);
  r.attachActuator("Right LED", LOW, HIGH, false, NULL, setRightLED);
  pinMode(RSERVO_PIN, OUTPUT);
  rServo.attach(RSERVO_PIN);
  r.attachActuator("Right Servo", 0, 180, false, NULL, setRightServo);
  pinMode(LSERVO_PIN, OUTPUT);
  lServo.attach(LSERVO_PIN);
  r.attachActuator("Left Servo", 0, 180, false, NULL, setLeftServo);
  pinMode(RWHEELSENSOR_PIN, INPUT);
  r.attachSensor("Right wheel sensor", "cm", false, getRightWheelRaw, getRightWheelProccessed);
  pinMode(LWHEELSENSOR_PIN, INPUT);
  r.attachSensor("Left wheel sensor", "cm", false, getLeftWheelRaw, getLeftWheelProccessed);
 
 
  attachInterrupt(0, rightEncoder, CHANGE);
  attachInterrupt(1, leftEncoder, CHANGE);
  Serial.begin(9600);
}
Como pueden ver, he marcado en naranja el código propio de la librería. Basta con incluir la Replicant.h y crear una instancia de un replicante.

La línea: Replicant r = Replicant("rachel", "home", 200, response);

Define a un replicante que se llama "rachel" y que pertenece a la comunidad "home", el siguiente parámetro es un timeout y el último un puntero a una función con la que la librería devuelve información.
Los dos últimos parámetros ahora mismo me preocupan poco, los dos primeros sí que les van a dar información sobre la idea que hay detrás de este proyecto. Cada replicante tiene un nombre y pertenece a una comunidad, por lo tanto, todos los cacharritos que tenemos pululando por casa podrían interactuar entre sí para hacer cosas más complejas. Esto se pone interesante.... :P

¿Qué puede hacer un Replicant?
Aquí entran en juego el resto de líneas del código de ejemplo.
Si ya han desarrollado algo con Arduino sabrán que en la función Setup se suelen configurar los pines de la placa como entrada y salida, la velocidad de transmisión del puerto serie, etc ... También se habrán percatado de que borrando las líneas en naranja lo que tienen es un código de inicialización de Arduino de lo más normalito.
Lo que hacemos con los métodos attachSensor y attachActuator es registrar qué dispositivos tiene un replicante para "sentir" su entorno y cuáles para "interactuar" con su entorno. 
Un sensor puede ser cualquier cosa desde un botón que nos indique si nuestro robotito móvil está chocando con la pared hasta un encoder óptico que nos permita calcular cuánto se ha desplazado una rueda.
Los actuadores habitualmente serán motores, servos, etc ...

Cuando definimos un sensor también le damos un nombre y algunos datos para que las aplicaciones u otros replicantes que puedan tomar el control del dispositivo en cuestión sepan qué se van a encontrar. Entre esta información pasamos las unidades en las que "mide" el sensor, si es digital o no y dos punteros a funciones que nos permiten obtener el valor crudo del sensor, es decir, exactamente lo que hay a la entrada y el valor procesado, ya pasado a las unidades correspondientes.

Representación de una operación compleja.
En el caso de los actuadores, también les damos nombre e indicamos los valores máximos y mínimos que pueden tomar, es decir, que les podemos enviar. También distinguimos entre actuadores con realimentación y sin realimentación y pasamos las funciones que permiten dialogar con estos actuadores.

Si nos quedásemos aquí, Replicant poco aportaría al panorama, la idea es que también sea capaz de describir operaciones complejas y que la aplicación o el replicante de control pueda utilizarlas de manera transparente. No podríamos decirle a un motor solamente gira 90º sino decirle directamente al robotito, muévete hasta que llegues a la latitud y longitud esta.

Rachel, la primera replicante.
En la peli, Rick Deckard se encuentra con una replicante que, dicho sea de paso, no está nada mal. Se llamaba Rachel.
Primer plano de Rachel.
Un poco a instancias de mi cosultor del proyecto (Gracias por la idea Víctor) denominé a la primera replicante así, Rachel.
Rachel es un pequeño robot móvil cargado de sensores y con un único criterio de diseño, que la estructura fuera fácilmente reproducible con materiales de ferretería. Estoy bastante harto de ver los pedazos de robotitos fabricados en fibra de carbono que después no me puedo construir en mi casa para cacharrear.
 Rachel está hecha con perfiles de aluminio de Leroy Merlin (No tengo comisión, aunque si el señor Merlin quiere esponsorizarme, aquí estamos, que me estoy dejando la vida entera en su tienda ;)) y un plástico que puede cortarse con un cutter que se llama PVC Multicell.
Rachel con su Shield y con la placa Wifly de Sparkfun.
El único capricho que me he permitido es pintar todo el chasis de rojo, releches, era la replicante guapa de la peli, no podía dejarla sin maquillar jejejeje. 
Aquí tengo que hacer un parón para agradecer a mis compañeros del seminario de Automoción que pintaron la estructura, en especial vaya mi agradecimiento a José Luis Delgado Marrero, un titán del que aprendo cada día.
Rachel tiene montados dos sensores frontales, un sonar de Maxbotics y un sensor Sharp IR para medir distancias.
Con el código en processing que publiqué hace no sé ni cuanto en este mismo blog fabriqué dos encoders ópticos, uno para cada rueda que se leen mediante dos sensores QRD1114 de Fairchild semiconductors. También monta dos resistencias LDR que permiten estimar la luminosidad de la sala por la que "pasea" Rachel.
Representación 3D de Rachel.
Como actuadores Rachel dispone de dos servos de rotación contínua que atacan a las dos ruedas frontales.
Por último, para comunicarnos con Rachel utilizo la placa WiFly de Sparkfun, que no es otra cosa que una interfaz Wifi.
Dado que soy ingeniero técnico en informática pero durante mi formación nadie pensó en enseñarme a hacer placas de circuito tuve que recurrir a otros tres titanes que además son compañeros de trabajo para que me ayudaran un poco, gracias a Paco Afonso, Ernesto Padrón y Juan José Montañez, todos esos sensores y los dos LEDS frontales del robotito se distribuyen gracilmente sobre un precioso shield de Arduino que yo me ocupé de destruir en el garaje por no tener un soldador en condiciones. ;)

¿Y ahora qué?
Pues ahora quedan pendientes varias cosas. 
La primera es que me he dado cuenta de que hay algunas sutilezas con los datos que se envían y que voy a tener que resolver. De momento sólo envío texto, pero a lo mejor tendría que considerar poder definir tipos concretos de datos.
La segunda es que me parece que la comunicación también debe ir en otro sentido, debería haber un mecanismo que permitiera a cacharritos como Rachel notificar cambios importantes. Por ejemplo, acabo de chocar contra un muro o me acabo de caer por un precipicio.

En cuanto la librería funcione más o menos la publicaré, junto con el diseño del shield. Lo he convertido de formato Eagle a Fritzing por una cuestión filosófica, lo que pasa es que no he podido comprobar aún que esta segunda versión funcione. 
A ver si esta semana lo compruebo todo y lo publico.
Mi intención es que este sea un proyecto totalmente abierto así que cuando entregue esto intentaré seguir haciéndolo crecer a ver si termina siendo útil.
Imagínense una impresora 3D imprimiendo piezas, un brazo robótico que las deposita terminadas en la parte superior de un robot móvil que las lleva hasta la estantería. 
Mientras con el mismo móvil con el que gobiernas toda esa comunidad abres la persiana robótica de casa y consultas el estado de la estación meteorológica que tienes en la azotea ;) 

¡Soñar es gratis y cuando soñamos juntos somos imparables!