Dev Life
Misión a Marte: PyCon 2014
Nos lo pasamos en grande en la PyCon 2013 con nuestra pistola Nerf gigante propulsada por email. Causó furor entre el público, así que para la PyCon 2014 queríamos hacer algo aún más impresionante. Por supuesto, estaba clarísimo que debíamos empezar con… una aspiradora. En este blog te contamos cómo pasamos de una aspiradora a un róver marciano y cómo volvimos a pasarlo genial este año en la PyCon.
Unos comienzos humildes… una misión a Marte
Anton, nuestro ingeniero eléctrico convertido en desarrollador de software, se había comprado un robot aspirador de Neato después de investigar a fondo y comparar Neato con el popular Roomba de iRobot. ¿El factor decisivo? Las aspiradoras Neato tienen una API que permite controlarlas mediante código. Justo lo que necesitábamos para nuestra misión a Marte.
Una de las muchas cosas que nos gustan de trabajar en Rackspace, la empresa que adquirió Mailgun en 2012, es el “hackday” mensual, en el que todo el equipo de ingeniería de la oficina se reúne para trabajar en cualquier cosa que les resulte interesante, esté o no relacionada con un proyecto oficial de Rackspace. Avisamos a un par de colegas de Rackspace y nos pasamos el día trabajando en el código que usaríamos para controlar el robot.
Teníamos claro que queríamos ofrecer la posibilidad de enviar comandos por email al robot como mecanismo de control y que el robot debía poder avanzar, retroceder y girar 360 grados. También queríamos poder “tomar muestras” de la superficie marciana (vamos, encender la aspiradora) y sacar una foto con la cámara montada en lo que se convertiría en la torre de instrumentos principal del róver.
Cómo funciona
Muchos de los detalles de nuestro juego para la PyCon de este año eran distintos, pero habíamos aprendido algo del año anterior:
el acceso a la red podía ser complicado en el recinto de la conferencia. Podía ser que la dirección IP de la Raspberry Pi no fuera accesible públicamente, así que quizá no sería posible enviarle una solicitud POST HTTP.
– Mailgun en la PyCon 2013
Para solucionarlo, usamos Redis para asegurarnos de que el róver pudiera recuperar comandos del servidor siempre que la Raspberry Pi tuviera conexión a Internet. Este es su aspecto conceptual:+ - - - - - + +-----------+ +------------+ +--------------+ | | | | | | | | SMTP | | HTTP | | | Cliente de email +-----> | Mailgun +-----> | Servidor web | | | | | ruta | | | +--------------+ | | | | | | | | +-----+------+ +-----------+ | | | Redis lpush | (local) | | | v | +--------------+ +------------+ | | Redis brpop | | | | | Raspberry Pi | | Cámara Raspberry Pi | | GPIO +-------------------+ +-------------------> | Brick Pi | | puerto serie +-------------------+ +-------------------> | Aspiradora Neato | +-------------------+
Una vez resuelto este problema, nos centramos en los controles principales.
A continuación incluimos ejemplos del código que usamos para controlar el robot de verdad:
Control de la torre de la cámara con BrickPi:
def init(host, password): """Init the required components.""" print "Init BrickPi" BrickPiSetup() BrickPi.MotorEnable[PORT_D] = 1 def camera_control(command, mission_control_address): print "Camera control module received:", command if command in ("up", "down"): if command "up": BrickPi.MotorSpeed[PORT_D] = -100 elif command "down": # despite the fact that the surface gravity of Mars is only # about 38% of Earth's there is still less force required to # bring the camera down BrickPi.MotorSpeed[PORT_D] = 50 BrickPiUpdateValues() sleep(0.5) # stop the motor BrickPi.MotorSpeed[PORT_D] = 0 BrickPiUpdateValues() elif command == "take_picture": camera.capture(file_name) send_picture(file_name, mission_control_address) def send_picture(file_name, mission_control_address) """Send picture back to the Mission Control Center.""" r = requests.post( "https://api.mailgun.net/v2/mailgun.net/messages", auth=("api", "***"), files=[("attachment", open(file_name))], data={"from": "Mars Rover ", "to": mission_control_address, "cc": "nsa@mailgun.net", # oops "subject": "A message from Mars", "text": "The picture of the surface is attached!"})
Control de la aspiradora:
def init(host, password): print "Init Vacuum Base!!!" vac_port = serial.Serial("/dev/ttyACM1") def vac_run_command(command, read_response=True): print "Vacuum base control module received:", command try: vac_port.write(command) if not read_response: # provided command doesn't have a response return return read_response() except: # fault tolerance for the WIN! reconnect()
Aceptación de solicitudes POST de Mailgun:
@app.route('/mission_control', methods=['POST']) def mission_control(): """Commands from Mailgun arrive here.""" command_message = request.form['stripped-text'] from_ = request.form['From'] for command in parse(command_message): robot.run(command, from_) return "10-4"
Vamos a necesitar más Legos
Con el software terminado, nos pusimos a convertir nuestra aspiradora en un róver marciano.
Empezamos buscando el mejor sitio para comprar piezas de Lego de un solo color al por mayor. Necesitábamos un montón de piezas negras, grises y blancas si queríamos crear un róver auténtico. Resulta que eBay es el mejor lugar para comprar Legos, a menudo al peso. 118 $ después, ya podíamos empezar.

Reunimos a un equipo de ingeniería de primera para la misión, en el que se incluía el hijo de cuatro años de alguien del equipo de Mailgun, y preparamos todas las piezas de Lego que formarían el cuerpo del róver. Aquí vemos a Anton, Ralph y Luca durante los preparativos. Después de crear prototipos de algunos de los componentes principales, formalizamos nuestro diseño. El róver tendría una cámara oscilante (propulsada por un motor Lego Mindstorms) montada en la parte superior de una torre de control que integraba Raspberry Pi, BrickPi y una batería de respaldo. Gran parte del cuerpo del róver también estaría cubierta por un panel solar USB funcional.

Unos cuantos contratiempos, un par de risas y unas horas más tarde, ya estábamos a punto de tener un robot montado para hacer una demostración en la presentación del “hackday” que, casualmente, estaba programada para más tarde ese mismo día en la oficina de Rackspace.

Aquí tienes un primer plano de la torre de control principal. Lo que lleva la pegatina de Mailgun es la batería de respaldo. La Raspberry Pi y la BrickPi están montadas encima, y en la parte superior de la foto puedes ver el motor de Lego. La cámara de la Raspberry Pi queda justo fuera del encuadre.

Esta es una vista trasera del róver. Gran parte del cromo decorativo lo añadió el miembro más joven de la misión, incluidas las dos figuras de Lego. Una de ellas es un marinero y la otra, un pirata. Esta resultó ser solo una de las partes de la misión que requeriría mucha creatividad, como verás más adelante.

Terminamos un largo día haciendo una demostración del róver en la oficina. Aquí vemos a Anton revisando el róver terminado.

Querida TSA:
Sabíamos que no podíamos llevar el róver con nosotros en el avión a Montreal. Reconocemos que parece una bomba, y no queríamos tener una larga y amena charla con el personal de la TSA. Así que metimos con cuidado el róver en una maleta grande y lo protegimos con unas 30 agradables y suaves camisetas de American Apparel 50-50 que repartiríamos en la conferencia a la gente que diera una vuelta con él. También incluimos una nota para la TSA en la que les avisábamos de que era un robot construido con una Raspberry Pi. Estábamos seguros de que abrirían la maleta y echarían un vistazo, pero no contábamos con que lo mirarían tan de cerca.
Nuevo y mejorado… pero no por elección propia
Al llegar a nuestro hotel en Montreal y abrir la maleta, lo primero que pensamos fue que debían de haberle dado buenos golpes al equipaje, porque muchas piezas se habían soltado del todo. Sin embargo, al mirarlo más de cerca, quedó claro que la TSA había desmontado el róver prácticamente pieza por pieza. Algunos componentes seguían intactos, pero las estructuras más complejas, como el chasis y la torre de control, se habían desmontado meticulosamente.
Con un café en la mano y a dos horas de la inauguración de la conferencia, volvimos a poner las piezas de Lego sobre una mesa y empezamos a montarlo todo de nuevo. El problema fue que no habíamos traído piezas de Lego de sobra. Como habíamos improvisado el diseño inicial, no teníamos ningún plano, así que cada pieza tendría que volver a ponerse exactamente como estaba si queríamos mantener el diseño original.
Huelga decir que acabamos optando por un diseño un poco diferente en el que, al final, utilizamos en torno a un 30 % menos de piezas de Lego para crear la misma estructura funcional.

Aunque al principio fue frustrante, reconstruir el róver resultó ser de lo más divertido. Acabamos hablando con un montón de entusiastas de Lego durante la mañana, y hubo quienes incluso se animaron a echarnos una mano. A mediodía, nuestro róver marciano estaba a pleno funcionamiento y fue una forma estupenda de conocer a la comunidad de Python. Algunas de las personas más “hackers” que conocimos fueron jóvenes que venían a la PyCon por primera vez. Aquí tienes una toma desde la propia cámara del róver después de que nuestro joven amigo controlara el robot enviando comandos por email desde el teléfono de su padre. ¡Diríamos que la misión fue todo un éxito!

Y esa es la historia de nuestro róver marciano. Pase lo que pase, siempre nos lo pasamos en grande en la PyCon. Estamos deseando que llegue el año que viene para volver a hacerlo.
¡Hasta entonces! Feliz envío.
El equipo de Mailgun.