Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 81

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA

Proyecto fin de carrera para la titulación de

INGENIERÍA TÉCNICA INFORMÁTICA DE SISTEMAS

Interfaz para PC y teleoperación del robot


iRobot Create

Realizado por:
Pablo Navarro Natal

Dirigido por:
Daniel Cagigas Muñiz

Departamento de
Arquitectura y Tecnología de Computadores

Sevilla, Junio de 2.015


2
Agradecimientos

Sois muchos con los que me siento en deuda por el apoyo recibido.

En primer lugar, quiero agradecerles a mis padres su infinito apoyo,


comprensión y cariño. Han sido fundamentales en la realización de éste y
de otros proyectos a lo largo de mi vida.
Gracias de corazón.

Gracias también a quienes de un modo u otro han estado ahí en


determinados momentos, mostrándome su afecto y animándome cuando
más lo he necesitado.
Sois muchos, pero sabéis quienes sois.

Gracias también a mi ex-compañero de proyecto, Javier Rodríguez


Maguillo, con el que comencé esta locura.

Y gracias, muchas gracias a todos los que me habéis prestado vuestra


ayuda en multitud de momentos:
Javier Sivianes, Pablo Flores, José Antonio Castro, Frutos Márquez,
Alfredo Moreno, Luis Manuel Montoro y Alejandro Vicente.
Sois grandes compañeros y mejores amigos.

Y por supuesto, gracias a mi tutor del proyecto, Daniel Cagigas, por su


ayuda y paciencia.

3
4
Índice general

1. Introducción.............................................................................................................7
1.1 Objetivo general.........................................................................................7
2. Descripción de tecnologías......................................................................................9
2.1 Relación del sistema a nivel hardware.......................................................9
2.1.1 Conector Mini-DIN.......................................................................9
2.1.2 Conversor USB/Serie.................................................................10
2.1.3 Comunicación por red................................................................11
2.1.4 Webcam.....................................................................................11
2.1.5 Alimentación del PC Cliente.......................................................11
2.1.6 Alimentación del PC Servidor.....................................................12
2.1.7 iRobot Create.............................................................................12
2.2 Descripción de tecnología a nivel de software..........................................13
2.2.1 Ubuntu........................................................................................13
2.2.2 Python.........................................................................................14
2.2.3 Qt................................................................................................15
2.2.4 OpenCV......................................................................................19
2.2.5 ROS............................................................................................19
2.2.6 Arquitectura Cliente-Servidor......................................................20
2.2.6.1 Programación de sockets.............................................22
2.2.6.2 Protocolo TPC/IP..........................................................24
3. Diseño y arquitectura del sistema...........................................................................26
3.1 Servidor.....................................................................................................30
3.2 Cliente.......................................................................................................31
4. Implementación.......................................................................................................33
4.1 Diagrama UML..........................................................................................33
4.2 Clase Cliente_pfc y Clase KeyboardControlThread..................................34
4.3 Clase Server..............................................................................................46
5. Manuales.................................................................................................................54

5
5.1 Manual de instalación...............................................................................54
5.2 Manual de usuario....................................................................................54
6. Pruebas realizadas.................................................................................................59
6.1 Algoritmo Bump & Go................................................................................59
6.2 Algoritmo KeyboardControl........................................................................60
6.3 Algoritmo de teleoperación a través de interfaz gráfica.............................61
6.4 GUI con teleoperación y visión...................................................................62
6.5 Teleoperación y reconocimiento visual.......................................................63
6.6 Teleoperación manual y mediante reconocimiento visual..........................64
7. Conclusiones y aplicaciones futuras........................................................................67
8. Bibliografía y referencias..........................................................................................68
9. Anexo: iRobot Create...............................................................................................70

6
Capítulo 1
Introducción

El gran auge que la robótica móvil ha tenido desde la década de los 70, ha venido
acompañada por la llegada de tecnologías de planificación y razonamiento
automático, por lo que se ha dado pie a las investigaciones y al diseño de plataformas
móviles instrumentadas, con miras al refinamiento del funcionamiento mecánico y
electrónico, lo que ha permitido aumentar la complejidad de los sistemas, mejorando
las prestaciones de los mismos, posibilitando el planteamiento y búsqueda de nuevas
y más ambiciosas metas.

La versatilidad de los robots móviles, ofrece la oportunidad de navegar en distintos


terrenos y tener aplicaciones de todo tipo, como exploración minera, exploración
planetaria, misiones de búsqueda y rescate de personas, limpieza de desechos
peligrosos, automatización de procesos, vigilancia, reconocimiento de terreno, entre
otras .

En la actualidad, se busca la mejora de los sistemas robóticos por medio del aumento
de la eficiencia de la programación de múltiples tareas y de la compatibilidad e
integración de nuevos equipos, sensores y aplicaciones. Esto, unido con la
elaboración de sistemas autónomos, semi-autónomos y de operatividad remota
desliga la necesidad de contar con un usuario presente en el área de actividad y en
un constante monitoreo.

En este mismo sentido, he querido trabajar en la realización de un proyecto enfocado


al control remoto de una plataforma iRobot Create.

1.1 Objetivo general

El principal objetivo de este proyecto es la realización de una aplicación para

7
teleoperar un robot Create a través de una interfaz. Dicha teleoperación se podrá
llevar a cabo, bien de manera manual mediante los botones de control, o bien
mediante reconocimiento visual.

8
Capítulo 2
Descripción de tecnologías

En este apartado de la memoria describiremos cada una de las principales


herramientas del desarrollo, tanto a nivel hardware como software.

2.1 Relación del sistema a nivel hardware

A continuación, haremos mención de todos y cada uno de los componentes hardware


necesitados para la realización del proyecto.

2.1.1 Conector Mini-DIN

Los conectores Mini-DIN forman parte de una familia de conectores de forma circular.
Tienen un diámetro de 9,5 mm y siete conjuntos de pines interiores, que van desde
los 3 hasta los 9 pines. En dichos conectores existen pequeñas muescas que sirven
de guías en la carcasa. Hay diferentes variedades de conectores Mini-DIN, cuyos
pines y muescas presentan una ordenación determinada que los diferencia. Cada
variedad tiene un conector llave que impide que se puedan conectar cables de
diferentes variaciones.

Familia de conectores Mini-DIN

Estos conectores se usan para multitud de aplicaciones, entre ellas, una de las más

9
extendidas es para conexiones de audio/vídeo. Pero para nuestro caso concreto,
usaremos el conector Mini-DIN para conectar el iRobot Create a nuestro ordenador.
La comunicación que se establece es una comunicación en serie mediante tecnología
TTL (transistor-transistor logic). En dicha tecnología se usan voltajes de entre 0 y 5
voltios.

La siguiente imagen muestra el patillaje del conector hembra para el iRobot Create, y
en la tabla inferior refleja la descripción de los distintos pines:

Arriba: Imagen del patillaje del conector Mini-DIN que usa el iRobot Create.
Abajo: Tabla descriptiva de los distintos pines del conector Mini-DIN.

2.1.2 Conversor USB/Serie

Existen diferentes modelos en cuanto a tipos de adaptadores o conversores de USB-


Serie se refiere. El tipo de interfaz más utilizada es aquel cuyo extremo “Serie” del
adaptador es el RS232. Es este mismo el que se usará para el proyecto. El conector
del RS232 es una interfaz cuyo conector es del tipo DB-9, que consta de 9 pines.

10
Imagen del conversor USB/Serie

2.1.3 Comunicación por red

La comunicación entre terminales puede hacerse de manera inalámbrica mediante


wifi o a través de una conexión cableada ethernet. Para ello requerimos de una tarjeta
de red wifi o ethernet. Las usadas durante el proyecto soportan una velocidad de
hasta 150 Mbps en el caso de la tarjeta wifi, y de 10/100/1000 Mbps en el caso de la
tarjeta ethernet. De todos modos, bastaría con cualquier tarjeta que soportase
velocidades de 10/100 Mbps.

2.1.4 Webcam

El dispositivo que actúe de cliente, necesitará una webcam para el control del robot
mediante la detección del color. En este caso, se ha usado la que venía integrada en
el portátil. Cualquier cámara con unos requisitos mínimos sería válida. Estos
requisitos necesarios serían 32 bits de profundidad, con una resolución de 640x480
píxeles.

2.1.5 Alimentación del PC Cliente

11
Para la realización del proyecto, la alimentación del PC que hace las veces de cliente
es de 19,5 V y 4,7 A.

Cargador del PC Cliente.

2.1.6 Alimentación del PC Servidor

Al igual que en el caso anterior, para la realización del proyecto, se ha usado un PC


concreto, cuya alimentación tiene un voltaje de entre 15 y 24 voltios y una intensidad
de 6 amperios.

2.1.7 iRobot Create

El robot Create, de iRobot, es un robot móvil de un considerable valor pedagógico, en


tanto en cuanto que representa una gran oportunidad, tanto para estudiantes como
para docentes, de desarrollar sus propias aplicaciones sea cual sea su finalidad. Así
pues, pueden desarrollarse aplicaciones relativas al movimiento, a los sonidos o a
determinados comportamientos, e incluso, se puede llegar a integrar electrónica
adicional al robot con la intención de poder realizar comportamiento más complejos.

12
Imagen general del robot iRobot Create

El iRobot Create está basado en la serie de robots Roomba. Este modelo de robot, el
Roomba, es utilizado a nivel doméstico para realizar tareas de limpieza (la mayoría de
los modelos se encargan de aspirar el suelo, pero recientemente han aparecido
también modelos para el fregado) evitando los obstáculos y, en la medida de lo
posible, no dejar ninguna zona sin aspirar. El iRobot Create también puede simular
este comportamiento, sólo que se ha eliminado los componentes de limpieza. Por
tanto, es un robot pensado para realizar aplicaciones y desarrollos de una forma
sencilla que, simplemente, se basa en la plataforma del Roomba.

2.2 Descripción de tecnología a nivel de software

Ahora serán detallados los componentes a nivel de software que se han requerido
para el desarrollo del sistema.

2.2.1 Ubuntu

Ubuntu es un sistema operativo, basado en el núcleo GNU/Linux y que se distribuye


como software libre. Tiene un diseño sencillo, orientado a todo tipo de usuarios, con
un fuerte enfoque en la facilidad de uso y con componentes que tratan de mejorar la
experiencia de aquel que lo utilice. Pensando en esto último, Ubuntu incluye su propio
entorno de escritorio, denominado Unity, que cuenta con una interfaz amigable para

13
todo aquel que haga uso de este sistema.

Su patrocinador es la empresa británica Canonical, quien además se hace cargo de


su mantenimiento y actúa como proveedor. Cabe destacar la extensa comunidad de
desarrolladores que proporcionan soporte para todas las derivaciones de Ubuntu,
entre las que consta distribuciones como Kubuntu o Xubuntu, por destacar algunos
ejemplos.

Logotipo clásico de Ubuntu.

Actualmente, la versión más reciente de Ubuntu es la 15.04, denominada Vivid Vervet.


Sin embargo, para la realización del proyecto se ha usado su versión 12.04, Precise
Pangolin, la cuál ha demostrado sobradamente su solidez, consolidándose como un
sistema robusto y muy estable que, además, aún hoy cuenta con un amplio soporte.

2.2.2 Python

Python es un lenguaje de programación de propósito general, de programación


multiparadigma, lo que permite a los desarrolladores de software adoptar distintos
estilos, ya sea una programación orientada a objetos, una programación funcional o
imperativa.

14
Logotipo de Python.

La filosofía de Python hace hincapié en una sintaxis que favorezca un código legible.

En la actualidad, el uso de este lenguaje es muy extendido y se encuentra en todos


los ámbitos, desde programación de páginas webs a desarrollos de aplicaciones para
investigaciones científicas.

En la realización de este proyecto se ha usado la versión 2.7. A día de hoy, Python se


encuentra en su versión 3.4. Actualmente (mayo de 2015), la mayoría de
distribuciones Linux siguen incluyendo Python 2 como versión predeterminada de
Python, aunque en todas se puede instalar Python 3 y utilizarlo sin problemas, y
aunque llevan tiempo trabajando en la transición, no se sabe cuándo la versión
predeterminada pasará a ser Python 3. Además, la transición entre una versión y otro
suele resultar más costosa de lo esperado. Son por estos motivos que he decidido
mantener la versión inicial.

2.2.3 Qt

Qt es un framework de código abierto multiplataforma de uso frecuente para, sobre


todo, el desarrollo de interfaces gráficas de usuario. A pesar de que su uso más
extendido es el mencionado, también se programan con ella programas sin interfaz
gráfica.

Qt apareció inicialmente como una librería desarrollada por TrollTech, en 1.992,


siguiendo un desarrollo basado en código abierto. En 2.008, Nokia adquirió TrollTech,
y por consiguiente, también adquirió Qt, la cuál utilizó para el desarrollo de

15
aplicaciones de escritorio y para dispositivos móviles.

Qt está programado en C++, y es en este lenguaje el que utiliza de forma nativa. Sin
embargo, Qt puede ser utilizado en otros lenguajes a través de bindings, adaptando
así la biblioteca para su uso con, por ejemplo, Java, a través del binding Qt Jambi;
PHP, con PHP-Qt; o Python, mediante los bindings PythonQt, PySide o PyQt, siendo
este último el usado durante el proyecto.

Evolución del logotipo de Qt a lo largo del tiempo.

El paquete Qt integra herramientas de desarrollo y soporte tales como QtCreator,


QtDesigner y QtAssistant, los cuales pasaremos a explicar brevemente a
continuación, así como librerías de clases auxiliares a Qt.

– Qt Creator: es un IDE, o entorno de desarrollo integrado, para la creación de


aplicaciones en C++ y Qt. Actualmente, QtCreator permite el desarrollo de archivos en
otros lenguajes como Python, no así proyectos, y pueden ser ejecutados; también
cuenta con resaltado de sintaxis, pero carece de características más complejas como
autocompletar.

16
Ejemplo de vista de Qt Creator

– Qt Designer: es una herramienta de desarrollo que nos permite crear


interfaces gráficas de usuario. Nos proporciona un conjunto de componentes estándar
y un mecanismo de conexión llamado signal-slot, en el que se basa Qt. Si bien, este
mecanismo para realizar signal-slot sólo ofrece la posibilidad de elegir aquellos que
vienen por defecto, así que, si quieres integrar en la aplicación signals y slots que no
están ahí definidos, debes programarlos e integrarlos manualmente en el código.

17
Ejemplo de vista de Qt Designer

– Qt Assistant: se trata de un componente de Qt que nos permite navegar por


la documentación, en forma de páginas HTML, e implementa opciones de búsqueda y
de extensión.

Ejemplo de vista de Qt Assistant

18
2.2.4 OpenCV

OpenCV o (Open Computer Vision) es una librería opensource de tratamiento de


imagen y visión artificial, desarrollada originalmente por Intel en 1999. OpenCV es
multiplataforma, soportado por Windows, Linux, Mac OS, iOS y Android, que cuenta
con un software robusto y muy eficiente desarrollado en C y C++. Además, dispone de
interfaces para diversos lenguajes como C ++, C, Python, Java y MATLAB. OpenCV
contiene más de 2.500 algoritmos optimizados de tratamiento de imagen. Los
algoritmos que podemos encontrar cuentan con funciones de reconocimiento facial,
identificación de objetos según su forma o color, monitorización de movimientos de
objetos, extraer modelos 3D de figuras, mediación de ángulos entre dos objetos,
etcétera.

Logo de OpenCV

Por lo explicado con anterioridad, OpenCV satisface de manera sobrada nuestras


necesidades.

La forma de trabajar de OpenCV se basa en la captura y segmentación de imágenes.


En nuestro caso, y como detallaremos más adelante, usaremos OpenCV para
detectar un objeto de un determinado color.

2.2.5 ROS

ROS, a pesar de lo que pudiera sugerir el nombre que definen sus siglas -Robot
Operating System-, no puede considerarse un sistema operativo en sí; de hecho,
ROS se sustenta bajo un sistema operativo de tipo Linux, concretamente Ubuntu,

19
aunque podemos encontrar versiones experimentales para otros sistemas, también de
tipo Linux, como Fedora o Debian para ordenador, Ubuntu ARM y Raspbian para
sistemas embedidos (este último concretamente para Raspberry Pi), o para Android
en el caso de dispositivos móviles. También existe versiones, igualmente
experimentales, para ordenadores con OS X y Windows. En consecuencia, no
debemos considerar a ROS como un sistema operativo, sino como un framework: una
estructura de soporte definido que dispone de una amplia colección de repositorios,
librerías y paquetes software para el desarrollo y ejecución de sistemas para robots
de todo tipo.

Una de las mayores ventajas que ofrece ROS es la gran capacidad de adaptación e
integración con otras tecnologías. ROS ofrece la posibilidad de trabajar en múltiples
lenguajes, facilitando así la tarea del programador, al que ofrece casi total libertad de
desarrollar su aplicación en el lenguaje con el que se sienta más cómodo o que mejor
se desenvuelva.

Logotipo de ROS.

2.2.6 Arquitectura Cliente-Servidor

La arquitectura Cliente-Servidor es un modelo que se usa para establecer una


comunicación entre distintos terminales. Dicho modelo consiste en un sencillo
mecanismo, en el que a través de un proceso, una máquina, el cliente, requiere de los
servicio de otra, el servidor, quien le proporciona la respuesta. Atendiendo a quién
realiza el proceso de la información existen básicamente cuatro tipos distintos de esta
arquitectura:

• Cliente Activo, Servidor Pasivo. El cliente realiza la totalidad del trabajo de


procesado de la información. El servidor sólo va a actuar cada vez que se lo pida el
cliente, y las comunicaciones se iniciarán sólo cuando éste así lo requiera a través de

20
una instrucción. Una vez que el servidor haya proporcionado una respuesta,
simplemente espera a que el cliente presente otra solicitud.

• Cliente Pasivo, Servidor Pasivo. Tanto el cliente como el servidor simplemente


pasan información.

• Cliente Pasivo, Servidor Activo. El servidor realiza todo el trabajo de


procesado y el cliente simplemente presenta los datos.

• Cliente Activo, Servidor Activo. Tanto el servidor como el cliente procesan la


información, es decir, no necesitan recibir previamente una petición para la realización
de un servicio. Además, ambos procesos deben estar abiertos a recibir mensajes
sobre las peticiones que realiza el otro.

La filosofía de este tipo de arquitectura va más allá de los dos terminales, pues
permite tener varios clientes o varios servidores. En la figura siguiente se muestra un
ejemplo gráfico de este tipo de protocolo que consta de un servidor y cinco clientes:

Arquitectura Cliente-Servidor con un único servidor

El proyecto realizado, como se mostrará más adelante, es una arquitectura simple


que cuenta con un único cliente, que será activo, y un sólo servidor, que es de tipo
pasivo.

21
Para programar el funcionamiento de esta arquitectura tenemos que recurrir al uso de
los “sockets”. Los sockets son una interfaz de programación usados para establecer
comunicaciones entre procesos.

Las comunicaciones establecidas con el modelo cliente-servidor pueden ser tanto


síncronas como asíncronas. Esta característica afecta directamente a la programación
de los sockets. La diferencia entre una comunicación síncrona y una comunicación
asíncrona se detalla brevemente a continuación:

• Comunicación síncrona: el elemento que envía el paquete de información


permanece bloqueado esperando a que llegue una respuesta del receptor antes de
realizar cualquier otro ejercicio. Es decir, cuando un cliente realiza un envío a un
servidor éste ya está esperando este tipo de envío y se queda bloqueado hasta que lo
reciba.

• Comunicación asíncrona: se trata de un tipo de comunicación no bloqueante,


en la que el emisor de la información continúa con su ejecución inmediatamente
después de enviar el mensaje al receptor. De este modo, un elemento intenta recibir
información y, si no se ha enviado nada o la información todavía no se ha preparado,
el dispositivo sigue trabajando hasta que tenga esta información para leer.

2.2.6.1 Programación de sockets.

Los sockets proporcionan una comunicación de dos vías, punto a punto entre dos
procesos. Un socket puede considerarse como un punto final de comunicación al cual
se puede asociar un nombre. Existen los siguientes tipos de sockets:

22
Esquema de funcionamiento de los sockets

A continuación se resumen las funciones utilizadas en los sockets. Debe tenerse en


cuenta que este desarrollo no es igual para todos los lenguajes, así pues, puede
diferir, aunque sea de manera mínima, en función del lenguaje empleado.

- socket()

Los sockets se crean con esta función y devuelve el identificador de socket (sockfd), ó
-1 en caso de haberse producido algún error.

- bind()

Esta función sirve para darle un “nombre” al socket, es decir, una dirección IP y un
número de puerto de la máquina local. Esto es así para establecer una correcta

23
comunicación al enviar y recibir los datos.

- listen()

La función listen() se invoca únicamente en el servidor y habilita el socket


configurándolo en modo escucha para poder recibir la información proveniente de las
conexiones. Esta llamada sólo es necesaria cuando se usan sockets del tipo Stream
(SOCK_STREAM).

- accept()

La función accept() también es utilizada sólo en el servidor. Una vez que se ha


invocado la función listen(), ésta función espera a que algún cliente establezca
conexión con el servidor. Es una llamada bloqueante, es decir, la función no finaliza
hasta que se realice alguna conexión o sea interrumpida por alguna señal.

- connect()

Esta función, como puede intuirse, inicia la conexión con el servidor, abriéndose así el
canal de la comunicación entre el cliente, desde el que se ejecuta esta instrucción, y
el servidor.

- send()

Una vez ya está establecida la conexión con el servidor se pueden enviar datos a
través esta función. La puede utilizar tanto el cliente como el servidor.

- recv()

Esta función se utiliza para la recepción de los datos. Esta llamada es bloqueante, por
lo que la función no finaliza hasta que se reciban los datos enviados.

2.2.6.2 Protocolo TCP/IP

Como el protocolo usado en el proyecto va a ser el protocolo TCP/IP, vamos a pasar a

24
describirlo para hacernos una idea de en qué consiste el mismo.

El protocolo TCP (Transmission Control Protocol, protocolo de control de transmisión)


está basado en IP (Internet Protocol) que es un protocolo de comunicación de datos
digitales no fiable y no orientado a conexión, y sin embargo es:

• Orientado a conexión: es necesario establecer una conexión previa entre las


dos máquinas antes de poder transmitir ningún dato. A través de esta conexión los
datos llegarán siempre a la aplicación destino de forma ordenada y sin duplicados.
Finalmente, es necesario cerrar la conexión.

• Fiable: la información que envía el emisor llega de forma correcta al destino,


pues cada vez que llega un mensaje se devuelve una confirmación
(acknowledgement, o ACK) para que el emisor sepa que ha llegado correctamente. Si
no le llega esta confirmación pasado un cierto tiempo, el emisor reenvía el mensaje.

La unidad de datos del protocolo es el byte, de tal forma que la aplicación origen
envía bytes y la aplicación destino recibe estos bytes. Sin embargo, cada byte no se
envía inmediatamente después de ser generado por la aplicación, sino que se espera
a que haya una cierta cantidad de bytes, se agrupan en un segmento y se envía el
segmento completo. El formato del segmento TCP es el siguiente:

Tabla con el formato de segmento TCP

25
Capítulo 3
Diseño y arquitectura del sistema

Pasamos ahora a describir la arquitectura del sistema implantado en el proyecto.

Para la realización del mismo, se ha desarrollado una aplicación con diferentes


objetivos. Por un lado, la teleoperación del robot iRobot Create mediante la detección
visual de un objeto de un color determinado, y por otro, el control del mismo mediante
los botones presentes en la interfaz gráfica del usuario. En esta arquitectura
intervienen un ordenador con webcam, que hará las veces de cliente, un ordenador
que actúa como servidor y que será quien se comunique directamente con el robot, y
el propio robot iRobot Create.

El esquema de conexión del sistema es el siguiente:

Esquema de la arquitectura del sistema

26
Y el diagrama de bloques de la aplicación, es el que se muestra a continuación:

Diagrama de bloques de la aplicación.

En el sistema desarrollado, como ya mencionamos con anterioridad, sólo existe un


servidor y un cliente. Además, esta arquitectura es síncrona a nivel de comunicación.
Esto quiere decir que en todo momento, tanto en la parte del cliente, como en la del

27
servidor, se sabe a priori cual es la información que va a llegar y en qué momento del
tiempo. Para una mayor comprensión, y de una forma esquemática, la funcionalidad
de esta arquitectura del sistema se muestra en el siguiente diagrama:

• Establecimiento de conexión:

1. El servidor está esperando nuevas peticiones y se mantiene en un estado de


apertura pasiva.

2. El cliente realiza la petición de conexión con el servidor. El bit de código del


mensaje que debe estar activado en el envío es el bit SYN. Una vez recibido el
mensaje por el servidor, éste envía una respuesta de confirmación; si desea abrir la
conexión, activa el bit SYN del segmento.

3. La primera máquina recibe el segmento y envía su confirmación, entendiendo


que el otro extremo ya está preparado para la comunicación. El servidor se mantiene
a la espera de recibir la información.

• Envío de información:

4. El cliente envía dicha información y el servidor, una vez procesada, comienza


la ejecución de dicha tarea. Para asegurar que el mensaje ha llegado correctamente,
el servidor envía al cliente la señal de confirmación ACK. Si pasado un tiempo
establecido en un temporizador del cliente, éste no recibe esta señal, el paquete de

28
información será enviado de nuevo al servidor.

• Cierre de la conexión:

5. Cuando el usuario lo estima oportuno, cierra la conexión. Es aquí donde el bit


de código activado es FIN.

Como puede apreciarse, el funcionamiento de las comunicaciones y conexiones es


similar en todas las fases del proceso, independientemente de la tarea a realizar.

29
A continuación, serán detalladas en los siguientes apartados las funcionalidades tanto
del servidor como del cliente de manera independiente:

3.1 Servidor

S1. Inicialización del socket.

S2. Ponemos el nombre y puerto del socket: Dirección IP = ' ', Puerto = 9999.

S3. Se prepara al socket en modo escucha para recibir conexiones.

S4. Llamada bloqueante que sirve para esperar peticiones de conexiones del cliente.

S5. El servidor recibe una cadena que contiene el código del comando que se desea
ejecutar. Para una mayor compresión de dichos códigos, serán agrupados del
siguiente modo:

• Códigos del reconocimiento visual

Valor 0: El robot permanece en el sitio y no se mueve.

Valor 1: El robot realiza un giro hacia atrás y a la izquierda.

Valor 2: El robot realiza un giro hacia atrás y a la derecha.

Valor 3: El robot rota hacia la izquierda.

Valor 4: El robot rota hacia la derecha.

Valor 5: El robot realiza un giro adelante y a la izquierda.

Valor 6: El robot realiza un giro adelante y a la derecha. Códigos en función del


posicionamiento del objeto para el
desplazamiento del robot
Valor 7: El robot se desplaza hacia atrás a mayor velocidad.

30
Valor 8: El robot se desplaza hacia atrás a menor velocidad.

Valor 9: El robot se desplaza adelante a menor velocidad.

Valor 10: El robot se desplaza adelante a mayor velocidad.

• Códigos de los botones de la interfaz

Valor ID_STOP: El robot permanece parado en el sitio.

Valor ID_UP: El robot se desplaza hacia delante a 50 mm/s.

Valor ID_UPP: El robot se desplaza hacia delante a 150 mm/s.

Valor ID_UPPP: El robot se desplaza hacia delante a 250 mm/s.

Valor ID_DOWN: El robot se desplaza hacia atrás a 50 mm/s.

Valor ID_DOWNN: El robot se desplaza hacia atrás a 150 mm/s.

Valor ID_DOWNNN: El robot se desplaza hacia atrás a 250 mm/s.

Valor ID_LEFT: El robot gira sobre sí mismo hacia la izquierda.

Valor ID_RIGHT: El robot gira sobre sí mismo hacia la derecha.

S6. El servidor recibe la cadena “Disconnect”, y el servidor queda desconectado y


cierra el socket.

3.2 Cliente

C1. Creamos el socket para conectar con el servidor.

31
C2. Realiza la petición de conexión al servidor, indicando el host correspondiente (en
nuestro caso, se trata del argumento argv[1], el cual corresponde con la ip del servidor
pedida al usuario) y el puerto.

C3. Envía el comando del código de la tarea que se quiere ejecutar. Estos códigos
fueron explicados en el apartado “S5” del servidor.

C4. Cuando el usuario lo crea conveniente, cerrará la comunicación, y el socket se


cerrará.

32
Capítulo 4
Implementación

Este capítulo está orientado a la comprensión de la aplicación y de su código. Para


ello, se presentará un diagrama UML, y se detallarán los paquetes y módulos
requeridos, además de explicar brevemente las funciones que pudieran suponer una
mayor complejidad de comprensión.

4.1 Diagrama UML

El diagrama UML del sistema es el que sigue:

Diagrama UML de la aplicación.

A continuación se describirán las siguientes clases que apreciamos en el diagrama


UML.

33
Las clases Cliente_pfc y KeyboardControlThread ejecutan dos procesos de manera
concurrente. La primera de ellas es la clase principal y, como su propio nombre indica,
es la que ejerce como cliente durante el proceso de comunicación. Además de
establecer dicha comunicación, se encarga de poner en marcha la interfaz gráfica que
manejará el usuario. La clase Cliente_pfc también lleva a cabo el reconocimiento
visual para la teleoperación del robot mediante esta técnica.

Por su parte, la clase KeyboardControlThread ejecuta el control del iRobot Create


mediante los botones de la interfaz gráfica.

La clase Server, es el servidor. Recibe la información del cliente y la procesa. Esta


clase, a través del servicio Tank, se comunica con el driver y ejecuta el movimiento del
robot.

Como aclaración decir que las clases Socket a las que están relacionadas tanto
Server como Cliente_pfc es la misma. El hecho de haberlo puesto de este modo, es
para que se pueda comprobar qué métodos ejecuta una clase y otra.

A continuación, se mostrarán los códigos de las clases, con comentarios que


describen lo que se está haciendo en todo momento.

4.2 Clase Cliente_pfc y Clase KeyboardControlThread

Las clases Cliente_pfc y KeyboardControlThread ejecutan sus procesos de forma


paralela; por un lado tenemos una clase principal, que ejerce como tal, Cliente_pfc, y
por el otro, tenemos la clase KeyboardControlThread, que lanzará su propio hilo. La
creación de este nuevo hilo no producirá un bloqueo en el proceso de la primera de
las clases.

A continuación, se mostrará el código y se explicará su funcionamiento.

34
"""

Filename: clientepfc.py

Description: Contiene la clase principal Cliente_pfc y KeyboardControlThread.


La clase Cliente_pfc pone en funcionamiento la GUI y lleva a cabo el procesamiento
del control del iRobot Create mediante reconocimiento visual utilizando los
algoritmos de visión artificial de OpenCV. Es también la encargada de enviar la
información a la máquina servidor, que controla el robot.
La clase KeyboardControlThread es el hilo que se encarga del control del robot
mediante los botones de la interfaz gráfica.

"""

#!/usr/bin/env python
import sys
import signal # Módulo que proporciona mecanismos de gestión de eventos
# asíncronos del sistema.

# Cargamos los módulos de Qt necesarios para el programa.


from PyQt4 import uic, QtGui, QtCore

# Cargamos el módulo de OpenCV.


import cv2
import numpy as np # Librería de computación científica. Utilizada para el
# procesamiento de arrays.

# Cargamos otras librerías


import Queue
import threading
import time
import socket
from time import sleep
from threading import Thread

# Constantes
35
ID_STOP = "01"
ID_UP = "02"
ID_UPP = "002"
ID_UPPP = "0002"
ID_DOWN = "03"
ID_DOWNN = "003"
ID_DOWNNN = "0003"
ID_LEFT = "04"
ID_RIGHT = "05"

# Variables globales
q = Queue.Queue()
move = "0"
prioridadBotones = False
connection = False

#Preguntamos por los argumentos de entrada para arrancar la aplicación


arglen=len(sys.argv)
if arglen<2:
print('please run as python clientepfc.py <ip_address>')
exit()

# Creamos el socket, establecemos el puerto correspondiente y lanzamos la


# conexión
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
port = 9999 # Seleccionamos el puerto 9999 como puerto genérico
clientSocket.connect((sys.argv[1], port))

#--------------------------------------------------------------
# Clase Cliente_pfc
#--------------------------------------------------------------
class Cliente_pfc:

def __init__(self):
# Cargamos la GUI desde el archivo UI.
self.MainWindow = uic.loadUi('gui.ui')
36
# Tomamos el dispositivo de captura a partir de la webcam.
self.webcam = cv2.VideoCapture(0)

# Creamos un temporizador. Una vez cumplido el tiempo límite, se toma una


# captura desde la webcam.
self.timer = QtCore.QTimer(self.MainWindow);

# Conectamos la señal timeout() que emite nuestro temporizador con la función


activity_frame().
self.MainWindow.connect(self.timer, QtCore.SIGNAL('timeout()'),
self.activity_frame)

# Tomamos una captura cada 1 milisegundo.


self.timer.start(1);

# Definimos los botones de la GUI


self.connectKc = self.MainWindow.connectButton
self.disconnectKc = self.MainWindow.disconnectButton
self.exitKc = self.MainWindow.exitButton

self.stopKC = self.MainWindow.stopButtonKC
self.upKC = self.MainWindow.upButton
self.downKC = self.MainWindow.downButton
self.leftKC = self.MainWindow.leftButton
self.rightKC = self.MainWindow.rightButton

self.disconnectKc.setEnabled(False)
self.stopKC.setEnabled(False)
self.upKC.setEnabled(False)
self.downKC.setEnabled(False)
self.leftKC.setEnabled(False)
self.rightKC.setEnabled(False)

# Connect: realizamos la conexión de los signals y los slots


37 self.connectKc.clicked.connect(self.establishConnection)
self.disconnectKc.clicked.connect(self.disconnection)
self. exitKc.clicked.connect(self.exitApplication)

self.stopKC.clicked.connect(self.pushStopKC)
self.upKC.clicked.connect(self.pushUpKC)
self.downKC.clicked.connect(self.pushDownKC)
self.leftKC.clicked.connect(self.pushLeftKC)
self.rightKC.clicked.connect(self.pushRightKC)

def activity_frame(self):
"""

Es la función principal del reconocimiento visual.


Toma la captura desde la webcam, la incorpora al label de la GUI,
hace el reconocimiento del color y se le indica la posición del
objeto reconocido para después enviar esa información al servidor.

"""

global prioridadBotones
global move
self.q = q

# Tomamos una captura desde la webcam y la convertimos de BGR -> HSV.


_,ipl_image = self.webcam.read()
hsv = cv2.cvtColor(ipl_image, cv2.COLOR_BGR2HSV)

# Establecemos el rango de colores que vamos a detectar


# En este caso de verde oscuro a verde-azulado o claro
verde_bajos = np.array([49,50,50], dtype=np.uint8)
verde_altos = np.array([80, 255, 255], dtype=np.uint8)

# Crear una mascara con solo los píxeles dentro del rango de verdes
mask = cv2.inRange(hsv, verde_bajos, verde_altos)
38
# Encontrar el area de los objetos que detecta la cámara
moments = cv2.moments(mask)
area = moments['m00']

# Ver el área por pantalla


#print area

if(connection == True and area > 2000000):

# Buscamos el centro x, y del objeto


x = int(moments['m10']/moments['m00'])
y = int(moments['m01']/moments['m00'])

# Mostramos sus coordenadas por pantalla


print "x = ", x
print "y = ", y

# Dibujamos una marca en el centro del objeto


cv2.rectangle(ipl_image, (x, y), (x+2, y+2),(0,255,0), 2)

# Posicionamiento del objeto y movimientos que realizara


# Se mantiene en el sitio
if (y>150 and y<300):
if (x>400): #Rota Derecha
move = "4"
print "Rota Derecha"

elif (x<200): #Rota Izquierda


move = "3"
print "Rota Izquierda"

else: #Parado
move = "0"
print "Parado"
39
#Atrás
elif (y>300):
if (x>400): #Atrás-Derecha
move = "2"
print "XCoordenadaMaximaX", x
print "Atras-Derecha"

elif (x<200): #Atrás-Izquierda


move ="1"
print "XCoordenadaMinimaX", x
print "Atras-Izquierda"

else: #Atrás
move = "8"
print "Atras"

if (y > 375): #Atrás (a mayor velocidad)


move = "7"
print "Atras"
print "CoordenadaMaximaY"

#Adelante
elif (y<150):
if (x>400): #Adelante-Derecha
move = "6"
print "Adelante-Derecha"

elif (x<200): #Adelante-Izquierda


move = "5"
print "Adelante-Izquierda"

else: #Adelante
move = "9"
print "Adelante"
40
if (y < 75): #Adelante (a mayor velocidad)
move = "10"
print "Adelante"
print "CoordenadaMinimaY", y

# Si no se observa objeto verde


else:
if (prioridadBotones):
pass # No se realiza ninguna acción
#print "prioridad a los botones"
else:
move = "0" # Permanece parado
#print "Parado"
if (connection == True):
clientSocket.send(move)

# Creamos una imagen a partir de los datos.


#
# QImage
#(
# Los píxeles que conforman la imagen,
# Ancho de de la imagen,
# Alto de de la imagen,
# Número de bytes que conforman una linea (numero_de_bytes_por_pixels *
ancho),
# Formato de la imagen
#)
image = QtGui.QImage(ipl_image.data, ipl_image.shape[1], ipl_image.shape[0],
QtGui.QImage.Format_RGB888)

# Creamos un pixmap a partir de la imagen.


# OpenCV entraga los pixeles de la imagen en formato BGR en lugar del
# tradicional RGB,
41 # por lo tanto tenemos que usar el método rgbSwapped() para que nos
# entregue una imagen con los bytes Rojo y Azul intercambiados, y así poder

# mostrar la imagen de forma correcta.


pixmap = QtGui.QPixmap()
pixmap.convertFromImage(image.rgbSwapped())
# Mostramos el pixmap en la QLable.
self.MainWindow.lblWebcam.setPixmap(pixmap)

#KeyboardControl Slots:
# Funciones para el movimiento del robot a través de los botones de la GUI.
# Una vez que se pulsa un botón, se guarda del valor en la cola
def pushUpKC(self):
# Pulsado el botón UP
q.put(ID_UP)
print "boton up pulsado"

def pushDownKC(self):
# Pulsado el botón DOWN
q.put(ID_DOWN)
print "boton down pulsado"

def pushLeftKC(self):
# Pulsado el botón LEFT
q.put(ID_LEFT)
print "boton left pulsado"

def pushRightKC(self):
# Pulsado el botón RIGHT
q.put(ID_RIGHT)
print "boton right pulsado"

def pushStopKC(self):
# Pulsado el botón STOP
q.put(ID_STOP)
print "boton stop pulsado"
42
def establishConnection(self):
# Pulsado el botón CONNECT
global connection
if (connection == False):
print "Establishing Connection..."
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSocket.connect((sys.argv[1], 9999))
print "Connected"
self.connectKc.setEnabled(False)
self.disconnectKc.setEnabled(True)
self.exitKc.setEnabled(False)
self.stopKC.setEnabled(True)
self.upKC.setEnabled(True)
self.downKC.setEnabled(True)
self.leftKC.setEnabled(True)
self.rightKC.setEnabled(True)
connection = True

def disconnection(self):
# Pulsado el botón DISCONNECT
global connection
if (connection == True):
print "Disconnected"
clientSocket.send("Disconnect")
clientSocket.close()
self.connectKc.setEnabled(False)
self.disconnectKc.setEnabled(False)
self.exitKc.setEnabled(True)
self.stopKC.setEnabled(False)
self.upKC.setEnabled(False)
self.downKC.setEnabled(False)
self.leftKC.setEnabled(False)
self.rightKC.setEnabled(False)
connection = False
43
def exitApplication(self):
# Pulsado el botón EXIT
self.MainWindow.close()

#--------------------------------------------------------------
# Clase KeyboardControl
#--------------------------------------------------------------
class KeyboardControlThread(threading.Thread):

def __init__(self, q):


threading.Thread.__init__(self)
self.q = q

def run(self):
"""

Esta función establece los parámetros del movimiento


del robot a través de los botones. Estos valores son
leídos de la cola, donde fueron almacenados mediante
los slots de la clase principal.

"""

global f
global prioridadBotones
global move
while True:
if not q.empty():
obj = q.get(False)
prioridadBotones=True

if ID_UP==obj: # Se lee un valor ID_UP


if (move != ID_UP and move!=ID_UPP and move != ID_UPPP):
44
# Comprobamos que es la primera vez de forma consecutiva que se
# ha pulsado UP.
print "adelante: velocidad uno"
move= ID_UP
elif (move==ID_UP):
# Comprobamos que es la segunda vez consecutiva que se ha
# pulsado UP.
print "adelante: velocidad dos"
move = ID_UPP
elif (move == ID_UPP):
# Comprobamos que se ha pulsado UP por tercera o mas veces
# consecutivas.
print "adelante: velocidad tres"
move = ID_UPPP

elif ID_DOWN==obj: # Se lee un valor ID_DOWN


if (move != ID_DOWN and move!=ID_DOWNN and move !=
ID_DOWNNN):
# Comprobamos que es la primera vez de forma consecutiva que se
# ha pulsado DOWN.
print "atras: velocidad uno"
move= ID_DOWN
elif (move==ID_DOWN):
# Comprobamos que es la segunda vez consecutiva que se ha
# pulsado DOWN
print "atras: velocidad dos"
move = ID_DOWNN
elif (move == ID_DOWNN):
# Comprobamos que se ha pulsado DOWN por tercera o mas veces
# consecutivas.
print "atras: velocidad tres"
move = ID_DOWNNN

elif ID_LEFT==obj: # Se lee un valor ID_LEFT


move=ID_LEFT

45
elif ID_RIGHT==obj: # Se lee un valor ID_RIGHT
move=ID_RIGHT

elif ID_STOP==obj: # Se lee un valor ID_STOP


prioridadBotones=False
move=ID_STOP

else:
time.sleep(0.1)

#--------------------------------------------------------------
# Main
#--------------------------------------------------------------
if __name__ == "__main__":

t = KeyboardControlThread(q)
t.start()

app = QtGui.QApplication(sys.argv)
cliente_pfc = Cliente_pfc()
cliente_pfc.MainWindow.show()

signal.signal(signal.SIGINT, signal.SIG_DFL)

app.exec_()

4.3 Clase Server

Ahora pasaremos a ver y comentar el código de la clase Server.

46
"""

Filename: sesrverpfc.py

Description: Contiene la clase Server y, como su propio nombre indica,


es la parte servidor de la aplicación. Recibe las ordenes del cliente
y, en función de las mismas, las procesa y hace que el robot ejecute
los movimientos gracias al servicio tank del driver irobot_create_2_1.

"""

#!/usr/bin/env python

import sys
import signal # Módulo que proporciona mecanismos de gestión de eventos
# asíncronos del sistema.

#Cargamos módulos de ROS


import roslib; roslib.load_manifest('irobot_create_2_1')
import rospy

#Cargamos módulos de iRobot


from irobot_create_2_1.msg import SensorPacket
from irobot_create_2_1.srv import *

#Cargamos otras librerías


from std_msgs.msg import Empty
import Queue
import time
import socket
from time import sleep

# Constantes
ID_STOP = "01"
ID_UP = "02"

47
ID_UPP = "002"
ID_UPPP = "0002"
ID_DOWN = "03"
ID_DOWNN = "003"
ID_DOWNNN = "0003"
ID_LEFT = "04"
ID_RIGHT = "05"

# Variables globales
q = Queue.Queue()
f = None

rospy.wait_for_service('tank') # Instrucción de bloqueo; espera que el servicio 'tank'


# esté disponible.
f = rospy.ServiceProxy('tank',Tank) #Inicializa el servicio 'tank' del driver.

#--------------------------------------------------------------
# Clase Server
#--------------------------------------------------------------
class Server:

def connect():
"""

Esta función abre la conexión al cliente. La información que este


le envíe, es tratada a través de una petición por el servicio
'tank', que lo ejecuta.

"""

#Creamos el socket y establecemos el puerto correspondiente.


serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
port = 9999
print "server active"

48
# Invoco al método bind, pasando como parametro una tupla con IP
# y puerto
serverSocket.bind((' ', port))

# Invoco el método listen para escuchar conexiones con el numero


# máximo de conexiones como parámetro; en este caso, 1.
serverSocket.listen(1)

# El método accept bloquea la ejecución a la espera de conexiones


# accept devuelve un objeto socket y una tupla IP y puerto
clientSocket, addr = serverSocket.accept()

# Inicialización de variables
leftSpeed = 0
rightSpeed = 0
changeSpeed = 50

while True:
# Instrucción bloqueante. Se recibe un stream en el socket con
# un máximo de 1024 bytes.
receivedData = clientSocket.recv(1024)

# Tratamiento del dato recibido

if (receivedData == "Disconnect"): # Desconexion


print "Disconnecting"
# Cierra los sockets que se han creado y finaliza el proceso.
serverSocket.close
clientSocket.close
break

elif (receivedData=="0"): #Parado


leftSpeed = 0
49 rightSpeed = 0
f(False, leftSpeed, rightSpeed) # Ejecución del servicio 'tank'.
# Esta opecarión se repetirá en
# todos los posibles casos de
# recepción del dato.
#print "Parado", self.leftSpeed, self.rightSpeed

elif (receivedData=="1"): #Atrás-Izquierda


leftSpeed = -50
rightSpeed = -125
f(False, leftSpeed, rightSpeed)
print "Atras-Izquierda", leftSpeed, rightSpeed

elif (receivedData=="2"): #Atrás-Derecha


leftSpeed = -125
rightSpeed = -50
f(False, leftSpeed, rightSpeed)
print "Atras-Derecha", leftSpeed, rightSpeed

elif (receivedData=="3"): #Rota Izquierda


leftSpeed = -100
rightSpeed = 100
f(False, leftSpeed, rightSpeed)
print "Rota Izquierda", leftSpeed, rightSpeed

elif (receivedData=="4"): #Rota Derecha


leftSpeed = 100
rightSpeed = -100
f(False, leftSpeed, rightSpeed)
print "Rota Derecha", leftSpeed, rightSpeed

elif (receivedData=="5"): #Adelante-Izquierda


leftSpeed = 50
rightSpeed = 125
f(False, leftSpeed, rightSpeed)
50 print "Adelante-Izquierda", leftSpeed, rightSpeed
elif (receivedData=="6"): #Adelante-Derecha
leftSpeed = 125
rightSpeed = 50
f(False, leftSpeed, rightSpeed)
print "Adelante-Derecha", leftSpeed, rightSpeed

elif (receivedData=="7"): #Atrás (a mayor velocidad)


leftSpeed = -125
rightSpeed = -125
f(False, leftSpeed, rightSpeed)
print "Atras", leftSpeed, rightSpeed

elif (receivedData=="8"): #Atrás


leftSpeed = -50
rightSpeed = -50
f(False, leftSpeed, rightSpeed)
print "Atras", leftSpeed, rightSpeed

elif (receivedData=="9"): #Adelante


leftSpeed = 50
rightSpeed = 50
f(False, leftSpeed, rightSpeed)
print "Adelante", leftSpeed, rightSpeed

elif (receivedData=="10"): #Adelante (a mayor velocidad)


leftSpeed = 125
rightSpeed = 125
f(False, leftSpeed, rightSpeed)
print "Adelante", leftSpeed, rightSpeed

elif (receivedData==ID_STOP):
try:
leftSpeed=0
rightSpeed=0
51 f(False, 0, 0)
except:
f(False,0,0)

elif (receivedData==ID_UP):
print "Arriba", receivedData
f(False, 50, 50)
leftSpeed = 50
rightSpeed = 50

elif (receivedData==ID_UPP):
leftSpeed = 3*changeSpeed
rightSpeed = 3*changeSpeed
f(False, leftSpeed, rightSpeed)

elif (receivedData==ID_UPPP):
leftSpeed = 5*changeSpeed
rightSpeed = 5*changeSpeed
f(False, leftSpeed, rightSpeed)

elif (receivedData==ID_DOWN):
print "Abajo", receivedData
f(False, -50, -50)
leftSpeed = -50
rightSpeed = -50

elif (receivedData==ID_DOWNN):
print "Aabajo", receivedData
leftSpeed = -3*changeSpeed
rightSpeed = -3*changeSpeed
f(False, leftSpeed, rightSpeed)

elif (receivedData==ID_DOWNNN):
print "Aaabajo", receivedData
leftSpeed = -5*changeSpeed
52 rightSpeed = -5*changeSpeed
f(False, leftSpeed, rightSpeed)

elif (receivedData==ID_LEFT):
print "Izquiera", receivedData
try:
if leftSpeed < 500 and rightSpeed <500:
leftSpeed += 2*changeSpeed
rightSpeed += 2*changeSpeed
f(False, -100, 100)
except:
f(False,0,0)

elif (receivedData==ID_RIGHT):
print "Derecha", receivedData
try:
if leftSpeed > -500 and rightSpeed >-500:
leftSpeed -= 2*changeSpeed
rightSpeed -= 2*changeSpeed
f(False, 100, -100)
except:
f(False,0,0)

# Si no se observa objeto verde o no se recibe nada.


# Esto no implica que esté desconectado.
else:
leftSpeed = 0
rightSpeed = 0
f(False, leftSpeed, rightSpeed)

connect()

53
Capítulo 5
Manuales

Este capítulo comprenderá el manual de instalación y el manual de usuario. En ellos


describiremos los pasos a seguir para hacer un correcto uso de la aplicación.

5.1 Manual de instalación

A continuación se detallarán los pasos a seguir para instalar la aplicación. Esta


aplicación está orientada a Ubuntu (ha sido probada en su versión 12.04).

En la máquina que haga de cliente, crear un directorio e instalar en el mismo


clientepfc, gui.py y gui.ui. En la máquina que vaya a ser servidor, que irá conectada al
iRobot Create, descargar y guardar en un directorio el archivo serverpfc.py

Tanto al archivo clientepfc.py como al serverpfc.py, hacer el siguiente proceso en sus


respectivos equipos:

cd directorio_aplicación
chmod +x filename (siendo 'filename' clientepfc.py y serverpfc.py)

Y ahora sí, ya se tienen los ejecutables de ambos archivos con los cuales se puede
arrancar directamente desde consola.

5.2 Manual de usuario

Ahora se detallará, paso a paso, las instrucciones para usar la aplicación.

1) En la máquina que tenga conectado el iRobot Create, se deberán abrir tres


terminales. En el primero de ellos, ejecutar roscore, que lanza los sistemas de control

54
de ROS.

2) En el segundo de los terminales se arrancará el driver con la instrucción:


rosrun irobot_create_2_1 driver.py

3) El tercer terminal se reserva para ejecutar nuestro archivo servidor. Una


vez que, desde el terminal, te encuentres en el directorio que lo contenga, arrancar
con la línea de comandos:
./serverpfc.py

4) En la máquina que actúe como cliente, y, como en el paso anterior, una


vez dentro del directorio en el que se encuentre el archivo, ejecutar la siguiente línea
de comando:
./clientepfc.py 192.168.1.129

La instrucción consta de dos parte; la segunda de ellas es una IP. El usuario ha de


poner la IP correspondiente con la IP del servidor.

5) Y ya tendremos lanzada nuestra aplicación.

Una vez que tenemos la ventana de nuestra aplicación en nuestra pantalla, nos
fijaremos en el siguiente detalle. El único botón que aparece como activo, es el botón
de CONNECT y EXIT. Además, la webcam sólo visualiza, sin que reconozca ningún
color. La aplicación estará así hasta que se pulse el botón CONNECT.

55
Detalle (I) del cuadro de mandos de la aplicación.

Con el botón CONNECT pulsado, los botones de control se desbloquean, pudiendo ya


operar con los mismos, así como en la pantalla de la aplicación ya se detecta los
objetos de color verde para poder dirigir también el robot de este modo. De esta
forma, el botón EXIT también aparece inactivo.

56
Detalle (II) del cuadro de mandos de la aplicación.

Cuando ya no se desee más continuar con la aplicación, se pulsa el botón


DISCONNECT, quedando activo de este modo el botón EXIT, a través del cuál
cerraremos la ventana de la aplicación.

57
Detalle (III) del cuadro de mandos de la aplicación.

58
Capítulo 6
Pruebas Realizadas

Hasta llegar a alcanzar la versión última de este proyecto, se han llevado a cabo
numerosas pruebas con distintos algoritmos e implementaciones. A lo largo de este
capítulo se harán mención de algunas de ellas, y se explicarán sus distintas
funcionalidad.

6.1 Algoritmo Bump & Go

Uno de los primero algoritmos con los que se realizaron pruebas con el iRobot Create
fue éste: Bump & Go. Este algoritmo lo que hace es, una vez lanzada su ejecución,
poner en marcha el robot, y éste va sorteando los obstáculos a ciegas, es decir, se
desplaza hasta que choca con un objeto, y lo esquiva. Esta funcionalidad la lleva a
cabo el robot retrocediendo y girando sobre sí mismo, y avanzando nuevamente hasta
que encuentre otro obstáculo en su camino. Cada uno de estas acciones individuales
requieren del lanzamiento de tres servicios por parte del driver, como son: “brake”,
que detiene el robot cuando éste choca; “tank”, que se encarga del desplazamiento
tanto cuando avanza, como cuando retrocede al impactar con el obstáculo; “turn”, que
hace que el robot gire para esquivar.

A continuación, se muestra el fragmento de código, - concretamente parte de un


método llamado run() -, en el que se ejecuta la acción anteriormente mencionada:

def run(self):
try:
while(self.go):
if (self.bumperRef[0]):
self.brake(1)
self.tank(1, -1*self.speed,-1*self.speed)

59
while(self.go and self.distanceRef[0] > -100):
print "backing up, distance %s"%self.distanceRef[0]
sleep(0.02)
self.brake(1)
self.turn(1,50)
while(self.go and self.angleRef[0] > -18):
print "turning, angle %s"%self.angleRef[0]
sleep(0.03)
self.brake(1)

La ejecución de este programa se realizó en distintos entornos, con más y con menos
obstáculos y en todos los casos fue exitoso.

6.2 Algoritmo Keyboard Control

El algoritmo, como indica su nombre, permite teleoperar el robot desde el teclado del
ordenador al que esté conectado. Es a través de las pulsaciones de las teclas de
desplazamiento del teclado como se dirige el robot, mientras que para detenerlo basta
con pulsar la tecla 'espacio'.

Es en este algoritmo en el que me basé para después realizar mi aplicación final.

El núcleo de este programa es el siguiente:

try:
while True:
c=cv.WaitKey(50)
if c != -1:
print c

if c == 65362: #up arrow


if leftSpeed < 500 and rightSpeed <500:
print "Forward/ Speed up"
leftSpeed += 2*changeSpeed
rightSpeed += 2*changeSpeed

60
elif c == 65364: #down arrow
if leftSpeed > -500 and rightSpeed > -500:
print 'Back/ Slow down'
leftSpeed -= 2*changeSpeed
rightSpeed -= 2*changeSpeed

elif c == 65361: #left arrow


if rightSpeed - leftSpeed < 300:
print "Start turning left"
leftSpeed -= changeSpeed
rightSpeed += changeSpeed

elif c == 65363: #right arrow


if leftSpeed - rightSpeed < 300:
print "Start turning right"
leftSpeed += changeSpeed
rightSpeed -= changeSpeed

elif c == 32: #space


print "Stop"
leftSpeed = 0
rightSpeed = 0

6.3 Algoritmo de teleoperación a través de interfaz gráfica

Tomando como referencia el algoritmo anterior, desarrollé una sencilla interfaz gráfica
para el usuario, para poder manipular el robot desde ella de forma remota. Esta
primera interfaz, que fue desarrollada con el framework Qt, tan sólo disponía de los
botones para moverse en las distintas direcciones y para detenerse, sustituyendo así
el teclado por una interfaz virtual.

La interfaz se mostraba del siguiente modo:

61
Tanto esta aplicación, como la anterior sin interfaz gráfica, respondían perfectamente
a los requerimientos, en este caso, un manejo teledirigido del robot. Ambas
aplicaciones fueron probados con distintas versiones de ROS, Fuerte y Groovy, no
habiendo problema en ningún caso.

6.4 GUI con teleoperación y visión

El siguiente paso fue incluir algoritmos de visualización.

La finalidad de incorporar visión a la aplicación era para que, una vez desarrollado el
algoritmo con la arquitectura cliente-servidor, el usuario, de forma remota, pudiera ver
el camino que debía seguir para manejar el robot. Para ello, en la interfaz gráfica
anterior le añadí un “label” que haría las veces de pantalla. De este modo, el usuario
dispondría de un entorno útil y amigable de teleoperación.

Fue durante el proceso de creación de este algoritmo con el que comencé a


familiarizarme con la tecnología OpenCV, así como con la integración de ésta en el
entorno diseñado con Qt. Dicha integración no fue sencilla en un principio, pues
OpenCV utiliza un modelo BGR, en lugar del clásico RGB, lo que implica hacer varios

62
cambios de formato a lo largo del código.

6.5 Teleoperación y reconocimiento visual

La siguiente implementación que se llevó a cabo tuvo como novedad el


reconocimiento visual. En este caso concreto, el reconocimiento sería a través del
color de un objeto.

El objetivo con el que planteé este algoritmo era que el usuario que manejara el
iRobot Create, pudiera identificar un objeto determinado mediante su color.

Como vemos en la imagen superior, anterior a la integración del algoritmo de


reconocimiento visual en la interfaz del usuario, el color reconocido es el verde, como
claramente se aprecia en la pantalla de la máscara. En la pantalla con la imagen real
identifica el color con un pequeño punto rojo.

El código de reconocimiento es el que sigue:

63
#Capturamos una imagen y la convertimos de RGB -> HSV
_, imagen = captura.read()
hsv = cv2.cvtColor(imagen, cv2.COLOR_BGR2HSV)

#Indicamos el rango de colores que queremos detectar


#El rango para este algoritmo va desde el verde oscuro
#a verde claro
verde_bajos = np.array([49,50,50], dtype=np.uint8)
verde_altos = np.array([80, 255, 255], dtype=np.uint8)

#Crear una mascara con solo los pixeles dentro del rango de verdes
mask = cv2.inRange(hsv, verde_bajos, verde_altos)

#Encontrar el area de los objetos que detecta la camara


moments = cv2.moments(mask)
area = moments['m00']

6.6 Teleoperación manual y mediante reconocimiento visual

El implementación final de la aplicación, consistió en dar la opción al usuario de la


interfaz de elegir el modo con el que quería controlar el robot. Para ello, al
reconocimiento visual se le dio una utilidad más allá del mero hecho de identificar un
objeto por su color. Así pues, a la posibilidad de teleoperar el robot de forma manual
con los botones de los que dispone la propia interfaz gráfica, se le sumó el hecho de
poderlo manejar sólo con poner un objeto del color preestablecido delante de la
webcam y desplazarlo dentro del ángulo de visión de la misma. De este modo, el
robot se moverá hacia donde se le indique moviendo el objeto.

64
En un primer momento, esta implementación se llevó a cabo de forma simple, es
decir, aplicado al propio ordenador que iba conectado al iRobot Create, cuya interfaz
del usuario es la que se muestra a continuación.

El siguiente paso, era agregarle una arquitectura cliente-servidor al sistema para


poder realizar la teleoperación convenientemente. Para ello, tuve que dividir las
distintas funcionalidades y adecuarlas según fuera cliente o servidor.

Además, el diseño de la interfaz cambió ligeramente, y se le añadieron los botones de


conectar y desconectar, además de un botón de salir. El resultado es el siguiente:

65
La aplicación funciona de manera bastante eficiente. Sin embargo, en función de la
iluminación del lugar y del entorno en el que te encuentres, la webcam puede detectar
puntos de luz de una gama de color contemplada en el rango establecido, por lo que
pudiera ser que el robot hiciera pequeños movimientos como consecuencia de ello,
siendo esto un inconveniente a tratar en el futuro.

Las demás funcionalidades de la aplicación funcionan correctamente, tanto la


teleoperación mediante los botones, probada, como ya se ha mencionado en
anteriores aparatados, en aplicaciones anteriores, como la conexión y desconexión
del sistema al servidor.

66
Capítulo 7
Conclusiones y aplicaciones futuras

Este proyecto no ha estado carente de problemas. En un primer momento, la idea


inicial era controlar el robot mediante con un sistema embedido, concretamente con
una placa BeagleBoard, pero en aquel momento el software no era aún estable en
esas arquitecturas, por lo que finalmente se optó por utilizar un PC.

El tratamiento de los hilos con Python a la hora de integrarlos con Qt, también fue otro
de los puntos con los que me costó más lidiar, pues para llevar a cabo las acciones en
la interfaz del usuario, Qt utiliza las funciones signals y slots, los cuales, en ocasiones,
es difícil implementarlos haciendo llamadas a funciones de distintos hilos.

Como aplicaciones futuras, el ordenador que hace las veces del servidor que controla
el robot Create podría ser sustituido por un sistema embedido o por una de las nuevas
placas de desarrollo que están apareciendo últimamente en el mercado. Dos de los
futuribles casos podrían ser la Raspberry Pi o la placa Intel Galileo. Por un lado,
Raspberry Pi es una arquitectura muy reconocida que, además, recientemente ha
sacado al mercado sus dos nuevos modelos. También cuenta con el respaldo de una
amplia comunidad de desarrolladores. Por su parte, la Intel Galileo puede
considerarse como un punto de inflexión dentro de las placas de desarrollo pues
cuenta con la tecnología de Intel y el prestigio de la marca. Ambos sistemas tienen
como características comunes un bajo consumo, gran conectividad y una
programación sencilla, además de un precio económico y accesible.

A nivel de software, podría ampliarse la aplicación añadiéndole una funcionalidad que


compruebe el estado de la batería del robot, o incluso, el uso de algunos sensores
que avisasen de la presencia de algún obstáculo.

67
Capítulo 8
Bibliografía y referencias
Bibliografía

Keir Davis, John W. Turner y Nathan Yocom. The Definitive Guide to Linux Network
Programming.
Ed. Apress.

Tod E. Kurt. Hacking Roomba.


Ed. Wiley Publishing , Inc.

Referencias

Tutoriales ROS:
http://www.ros.org/wiki/ROS/Tutorials

Tutorial ROS driver irobot_create_2_1:


http://wiki.ros.org/irobot_create_2_1

Introducción a PyQt:
http://www.rkblog.rk.edu.pl/w/p/introduction-pyqt4/

Un widget PyQt para una vista previa de cámara mediante OpenCV:


https://rafaelbarreto.wordpress.com/2011/08/27/a-pyqt-widget-for-opencv-camera-
preview/

Tutoriales OpenCV:
http://acodigo.blogspot.com.es/p/tutorial-opencv.html

68
Multiprocesamiento en Python: Threads a fondo:

http://www.genbetadev.com/python/multiprocesamiento-en-python-threads-a-fondo-
introduccion

Documentación PyQt:
https://wiki.python.org/moin/PyQt

Cómo convertir imagen Python OpenCV a imagen Python Qpixmap:


http://flopalm.com/how-to-convert-python-opencv-image-numpy-array-to-pyqt-
qpixmap-image/

69
Capítulo 9
Anexo: iRobot Create
El iRobot Create es básicamente un robot diseñado expresamente para el desarrollo
de la robótica.

Imagen general del robot iRobot Create

Podría decirse que el iRobot Create es una Roomba diseñada para ser hackeada.
Puede observarse el parecido en las siguientes imágenes.

70
Vista comparativa superior entre el Create, a la izquierda, y el robot aspiradora Roomba, a la
derecha.

Vista comparativa inferior entre el Create, a la izquierda, y el robot aspiradora Roomba, a la


derecha.

Como podremos observar en la imagen que se muestra a continuación, la estructura


del robot es bastante simple. Cuenta con un receptor de infrarrojos en la parte frontal
que es utilizado para la detección de muros, ya sean reales o virtuales (estos últimos
creados también con sensores infrarrojos), además de ser utilizado para que el robot

71
encuentre la base y se cargue de manera automática. Por otro lado, dispone de una
cavidad para poder añadir elementos al robot, como por ejemplo una cámara para
que disponga de visión, o un sistema embebido para que el robot tenga autonomía de
manera que no sea necesario el uso de un PC para la programación o el control de
éste.

Imagen superior del iRobot Create y descripción de sus elementos

En el conector “Cargo Bay” se puede conectar desde una antena Bluetooth para
comunicarse con un PC o un dispositivo móvil mediante Bluetooth, a un módulo
supletorio, el “Command Module”, que se explicará en secciones posteriores.
Finalmente, también disponemos de la conexión con el cable serie para poder enviar
y recibir las órdenes al robot.

Por último, el Create cuenta con una serie de botones y sus correspondientes
indicadores a modo de leds, y un pequeño altavoz. Éstos actúan como salidas del
robot mostrando los estados del mismo y cualquier información que se le desee
indicar. Los botones pueden ser empleados como entradas digitales. El botón de
inicio, power button, se encarga de encender o apagar la máquina.

72
Imagen ilustratica del panel de botones e indicadores del iRobot Create

Como puede apreciarse en la imagen inferior, el robot dispone de cuatro sensores


ópticos infrarrojos y dos sensores de choque en la parte delantera. La finalidad de
estos últimos es la detección de obstáculos cuando el robot se golpea contra ellos.
Este tipo de sensores son muy utilizados durante las tareas de limpieza (en el
Roomba), de tal modo que cuando el robot choca contra un objeto, ya sea un muro,
una silla, una mesa, o cualquier otro tipo de obstáculo, sea capaz de sortearlo y
evitarlo gracias a estos dos sensores, para así no dejar ninguna zona sin limpiar.

Vista inferior de iRobot Create

Para cualquier consulta o aclaración de la arquitectura del Robot se puede consultar


la página web:

http://store.irobot.com/shop/index.jsp?categoryId=3311368

73
En las siguientes secciones se va a explicar con detalle algunas de las características
de las que dispone el robot, así como diferentes componentes adicionales que
podemos adquirir para nuestro robot. Otra parte fundamental que se verá con detalle
es la forma de programar el robot. Aunque, no sea excesivamente complejo, si qué es
cierto que disponemos de varias metodologías para interactuar con el robot; por lo
que se explicarán cada una de ellas y, en algunos casos, se pondrá algún ejemplo de
programación.

- Sensores

A continuación se va a explicar brevemente los sensores de los que disponemos en el


robot. En cualquier caso, si es necesario instalar cualquier sensor adicional, se puede
realizar sin más, puesto que cuenta con hasta 30 conexiones adicionales para añadir
cualquier hardware al robot.

Sensores de impacto

Como se ha comentado anteriormente, el robot dispone de 2 sensores en la parte


delantera, también conocidos como “bumpers”. El funcionamiento de éstos es muy
simple: nos brindan la capacidad de detectar obstáculos en su desplazamiento por
contacto directo. O dicho de otro modo, se trata de un pulsador que, en estado de
reposo (no hay choque) el sensor devuelve un “0” lógico. Por el contrario, en caso de
impacto, este pulsador es presionado; a continuación, se consulta el estado de este
dispositivo, que nos devuelve un “1” lógico, valor que nos indica que se ha producido
el impacto. Cuando ya no hay contacto con ningún obstáculo, el sensor vuelve a su
posición inicial con la ayuda de un muelle, por lo que ya no se recibe el “1” lógico del
sensor y se recibe un “0” lógico. Si quisiéramos obtener el estado de un sensor
simplemente enviamos un comando consulta al robot, bien por el cable serie o bien
por la conexión bluetooth.

74
Sensores de
impacto o
bumpers

Imagen del posicionamiento de los sensores de impacto o bumpers

Sensores Cliff (Infrarrojos)

Otro grupo de sensores que tiene el robot son los sensores ópticos infrarrojos. Cada
uno consta de un fotodiodo y un fototransistor para saber si existe peligro decaída. Es
decir, tenemos 4 sensores frontales que apuntan hacia el suelo y se usan únicamente
para saber si existe un desnivel y así, por ejemplo, poder parar el robot. La forma de
consultar el estado de estos sensores es como en el caso anterior, enviando un
código para recibir cuál es el estado de estos 4 sensores.

75
Sensores infrarrojos
o Cliff sensor

Detalle de la posición de los sensores infrarrojos

Encoders (Sensores de rotación)

Las dos ruedas del robot disponen de dos sensores de rotación que nos permite
saber cuánto se ha desplazado el robot, ya sea un desplazamiento lineal, tomada en
milímetros, o angular, medida en grados. Éstos actúan en cada rueda de manera
independiente. El encoder es un transductor rotativo que transforma un movimiento
angular en una serie de impulsos digitales. Por otro lado, la forma de trabajar con
estos encoders es algo limitada. Es decir, lo único que podemos consultar al robot es
la distancia que ha recorrido y el ángulo que ha girado. De ninguna forma podemos
acceder a los pulsos individuales de cada rueda. Esta tarea, se podrá realizar en
posteriores versiones del robot. Por lo tanto, cuando realizamos una consulta de la
distancia recorrida, el robot devuelve esta distancia (en milímetros) como la suma de
las distancias recorridas por cada rueda dividida entre dos. Cuando consultamos el
ángulo la forma de trabajar será similar. También hay que tener en cuenta que cada
vez que realizamos una consulta de estos valores, los contadores serán inicializados
para posteriores consultas, por lo que, esto será un aspecto crucial a tener en cuenta
en la programación, ya que de alguna manera hay que acumular los valores
consultados para no perder en ningún momento la referencia del robot. Finalmente,
después de realizar varios experimentos con el robot, se puede decir que los
encoders que utiliza funcionan razonablemente bien en lo que respecta a la distancia
recorrida. En cambio, experimentos realizados para consultar los grados que el robot
ha girado en un sentido y en otro, se obtiene errores considerables de estos giros. Por
ejemplo, si enviamos un comando para que el robot gire 90º, cuando hacemos la
petición para saber cuánto ha girado el robot, obtenemos valores de 88º ó 92º. Estos
valores son inadmisibles, puesto que se realizan muchas consultas a lo largo de la
ejecución del programa de trayectorias. Este error de 2 grados es para una consulta.
Si, por ejemplo, hacemos 10 consultas el error que estamos cometiendo es de 20º,

76
que, como observamos es un error muy grande. Por lo que únicamente usaremos el
encoder para consultas de desplazamiento lineal y, el desplazamiento angular será
estimado a través de otros mecanismos.

Encoders, o sensores de
rotación

Posición de los encoders en el iRobot Create

Sensores de caída

El robot también dispone de sensores de caída en cada una de las ruedas. Estos
sensores, simplemente sirven para saber si alguna de las ruedas está suspendida en
el aire o, por el contrario, está en contacto con el suelo. Estos tipos de sensores son
muy utilizados como medida de seguridad, de tal forma que, cuando se detecta que
alguna rueda no está en contacto con el suelo, el robot se para automáticamente para
evitar posibles daños en el entorno y daños del propio robot.

77
Sensores de caída

Imagen que muestra la posición de los sensores de caída

- Actuadores

Además de los sensores, también es necesario disponer de actuadores, que son los
componentes del robot donde podemos modificar su comportamiento. El Create de
iRobot dispone de los dos motores que mueven las dos ruedas de alimentación a
través de una transmisión por correa. Los actuadores son, por consiguiente, los
encargados de mover la plataforma. La velocidad máxima a la que estos motores
pueden trabajar es de 0,5 m/s, ya sea hacia delante o hacia atrás, y pueden realizar
giros circulares de hasta 0,2 m de radio.

Básicamente, la forma de trabajar con estos motores es muy simple. Existen dos
formas de interactuar con estos actuadores:

- Enviar la velocidad (en mm/s) de forma independiente a cada rueda. Con un


simple comando, enviamos al robot cuales son las velocidades que deben de tener
cada rueda, de forma independiente.

- Enviar la velocidad y el ángulo deseado. Se envía cual es la velocidad total lineal


que se desea (en mm/s) y qué ángulo que debe de girar respecto del centro del robot.
Este ángulo se indica en grados.

En cualquier caso, por simplicidad de programación y de cálculos en los algoritmos,


se usa el primer método. Es decir, todos los cálculos que se realizan son para obtener
las velocidades de la rueda izquierda y derecha de forma independiente, por lo que la
primera opción es la que se adapta a nuestras necesidades. Además, el robot también

78
dispone de una rueda delantera para conseguir una mayor estabilidad y, de forma
opcional, se puede instalar una rueda trasera para que, en caso de incorporar
componentes adicionales de un peso considerable encima del robot, no se pierda la
estabilidad. Estos dos tipos de ruedas son giratorias y no son del tipo actuador,
simplemente se utilizan para conseguir estabilidad. Por lo que los únicos actuadores
que va a disponer el robot son los de las ruedas de alimentación. En cualquier caso,
siempre se pueden añadir mecanismos al robot que también sean actuadores, como
por ejemplo, un pequeño brazo robótico para cualquier otro fin. No existen problemas
de conexión, pues dispone de una gran conectividad para componentes adicionales.

- Ruedas:

El Create cuenta con tres ruedas en su estructura: dos ruedas traseras y


una rueda delantera.

Vista de la estructura de la que forma parte las ruedas.

Detalle en el que puede apreciarse el actuador, la correa de transmisión y la rueda.

79
Las ruedas traseras comparten un mismo eje y cada una de ellas es controlada de
forma independiente. El movimiento de las mismas es independiente, lo que permite
la ejecución de tres tipos de desplazamientos: avance en línea recta, giro hacia
ambos lados y rotación sobre su propio eje.

La rueda delantera es libre, lo que facilita los movimientos del robot.

Se podría añadir una cuarta rueda en la parte trasera del ICR para mejorar la
estabilidad del robot, lo cuál sería principalmente útil cuando se añade carga a la
plataforma.

- Microcontrolador

El microcontrolador del Create es un MC9S12E128 de 16 bits, de la compañía


Motorola. Este microcontrolador es el responsable de la lectura de los sensores,
manejo de actuadores, conectores físicos y permite la interpretación de los comandos
de la interfaz abierta del ICR.

- Componentes adicionales

En los siguientes apartados se va a explicar con detalle algunos componentes


adicionales que podemos adquirir para el robot.

Command Module

Este robot, como desventaja, no dispone de ningún hardware para poder realizar un
programa residente en el robot y que trabaje de forma independiente. Como mucho,
se pueden realizar “scripts” que sí permanecen en el robot, pero como máximo son de
100 bytes. Para ello, se puede adquirir el command module. Este módulo permite
realizar programas en C y C++ que residen en dicho módulo, ya que dispone del
microprocesador Atmel AVR ATmega168, entre otros componentes. En la figura
siguiente se muestra la apariencia que tiene el “command module”.

Imagen del Command Module.

Como podemos observar en la imagen anterior, el command module además de


permitir realizar programas en C y C++ para que el robot tenga la autonomía
suficiente, dispone de varios conectores y puertos para aumentar la conectividad del
robot.

80
Bluetooth Adapter Module (BAM)

Otro dispositivo que podemos adquirir para el robot es una antena bluetooth que se
conecta en el “cargo bay connector” de éste. De esta forma, podemos realizar la
comunicación con el robot de forma inalámbrica. Es decir, lo único que se hace es
crear un puerto serie virtual que funciona como si fuese un puerto serie normal y
corriente, sólo que éste función a de forma inalámbrica gracias a este dispositivo.
Además, dispone de una serie de conectores para recibir información de ciertos pines
del robot o para conectar más actuadores. En la siguiente imagen puede apreciarse
este complemento.

Visión del Bluetooth Adapter Module (BAM).

81

También podría gustarte