fin de la primera parte

Por fin he terminado la primera parte de presencebot. El último paso ha sido refinar el movimiento del servo y le he añadido un par leds rojos que hacen de ojos.

Incluso con la escasa capacidad de movimiento de este robot, he descubierto que puede ser bastante expresivo.

Simplemente jugando con los siguientes elementos se pueden conseguir varios efectos sorprendentes:

- Velocidad de movimiento del servo: inicialmente estaba moviendo el servo a la velocidad máxima. Esto hacía que el robot pareciese muy brusco, incluso agresivo. Modificando el programa para que tenga un movimiento más suave, el resultado es que el robot perece más tranquilo. Así que finalmente he hecho una combinación de ámbos efectos: cuando el robot se despierta (al detectar la presencia on-line), se mueve bruscamente hacia arriba. Cuándo el robot detecta la ausencia on-line, se vuelve tristón y lentamente se mueve la posición más baja.

- Guiños: a pesar de que los ojos no son funcionales, el simple hecho de tenerlos ya transmite sensaciones (es lo malo de ser humanos). He probado a realizar guiños y aunque parezca una tontería le da más sensación de realismo. En la versión actual, el robot guiña al despertarse (cómo si estuviese sorprendido) y “cierra los ojos” (se apagan los led) al entrar en la posición de dormido.

- Rebote: el último cambio que he introducido es un rebote al reaccionar. El movimiento inicial era muy brusco, pero casi es más realista que un movimiento lento y preciso. Por otra parte, haciendo pruebas he detectado que es importante el feedback físico. Por ejemplo, si el robot está en la posición más alta posible y le envías una orden para avanzar más. Algo tan tonto cómo un ligero rebote en el tope indica física y visualmente que el robot ha recibido la orden y ya no se puede mover más. Por otra parte, al pasar a la posición “despierto” he añadido un pequeño rebote junto al guiño anterior. El resultado es que el robot tiene un despertar más dinámico y realista.

Estos efectos no hacen magia, se trata de un robot muy sencillo, pero creo que es útil saberlo. Si conseguimos fabricar un robot muy complejo, siempre tendremos en contra el efecto valle inexplicable y con movimientos tan sencillos como éstos conseguimos reducir el efecto.

Estos días publicaré algún video, fotos y código fuente. Y próximamente empezaré con modificaciones que se me han ocurrido para la siguiente versión: mejoras estéticas, más comandos y reacciones más complejas y añadir nuevos sensores.

construción física de presencebot

La semana pasada me puse con la construcción física de presencebot. Se trata de un robot muy sencillo por lo que por ahora no he querido complicarlo.

Lo interesante es que me he basado en un juego imitación de meccano hace tiempo. No recuerdo el precio, pero me salió muy barato. Mi principio para experimentar es utilizar tecnología que sea lo más flexible posible, incluso para la parte mecánica de un robot.

En programación intento usar lenguajes dinámicos, siempre que el rendimiento no sea una barrera. En especial intento usar ruby que desde el principio me ha parecido un lenguaje muy flexible.

En hardware es más difícil, pero también se puede hacer algo. No soy un experto en hardware y estructuras mecanicas, pero estos son algunas de las combinaciones de materiales y técnicas que he usado para construir prototipos rápidos de robots:

  • Lego y similares: el más clásico de los juegos de construcciones, piezas de plástico con muchas formas y colores que permiten construir casi cualquier cosa. Probablemente no sea demasiado resistente, pero es muy divertido. Una alternativa es usar Fishertechnik, que utilicé en el robot demi PFC, es algo más resistente, pero sigue siendo un juguete.
  • Meccano y similares: me refiero a las piezas metálicas que van atornilladas, no a las imitaciones de plástico. Algo más resistentes, pero en la misma linea que el lego. Suele haber menos variedad de piezas, pero el robot nos puede durar un poco más.
  • Cartón y pistola de pegamento: nunca he usado esta técnica, pero he leido de gente que la usa. Desde luego parece una técnica muy sencilla y rápida. También barata, las pistolas de pegamento son muy baratas y el cartón se puede conseguir de cualquier sitio. Otra cosa es lo que nos puede durar el artilugio…
  • Madera: aquí depende de las habilidades y herramientas de cada uno. Hay muchas cajas que pueden ser reutilizadas (sobretodo las cajas de vino ahora en navidad) y es la opción más fácil. Otra es comprar planchas de madera. Dependiendo de nuestra habilidad, esta técnica no se puede considerar de “prototipado rápido”.
  • Reutilización de juguetes: tengo una caja de una vaporetta que tengo pendiente reutilizar. Tiene el tamaño apropiado: pequeña, redondeada, con ruedas “caster” incorporadas. También es rápido hacer prototipos de esta forma reutilizando jueguetes. Pero ojo, igual que con la madera, si no somos hábiles, nos puede llevar más tiempo que el considerable para un prototipo.
Mecanos de lonoak

Mecanos de lonoak

Como decía, con presencebot me he limitado a trabajar con una imitación de meccano y con servos, para evitar tener que lidiar con controladores de motores (conectar y controlar). En este caso ha sido muy sencillo, lo normal es que nolo sea tanto.

comunicación por puerto serie con ruby

Llegó el momento de conectar los dos módulos de software que he estado preparando: el controlador de servos de arduino y un programa ruby para detectar la presencia online de un usuario.

Para enviar mensajes por el puerto serie desde un programa ruby, estoy usando la librería ruby-serialport. Se trata de una librería relativamente antigua, que no se actualiza desde 2004, pero que funciona bien, aunque con algún problema que he encontrado.

Cómo se puede ver en un ejemplo de la documentación de arduino, la librería es muy sencilla de usar:

1.- Primero se incluye la dependencia:

require “serialport.so”

2.- Después se inicializa la comunicación con el puerto serie:

#params for serial port
port_str = “/dev/ttyUSB0″ #may be different for you
baud_rate = 115200
data_bits = 8
stop_bits = 1
parity = SerialPort::NONE

sp = SerialPort.new(port_str, baud_rate, data_bits, stop_bits, parity)

3.- Se leen y/o escriben datos según se necesite:

sp.putc(GO_UP_SYMBOL)
printf(“%c”, sp.getc)

4.- Por último se se cierra el puerto cuando se deja de usar:

sp.close

El problema que he encontrado con esta librería, es que para leer y escribir en el puerto serie, he creado una clase específica. Al incluir la clase en mi programa principal, no podía acceder al puerto serie, ya que se obtenía el siguiente error:

(eval):1: (eval):1:in `private_class_method’: undefined method `create’ for class `Class’ (NameError)
from (eval):1
from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `require’
from ./serialpresencebot.rb:1
from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require’
from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `require’
from ./presencebotlauncher.rb:3

Finalmente, he tenido que incluir la librería en el programa principal y eliminar el “require” de la clase que controla el puerto serie para que funcionase. Quizá se trate de un problema de funcionamiento de ruby, pero parece más probable que se trate de un problema con la librería ruby-serialport. En cualquier caso, es sencillo de resolver.

moviendo un servo con arduino

Después de conectar con la librería windows live presence, el siguiente paso en el miniproyecto presencebot es controlar un servo con la tarjeta arduino.

Lo más fácil es seguir las indicaciones de la documentación de arduino que incluyen un ejemplo de control de un servo. Añadiendo un poco de código para leer el puerto serie, conseguimos un programa muy sencillo al que se le pueden enviar comandos con minicom para controlar el servo. Dado que presencebot sólo controla los eventos online/offline, por ahora sólo he implementaro los comandos de posición alta y posición baja y un comando que devuelve la posición actual del servo.

El único problema en la librería de control de servos es que limita la temporización de nuestro programa: no podemos poner las instrucciones delay que queramos. Existe una versión nueva de la librería (SoftwareServo) que obliga a hacer el refresco de forma implicita: hay que llamar a una función refresh cada 50ms para que el servo actualice su posición. También existe una librería de control de servos mediante hardware que no tiene la limitación de temporización, pero está limitada a 2 servos.

En mi caso estoy usando la librería software, aunque probablemente termine usando la librería hardware. Para resolver el problema de la temporización en el caso del encendido/apagado de un led, he creado una función que controla el momento en el que se encendió el led y si ha pasado el tiempo suficiente, lo apaga. Ésta función hay que llamarla periódicamente, pero aunque sería mejor tener interrupciones temporales, en arduino es normal tener un ciclo de control periódico.

Sobre el protocolo de comunicación, prefiero que sea lo más sencillo posible y preferentemente en modo texto, para que se pueda trazar leyendo el ASCII directamente. Aunque sea menos eficiente en el consumo de ancho de banda (por ahora no es una cuestión importante), prefiero saber qué está haciendo sin necesidad de interpretar instrucciones en hexadecimal.

La experiencia con arduino es buena, es una placa versátil y potente (y eso que tengo la versión NG que ya está algo desfasada), tiene un coste relativamente bajo y cada vez hay más código y ejemplos en internet para usar esta tarjetita.

pruebas con Windows Live Presence API

Estoy empezando a hacer algunas pruebas con presencebot, un experimento sencillo que consiste en reflejar de forma física la presencia virtual en messenger de microsoft.

Para obtener el estado online de una persona, estoy utilizando la librería Windows Live Presence API, que no es más que un api json para obtener el estado online de un usuario de messenger, que previamente se tiene que haber registrado. Usar este api tiene la ventaja de que es web y por lo tanto accesible desde cualquier lugar con conectividad a internet y la desventaja de que al ser web es más lento que un plugin local de messenger.

Otra ventaja es que el funcionamiento del api es muy sencillo, sólo hay que seguir los siguiente pasos:

1. Aceptación de condiciones: Antes de usar el API, la aplicación debe hacer que el usuario se inscriba en el servicio y acepte las condiciones de uso. El registro se hace en la siguiente url:

http://settings.messenger.live.com/applications/websignup.aspx?returnurl=[URL]&privacyurl=[URL]

Los parámetros que debemos enviar son returnurl con la dirección de vuelta una vez que el usuario ha aceptado (ó rechazado) la entrada en el servicio y privacyurl que debe apuntar a un texto explicativo de las condiciones de privacidad de nuestra aplicación.

Si el usuario acepta, es envíado a returnurl, cón los siguientes parámetros id y result. Result nos informa del resultado del registro: Accepted si acepta registrarse, Declined si rechaza el registro, NoPrivacyUrl si privacyurl no es válida. Id nos devuelve el identificador del usuario, que se necesitará para hacer la consulta propiamente dicha.

2. Consulta del estado: Después del registro, el estado del usuario se puede consultar en la siguiente url:

http://messenger.services.live.com/users/[ID]/[resource]

Id es el recibido en returnurl y sirve para identificar al usuario. Hay que tener en cuenta que es case sensitive así que cuidado con las mayúsculas/minúsculas. Resource puede tomar los valores presence ó presenceimage. En el primer caso se obtiene un objeto json con el estado online del usuario y en el segundo la url de una imagen que representa el estado online.

En esta url se pueden encontrar los elementos devueltos en el objeto json. El que me interesaba en este caso es “status” que puede tener los valores conocidos de msn:

Online, Away, Idle, BeRightBack, Busy, OutToLunch, OnThePhone, Offline

Con ruby se puede hacer un programa que chequee el estado online en apenas 15-20 líneas, cuando tenga terminado el proyecto publicaré el código fuente.

Realmente es un api muy sencillo de usar, con la única pega de que una vez que el usuario se ha registrado, cualquier aplicación puede acceder a esta url para consultar el estado del usuario, lo que no es demasiado bueno de cara a la privacidad.