Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Transporte (SGVRMT)
1
Indice
2
Transformada de Hough e integración con Aria
En esta etapa del proyecto implementaré una conducta de guiado visual que permita
realimentar el sistema de control con la información obtenida desde la cámara situada
sobre la plataforma móvil. Para realizar dicha implementación he optado por la biblioteca
Aria desarrollada por ActivMedia Robotics y que sustituye a la biblioteca Saphira en las
tareas de más bajo nivel de control del robot, encargándose de los aspectos más básicos
como la comunicación con el mismo y la lectura de los diferentes sensores.
Aria es una potente interfaz para clientes de los servidores de los robots de ActivMedia
Robotics totalmente desarrollada bajo el paradigma de orientación a objetos. Las
aplicaciones cliente desarrolladas con Aria pueden controlar dinámicamente la velocidad,
la orientación, la orientación relativa y otros parámetros de la navegación del robot
servidor.
Figura 1. Resolver
3
de Hough. La transformada de Hough es una técnica que puede ser usada para detectar
características de una figura particular dentro de una imagen. Ya que necesita que las
características deseadas sean expresadas en forma paramétrica, la transformada de Hough
clásica es usada comúnmente para detectar curvas regulares como líneas, círculos,
elipses, etc. Una transformada de Hough generalizada se puede emplear en aplicaciones
donde no es posible encontrar una descripción simple de las características.
Transformada de Hough
x cos θ + y sin θ = r
4
donde r es la longitud de la normal de la recta desde el origen y θ es la orientación de r
respecto al eje X , como se muestra en la figura 3. Para cualquier punto (x,y) sobre esta
línea, los valores de r y θ son constantes.
5
Figura 4. Detección de líneas con la transformada de Hough
( x − a ) 2 + ( y − b) 2 = r 2
Donde a y b son las coordenadas del centro del círculo y r es el radio. En este caso, la
complejidad computacional comienza a incrementarse ya que ahora tenemos tres
coordenadas en el espacio de parámetros y un acumulador de tres dimensiones.
La idea de este algoritmo es considerar píxeles aleatorios uno a uno. En cada ocasión el
acumulador es actualizado y se comprueba si el pico más alto sobrepasa un umbral. En
caso de que esto ocurra, los puntos que pertenecen al pasillo especificado por el pico son
eliminados. Si el número de puntos excede un valor predefinido de longitud mínimo de
línea, entonces es considerado una línea, en otro caso en considerado ruido. Luego se
repite el proceso desde el principio hasta que no queden más píxeles en la imagen. El
algoritmo mejora el resultado en cada paso, por lo que puede ser interrumpido en
cualquier momento.
Este método posee una desventaja ya que, al contrario que la transformada de Hough
estándar, no es capaz de procesar correctamente algunas características de la imagen,
como por ejemplo líneas cruzadas. Sin embargo esto no supone un problema para la
aplicación concreta en este caso ya las líneas a detectar en la imagen no tienen por qué
cruzarse.
7
Definición de comportamientos en Aria
Las acciones de comportamiento pueden controlar diferentes valores del robot, como la
velocidad de desplazamiento, la posición, la velocidad de giro y la orientación. Las
salidas de las acciones son combinadas por un resolver.
En cada ciclo de 100ms, cada objeto acción es evaluado y produce una salida para la
velocidad de translación y de rotación junto con la fuerza de cada uno. La fuerza, que
puede variar entre 0 y 1, indica como de fuerte deseada la acción que sea ejecutado este
movimiento. Una vez que las salidas de todas las acciones han sido calculadas, son
pasadas al resolver para determinar cuál será la salida final. El resolver estándar de Aria
utiliza una estrategia de resolución de dos partes. Para resolver la prioridad, se asocia una
valor de prioridad con cada acción, el cuál será un entero positivo. Cuanto mayor sea el
valor mayor será la prioridad de la acción. Dentro de cada clase de prioridad ( definida
como todas las acciones que tienen la misma prioridad), se calcula el promedio de las
salidas de acuerdo con su fuerza. Para determinar el movimiento final se busca en las
clases de prioridad desde mayor a menor prioridad. Una energía de activación es
inicializada a 1 para el nivel más alto, y el nivel “utiliza” la activación de acuerdo con la
fuerza de su acción más fuerte, por ejemplo, una fuerza de 1 usará toda la activación,
mientras que una fuerza de 0 no usará ninguna. En el siguiente nivel, el comando de
movimiento es promediado, pero usando la energía de activación restante. Nuevamente,
el nivel utiliza la activación basándose en la fuerza de su movimiento de salida.
8
Implementación
He desarrollado un cliente Aria (ver Anexo A) capaz de conectarse con una plataforma
robótica móvil de ActivMedia Robotics así como con el simulador de las mismas que
viene con la biblioteca Aria.
También he desarrollado dos acciones de Aria. Una de ellas implementa una interfaz de
usuario al estilo de Saphira pero más sencilla, que permite monitorizar de forma gráfica
el estado del robot y controlar su movimiento mediante teclado. Es una acción muy
sencilla pero que, al mismo tiempo, sirve de ejemplo para mostrar como se pueden
combinar las bibliotecas Aria y OpenCV. La segunda acción implementa un guiado
visual del robot utilizando la información obtenida de una cámara junto con sus
parámetros extrínsecos e intrínsecos.
La función más importante de una acción Aria es la función fire que implementa el
cuerpo principal de la acción y que devuelve un valor de tipo ArActionDesired que indica
el movimiento deseado por la acción.
Cliente Aria
El cliente inicializa la biblioteca Aria y habilita el anillo de sónars del robot.
Seguidamente trata de conectarse con el robot, finalizando la ejecución si no lo consigue.
Si la conexión tiene éxito añade dos acciones a la lista de acciones del robot y pone el
robot en marcha.
9
lo que la línea de velocidad crecerá en esa dirección a si la velocidad actual es positiva, y
en sentido contrario en caso de ser negativa. La misma línea sirve para indicar la
velocidad de rotación. Si el robot está girando a la izquierda la línea se moverá en esa
dirección en la ventana, es decir, hacia arriba. Hay que tener en cuenta que si el robot se
está moviendo hacia atrás, o sea, con velocidad de traslación negativa, la línea se moverá
hacia arriba cuando el robot esté girando hacia la derecha. En la misma ventana se
muestra la lectura de los sónars realizadas cada 10º. Se mostrará un cuadrado si se detecta
algo a una distancia inferior a 2m a una distancia proporcional del centro del robot y en el
ángulo adecuado.
Esta acción también permite el control del robot a través del teclado. Con la tecla ‘w’ se
puede incrementar la velocidad de traslación y con la ‘s’ se puede disminuir. Con la tecla
‘a’ se puede girar a la izquierda y con la tecla ‘d’ hacia la derecha.
10
la matriz de proyección. Una vez calculada rellena una matriz que sirve como mapa en
donde se almacenan las coordenadas en la imagen correspondientes a los puntos 3D
usados como referencia durante el proceso de calibración de los parámetros extrínsecos.
También calcula las coordenadas que corresponden en la imagen con el centro del robot.
Una vez iniciada la cámara, se captura una imagen en cada ciclo de evaluación de la
acción y se procesa. Primero se corrige la distorsión de la imagen mediante una función
OpenCV y seguidamente se marca la región de la imagen que corresponde con la zona
del suelo situado frente al robot como región de interés, por lo que los procesos siguientes
se realizarán sobre esta zona de la imagen, y no tendrán en cuenta las regiones negras
añadidas por el proceso de corrección de distorsión. El siguiente paso es la búsqueda de
la línea de guiado del robot en la imagen. Para conseguirlo ser realiza un umbralizado de
la imagen y luego se aplica el algoritmo de Canny para la detección de bordes. El
umbralizado previo a la detección de bordes puede ser deshabilitado desde la ventana de
la acción, y también puede especificarse el valor de umbral. Sobre la imagen de bordes se
aplica la transformada de Hough progresiva probabilística. El centre de cada línea
detectada se marca sobre la imagen con un circulo azul. Al final de este proceso se
obtienen las coordenadas del centro de la línea situada más a la derecha. Con esta
información se busca el punto más cercano sobre la imagen que se encuentre en el mapa
y serán las coordenadas de ese punto el espacio hacia las que se dirija el robot.
La línea azul une el centro del robot con el punto de destino del movimiento.
Las distancias dx y dy hasta al centro del robot son usadas para calcular el ángulo alfa,
que determinará la nueva orientación del robot. La velocidad de traslación se ajustará a
10cm por segundo siempre que se detecten líneas en la imagen.
12
Anexos
Anexo A
Fichero guivi_act.cpp que implementa un cliente Aria.
#include "Aria.h"
#include "IuAct.h"
#include "GvAct.h"
IuAction interfaz;
GvAction gui_vi(true, 200);
Aria::init();
robot.addRangeDevice( &sonar);
robot.setAbsoluteMaxTransVel( 400);
robot.comInt( ArCommands::ENABLE, 1);
robot.comInt( ArCommands::SOUNDTOG, 0);
//----------------------------------------
//----------------------------------------
robot.run( true);
Aria::shutdown();
return 0;
13
Anexo B
Fichero IuAct.h con la definición e implementación de la acción IuAction.
#ifndef IUACTION_H
#define IUACTION_H
#include "Aria.h"
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
IuAction::IuAction() :
ArAction("IU", "Muestra información del robot.")
{
miSonar = NULL;
miImg = cvCreateImage( cvSize( 400, 400), IPL_DEPTH_8U, 1);
cvSet( miImg, cvScalar(255,255,255), 0);
iniciar = true;
miIncV = 15;
miIncDH = 10;
}
14
int alto_vent_inf = 90;
int rob_x = 150;
int rob_y = 150;
x = (int)(cos( angle*CV_PI/180.)*((dist*150)/2000));
y = (int)(sin( angle*CV_PI/180.)*((dist*150)/2000));
cvRectangle( img, cvPoint(rob_x+x,rob_y-y),
cvPoint(rob_x+5+x,rob_y+5-y), cvScalar(0,0,255));
}
}
}
myDesired.reset();
if( miSonar == NULL)
{
15
deactivate();
return NULL;
}
if( iniciar)
{
cvNamedWindow("IU", CV_WINDOW_AUTOSIZE);
iniciar=false;
}
miVelDeseada = myRobot->getVel();
miGiroDeseado = 0;
if( miImg != 0)
{
pinta_iu( miImg, myRobot);
cvShowImage("IU", miImg);
if( ( c = cvWaitKey(1)) != -1)
{
switch( c)
{
case 'w': miVelDeseada += miIncV; break;
case 's': miVelDeseada -= miIncV; break;
case 'a': miGiroDeseado = miIncDH; break;
case 'd': miGiroDeseado = -miIncDH; break;
case 32: miVelDeseada = 0; break;
case '\x1b': myRobot->stopRunning(); break;
}
myDesired.setVel( miVelDeseada);
myDesired.setDeltaHeading( miGiroDeseado);
return &myDesired;
}
}
return NULL;
}
#endif // IUACTION_H
16
Anexo C
Fichero GvAct.h con la definición e implementación de la acción GvAction.
#ifndef GVACTION_H
#define GVACTION_H
#include "Aria.h"
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
float P[3*4];
CvMat mP;
CvPoint *mapa;
CvPoint3D32f *mapa3D;
CvPoint centro_robot;
CvPoint3D32f centro_robot3D;
CvCapture *camara;
int miUmbral;
int miUmbralizar;
};
float A[3*4];
carga_params_int( "params_int.txt");
17
A[0] = mat_camara[0]; A[1] = mat_camara[1]; A[2] = mat_camara[2];
A[3] = 0;
A[4] = mat_camara[3]; A[5] = mat_camara[4]; A[6] = mat_camara[5];
A[7] = 0;
A[8] = mat_camara[6]; A[9] = mat_camara[7]; A[10] = mat_camara[8];
A[11] = 0;
float D[4*4];
carga_params_ext( "params_ext.txt");
D[0] = mat_rotacion[0]; D[1] = mat_rotacion[1]; D[2] =
mat_rotacion[2]; D[3] = vec_traslacion[0];
D[4] = mat_rotacion[3]; D[5] = mat_rotacion[4]; D[6] =
mat_rotacion[5]; D[7] = vec_traslacion[1];
D[8] = mat_rotacion[6]; D[9] = mat_rotacion[7]; D[10] =
mat_rotacion[8]; D[11] = vec_traslacion[2];
D[12] = 0; D[13] = 0; D[14] = 0; D[15] = 1;
float XYZ[4];
float uv[3];
CvMat mXYZ;
CvMat muv;
18
IplImage *gris2 = cvCreateImage( cvGetSize( src), IPL_DEPTH_8U,
1);
CvMemStorage *storage = cvCreateMemStorage( 0);
CvSeq *lines = 0;
*pto_d = cvPoint(0,0);
cvReleaseImage( &gris);
cvReleaseImage( &gris2);
cvReleaseMemStorage( &storage);
return n_lines;
}
return 0;
}
19
int GvAction::carga_params_int( char *nombre_fichero)
{
FILE *f;
fclose( f);
return 0;
}
20
if( i>9)
{
if( sqrt( pow( abs( pto_d.x - mapa[i+1-10].x),2) + pow( abs(
pto_d.y - mapa[i+1-10].y),2)) < dist)
{
dist =sqrt( pow( abs( pto_d.x - mapa[i+1-10].x),2) +
pow( abs( pto_d.y - mapa[i+1-10].y),2));
i_mapa = i+1-10;
}
if( sqrt( pow( abs( pto_d.x - mapa[i-10].x),2) + pow( abs(
pto_d.y - mapa[i-10].y),2)) < dist)
{
dist =sqrt( pow( abs( pto_d.x - mapa[i-10].x),2) +
pow( abs( pto_d.y - mapa[i-10].y),2));
i_mapa = i-10;
}
}
return i_mapa;
}
if( !camara_iniciada)
{
camara = cvCaptureFromCAM( 0);
if(( camara) && ( frame = cvQueryFrame( camara)))
{
img = cvCreateImage( cvGetSize( frame), IPL_DEPTH_8U,
3);
camara_iniciada = true;
dim_frame = cvGetSize( frame);
21
pto_dest.y += 50;
cvResetImageROI( img);
DibujaMapa( img);
cvCircle( img, pto_dest, 6, cvScalar(0,0,255));
if( mapa3D[i_mapa].x == 0)
{
myDesired.setDeltaHeading(0);
}
else
{
double hip = sqrt( pow( mapa3D[i_mapa].x, 2) + pow(
abs( centro_robot3D.y) + mapa3D[i_mapa].y, 2));
double theta = (asin( fabs( mapa3D[i_mapa].x) / hip) *
360) / CV_PI;
if( mapa3D[i_mapa].x > 0) theta = theta * -1;
myDesired.setDeltaHeading( theta);
}
myDesired.setVel( 100);
}
else
{
myDesired.setDeltaHeading( 0);
myDesired.setVel( 0);
}
cvResetImageROI( img);
return &myDesired;
}
#endif // GVACTION_H
22
Bibliografía
[Kor98] Kortenkamp D., Bonaso P., Murphy R. (Edit.) "Artificial Inteligence and Mobile
Robots. Case Studies of Successful Robot Systems", MIT Press, 1.998.
Computing, 1995.
23
24