Interfaz para PC y Teleoperación Del Robot Irobot Create (iROBOT CREATE INTERFACE FOR TELEOPERATION) (2015)
Interfaz para PC y Teleoperación Del Robot Irobot Create (iROBOT CREATE INTERFACE FOR TELEOPERATION) (2015)
Realizado por:
Pablo Navarro Natal
Dirigido por:
Daniel Cagigas Muñiz
Departamento de
Arquitectura y Tecnología de Computadores
Sois muchos con los que me siento en deuda por el apoyo recibido.
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.
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.
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
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.
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.
10
Imagen del conversor USB/Serie
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.
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.
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.
Ahora serán detallados los componentes a nivel de software que se han requerido
para el desarrollo del sistema.
2.2.1 Ubuntu
13
todo aquel que haga uso de este sistema.
2.2.2 Python
14
Logotipo de Python.
La filosofía de Python hace hincapié en una sintaxis que favorezca un código legible.
2.2.3 Qt
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.
16
Ejemplo de vista de Qt Creator
17
Ejemplo de vista de Qt Designer
18
2.2.4 OpenCV
Logo de OpenCV
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.
20
una instrucción. Una vez que el servidor haya proporcionado una respuesta,
simplemente espera a que el cliente presente otra solicitud.
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:
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.
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
- 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()
- accept()
- 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.
24
describirlo para hacernos una idea de en qué consiste el mismo.
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:
25
Capítulo 3
Diseño y arquitectura del sistema
26
Y el diagrama de bloques de la aplicación, es el que se muestra a continuación:
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:
• Envío de información:
28
información será enviado de nuevo al servidor.
• Cierre de la conexión:
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
S2. Ponemos el nombre y puerto del socket: Dirección IP = ' ', Puerto = 9999.
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:
30
Valor 8: El robot se desplaza hacia atrás a menor velocidad.
3.2 Cliente
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.
32
Capítulo 4
Implementación
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.
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.
34
"""
Filename: clientepfc.py
"""
#!/usr/bin/env python
import sys
import signal # Módulo que proporciona mecanismos de gestión de eventos
# asíncronos del sistema.
# 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
#--------------------------------------------------------------
# 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)
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)
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):
"""
"""
global prioridadBotones
global move
self.q = q
# 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']
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"
else: #Atrás
move = "8"
print "Atras"
#Adelante
elif (y<150):
if (x>400): #Adelante-Derecha
move = "6"
print "Adelante-Derecha"
else: #Adelante
move = "9"
print "Adelante"
40
if (y < 75): #Adelante (a mayor velocidad)
move = "10"
print "Adelante"
print "CoordenadaMinimaY", y
#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 run(self):
"""
"""
global f
global prioridadBotones
global move
while True:
if not q.empty():
obj = q.get(False)
prioridadBotones=True
45
elif ID_RIGHT==obj: # Se lee un valor ID_RIGHT
move=ID_RIGHT
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_()
46
"""
Filename: sesrverpfc.py
"""
#!/usr/bin/env python
import sys
import signal # Módulo que proporciona mecanismos de gestión de eventos
# asíncronos del sistema.
# 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
#--------------------------------------------------------------
# Clase Server
#--------------------------------------------------------------
class Server:
def connect():
"""
"""
48
# Invoco al método bind, pasando como parametro una tupla con IP
# y puerto
serverSocket.bind((' ', port))
# 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)
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)
connect()
53
Capítulo 5
Manuales
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.
54
de ROS.
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.
56
Detalle (II) del cuadro de mandos 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.
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.
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.
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'.
try:
while True:
c=cv.WaitKey(50)
if c != -1:
print c
60
elif c == 65364: #down arrow
if leftSpeed > -500 and rightSpeed > -500:
print 'Back/ Slow down'
leftSpeed -= 2*changeSpeed
rightSpeed -= 2*changeSpeed
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.
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.
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.
62
cambios de formato a lo largo del código.
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.
63
#Capturamos una imagen y la convertimos de RGB -> HSV
_, imagen = captura.read()
hsv = cv2.cvtColor(imagen, cv2.COLOR_BGR2HSV)
#Crear una mascara con solo los pixeles dentro del rango de verdes
mask = cv2.inRange(hsv, verde_bajos, verde_altos)
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.
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.
66
Capítulo 7
Conclusiones y aplicaciones futuras
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.
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.
Referencias
Tutoriales ROS:
http://www.ros.org/wiki/ROS/Tutorials
Introducción a PyQt:
http://www.rkblog.rk.edu.pl/w/p/introduction-pyqt4/
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
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.
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.
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.
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
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
Sensores de impacto
74
Sensores de
impacto o
bumpers
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
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
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
- 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:
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:
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.
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
- Componentes adicionales
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”.
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.
81