Conclusiones

31/05/2009 at 7:25 pm (General)

Por último, hicimos un video para ver como funciona el programa completo:

    Enlace al video en ScreenCastle

En resumen hemos aprendido mucho sobre el robot nao, la forma de realizar movimientos simples (andar o girar) y como relacionarnos con el entorno por medio de los diferentes sensores de los que disponemos (ultrasonidos, presión). También hemos aprendido a obtener la imagen y hacer transformaciones entre los diferentes formatos (HSV, YUV, RGB).

Además de aprender a implementar un interfaz gráfico sencillo y al manejo del simulador webots.

Permalink Dejar un comentario

Sistema de Visión: YUV

30/05/2009 at 6:33 pm (Robot Nao)

En este caso probaremos con el formato YUV. Obtendremos la imagen de la cámara del robot como antes en formato RGB, una vez la tengamos la convertimos a su correspondiente en YUV.

    y = r * .299000 + g * .587000 + b * .114000;
    u = r * -.168736 + g * -.331264 + b * .500000 + 128;
    v = r * .500000 + g * -.418688 + b * -.081312 + 128;

Una vez hecho esto mostraremos las 3 imagenes en el interfaz (la de Y , U, V). Y volveremos a convertir la imagen a RGB para mostrar la otra.

    r = y + 1.4075 * (v – 128);
    g = y – 0.3455 * (u – 128) – (0.7169 *(v – 128));
    b = y + 1.7790 * (u – 128);

yuv

yuv2

Permalink Dejar un comentario

Sistema de Visión: HSV

30/05/2009 at 6:26 pm (Robot Nao)

Una vez representada la imagen en RGB nos pusimos a probar con diferentes formatos de imagen, en este caso usaremos el HSV.

Obtendremos la imagen de la cámara del robot como antes en formato RGB, una vez la tengamos la convertimos a su correspondiente en HSV.

    float max = r;
    float min = r;

    if (max < g) max = g;
    if (min > g) min = g;
    if (max < b) max = b;
    if (min > b) min = b;

    if (max == min){
    h = 0.0;

    if (max == r ){
            h = 60 * ((g – b) / (max – min));
            if (g < b){
                    h += 360;
            }
    }
    if (max == g){
            h = (60 * ((b – r) / (max – min))) + 120;
    }
    if (max == b){
            h = (60 * ((r – g) / (max – min))) + 240;
    }
    if (max == 0){
            s = 0.0;
    }else{
            s = 1 – (min / max);
    }
    v = max;

Una vez hecho esto mostraremos las 3 imagenes en el interfaz (la de H , S, V). Y volveremos a convertir la imagen a rgb.

    float h_aux, f, p, q, t, v_aux;

    h_aux = ((int)fabs(H/60.0)) % 6;
    f = (H/60.0) – h_aux;

    v_aux = V;
    p = v_aux * (1-S);
    q = v_aux * (1 – f*S);
    t = v_aux * (1 – (1-f)*S);

    if (((int)h_aux) == 0){
            r = v_aux; g=t; b=p;
    }
    else if (((int)h_aux == 1)){
            r = q; g=v_aux; b=p;
    }
    else if (((int)h_aux == 2)){
            r = p; g=v_aux; b=t;
    }
    else if (((int)h_aux == 3)){
            r = p; g=q; b=v_aux;
    }
    else if (((int)h_aux == 4)){
            r = t; g=p; b=v_aux;
    }
    else if (((int)h_aux == 5)){
            r = v_aux; g=p; b=q;
    }

Tuvimos algún problema en las conversiones, perdiamos algo de información y no nos dimos cuenta de los rangos en los que estaba HSV, pero pudimos arreglarlo sin ningún problema.

    image1->SetRGB(x/2, y/2, (h * 255/360), 0, 0);
    image2->SetRGB(x/2, y/2, 0, (s * 255), 0);
    image3->SetRGB(x/2, y/2, 0, 0, v);

hsv

hsv2

Permalink Dejar un comentario

Sistema de Visión

30/05/2009 at 6:21 pm (Robot Nao)

Una vez tenemos el proxy al módulo de NaoCam podemos llamar a sus métodos.

Primero registraremos los parámetros en la cámara, ajustando la resolución, el tipo de imagen que queremos obtener y el refresco. En nuestro caso obtendremos la imagen en RGB en formato VGA (640 x 480) con 5fps de refresco.

    gvm_fname = camera_proxy->call<std::string>(“register”, gvm_fname,     
    camera_resolution, colorSpace, fps);    

Luego seleccionaremos la cámara que queramos usar, en nuestro caso usaremos una variable que modificamos con el interfaz gráfico para elegir entre la cámara frontal o la que apunta al suelo.

    camera_proxy->callVoid(“setParam”, kCameraSelectID, camera_selection);    

Una vez configurada podremos coger la imagen de la cámara, usaremos el método getImageRemote en una llamada al proxy para obtener una imagen del tipo ALValue.

    AL::ALValue lastImage;    
    lastImage = camera_proxy->call<AL::ALValue>(string(“getImageRemote”),      
    gvm_fname);    

Antes de mostrar la imagen en el interfaz realizamos alguna prueba para verificar que la obteniamos correctamente. Sacamos de la imagen los datos que la definían (alto, ancho, número de capas (al ser rgb son 3), el tipo de imagen y el tamaño) y los imprimimos por la salida estándar (consola).

salida shell

También nos creamos un fichero .ppm donde la guardabamos para poder comprobar con un editor de imagen que los colores son iguales.

Después de comprobar que lo hacía correctamente la mostramos por el interfaz. Tendremos que crearnos una variable del tipo wxImage y la pintaremos pixel por pixel con los componentes rgb leidos.

    wxImage *image;    
    image->SetRGB(x, y, R, G,  B);    

Una vez tengamos la imagen tendremos que mostrarla por el interfaz, usaremos un cliente dc para ello.

    wxBitmap bitmap1(*image);    
    wxClientDC dc1(bitmap_1);    
    bitmap_1->GetPosition(&xx ,&yy);    
    dc1.DrawBitmap(bitmap1, xx, yy, false);    

Al pintar la imagen pixel por pixel y tener los componentes RGB separados nos permite mostrarlos individualmente. En nuestro programa mostraremos los 3 y la imagen completa.

rgb

RGB2

Permalink Dejar un comentario

Sensores de ultrasonidos

29/05/2009 at 5:39 pm (Robot Nao)

Nao dispone de 2 parejas de ultrasonidos.

Ultrasonidos

Para conocer el valor de ambos ultrasonidos en cada momento hay que acceder al módulo de memoria a través de su memoryProxy y obtener los datos de las siguientes posiciones utilizando el método getData. Los datos se almacenan en un array de 2 posiciones:

    ”extractors/alultrasound/distances”     

Con los valores obtenidos teniamos el mismo problema de siempre y es que nos devolvía enteros por lo que perdiamos los decimales. En este caso el problema era aun mas grave porque los valores que devuelve el ultrasonidos van desde 0 hasta 1, de forma que siempre nos devolvía 0 y no sabiamos si estabamos cogiendo los valores adecuados.

El dato verdadero se puede mirar en el módulo de memory cuando el webots esta en funcionamiento.

Permalink Dejar un comentario

Sensores de presión

29/05/2009 at 5:36 pm (Robot Nao)

El Nao tiene 4 sensores de presión en cada pie.

Piezitos

Para conocer su valor hay que acceder al módulo de memoria a través de su memoryProxy y obtener los datos de las siguientes posiciones con el método getData

Para el pie izquierdo:

    ”Device/SubDeviceList/LFoot/FSR/FrontLeft/Sensor/Value”    

    ”Device/SubDeviceList/LFoot/FSR/FrontRight/Sensor/Value”    

    ”Device/SubDeviceList/LFoot/FSR/RearLeft/Sensor/Value”    

    ”Device/SubDeviceList/LFoot/FSR/RearRight/Sensor/Value”    

Para el pie derecho:

    ”Device/SubDeviceList/RFoot/FSR/FrontLeft/Sensor/Value”    

    ”Device/SubDeviceList/RFoot/FSR/FrontRight/Sensor/Value”    

    ”Device/SubDeviceList/RFoot/FSR/RearLeft/Sensor/Value”    

    ”Device/SubDeviceList/RFoot/FSR/RearRight/Sensor/Value”    

Con los valores obtenidos teniamos un gran problema, nos dimos cuenta que cualquier petición de datos al robot nos la devolvía siempre como un entero truncado, en este caso las medidas del sensor de presión son floats y tienen decimales los cuales perdemos.

En la siguiente consola observamos los valores del robot cuando esta parado, apoyado con ambos pies en el suelo. Cuando levanta un pie del suelo los valores son cero y los del pie apoyado incrementan.

salida shell

Permalink Dejar un comentario

Movimiento

27/05/2009 at 12:53 am (Robot Nao)

En el apartado de movimiento, lo que teniamos que realizar es que Nao sea capaz de andar hacia delante y hacia atrás, además de poder girar a ambos lados.

Para andar hay que crear un proxy al ALMotion. Una vez lo tengamos creado ya podemos realizar las llamadas a los métodos del módulo, en nuestro caso:

setBodyStiffness: Es lo primero a lo que hay que llamar después de conectarse al módulo, sirve para dar fuerza a las articulaciones (el parámetro es un valor entre 0 y 1).

    pmotion->setBodyStiffness(1.0);    

setWalkConfig: Sirve para ajustar los parámetros del nao al moverse. Con esta tuvimos problemas ya que si la usabamos el robot no andaba, sólo andaba si no la utilizabamos y dejabamos los valores por defecto del Webots.
Para girar si que podiamos emplearla con los siguientes parámetros y funcionaba perfecta:

    pmotion->setWalkConfig( 0.05, 0.07, 0.04, 0.4, 0.01, 0.00);    

Para girar empleamos la función:

    pmotion->turn(giro , 80);    

La variable giro tendrá el valor que se le asigne desde la interfaz por el usuario. El 80 es la velocidad con que girará el robot. De esta forma gira a la izquierda, para girar a la derecha solo habría que negar la variable giro.

Para andar empleamos la función:

    pmotion->post.walkStraight(distancia, 80);    

La variable distancia tendra el valor asignado por le usuario desde la interfaz. El 80 es para lo mismo que en la funcion girar. Para andar hacia atrás basta con negar la variable distancia.

Como se puede observar en ambas funciones hemos empleado el prefijo post. Esto provoca que no sean bloqueantes las acciones de andar y girar para poder capturar imagenes al mismo tiempo.

En el siguiente video se pueden observar los problemas al andar después de ajustar los parámetros de caminata.

    Enlace al video en ScreenCastle

1º Gira a la derecha sin haber ajustado los parámetros de giro correctos (se observa como se tambalea ligeramente).
2º Anda hacia delante con los parametros por defecto.
3º Gira a la izquierda habiendo ajustado los parámetros de giro buenos.
4º Se cae al intentar andar después de haber ajustado los parámetros de caminata.

Permalink Dejar un comentario

El robot Nao

27/05/2009 at 12:43 am (General)

Este  robot ha sido creado por Aldebaran Robotics, se engloba en la clase de humanoides. Principalmente es usado en la robocup para competición.

Este robot es muy completo, cuenta con muchos sensores y actuadores con los que manejarlo.

HardWare_JointName

Tiene varios servos en todas sus articulaciones lo q le permite una gran movilidad y libertar de movimiento.
Además cuenta con diversos sensores para interactuar con el mundo, disponemos de 2 cámaras situadas en la cabeza, 2 sensores de ultrasonidos en el pecho, sensores de presión tanto en la planta como en la punta de los pies, 3 giroscopios en los 3 ejes de coordenadas, además de diversos leds, micrófonos y altavoces.

nao_leds_in_the_dark

Permalink Dejar un comentario

Conectando con Webots

27/05/2009 at 12:19 am (Robot Nao)

Para conectar nuestra aplicación con el simulador webots se puede hacer de 2 formas diferentes pero con igual resultado.

1- Crear un proxy directamente desde nuestra aplicación al módulo seleccionado.

Nos conectaremos en un principio al módulo de la cámara “NaoCam” para obtener imagenes de las cámaras.

    AL::ALProxy *camera_proxy;
    camera_proxy = new ALProxy ( “NaoCam” , “127.0.0.1″ , 9559 );      

2- Crearnos un broker y sacar los proxies a través de él. Este modo nos permite hacer llamadas a los métodos de los módulos como si fuesen propios.

Crearemos un broker, introduciremos los parámetros para crearlo, el nombre del broker, la ip y el puerto, y la ip y puerto del broker padre.

    AL::ALPtr pBroker;
    pBroker = AL::ALBroker::createBroker(brokerName, brokerIP, brokerPort,     
    parentBrokerIP, parentBrokerPort);

Una vez creado el broker crearemos a partir de él 2 proxies a los módulos que queremos, en este caso al de “ALMemory” y al “ALMotion”.

    AL::ALPtr pmotion;    
    AL::ALPtr memoryProxy;    
    pmotion = pBroker->getMotionProxy();    
    memoryProxy = pBroker->getMemoryProxy();    

Permalink Dejar un comentario

Interfaz gráfico

26/05/2009 at 11:43 pm (General)

El interfaz gráfico lo crearemos a partir de la librería wxWidget, usaremos el programa wxGlade que trabaja sobre esta librería y nos permite generar el interfaz de una forma cómoda y sencilla. wxGlade nos permite exportar el código en formato xrc que es fácilmente adaptable en un programa implementado en c++.

Al principio no nos dio demasiados problemas pero cuando iba creciendo la práctica y teniamos que añadir nuevos botones o cuadros de imagen, nos dio bastante guerra ya que era difícil de cuadrar cada uno.

Al final el interfaz gráfico fue el siguiente:

interfaz1

Permalink Dejar un comentario

Introducción y objetivos

26/05/2009 at 11:02 pm (General)

!!!Bienvenidos al blog sobre el robot Nao!!!

En primer lugar nos presentaremos: somos Daniel Montero y Alberto Sánchez, alumnos de Ingeniería Técnica en Informática de Sistemas de la UJRC.

Este blog está diseñado para la asignatura robótica de 3º de carrera y tratará sobre el robot Nao.

NaoDoc

No trabajaremos sobre el propio robot,  si no que emplearemos el simulador Webots que nos aportará ventajas como agilizar el proceso de pruebas y no correr el riesgo de romper el robot (al ser un robot bípedo es fácil que se caiga al suelo si se desestabiliza).

Los objetivos de la asignatura serán trabajar con los sensores y actuadores del robot, principalmente con las 2 cámaras  de la cabeza. Además diseñaremos un interfaz gráfico no muy complejo para trabajar con nuestro programa.

Permalink Dejar un comentario

Seguir

Get every new post delivered to your Inbox.