La parametrización es relativamente trabajosa. Los parámetros más importantes son la relación entre fuerza atractiva y repulsiva, así como las distancias a las que la fuerza repulsiva se hace cero y llega a su máximo.
El problema principal que tuve es que tenía un bug en el cálculo de la fuerza repulsiva. Estaba correcta para 0º, 90º y 180º, pero en valores intermedios tenía un error. Y, sobre todo, el problema principal es que el error no era demasiado grande, es decir, el programa medio funcionaba. Así que parametricé y afiné con ese error. Cuando lo descubrí, porque las cosas no acababan de ir bien, quedaba muy poco tiempo para re-parametrizar. Tuve que volver a calcular los parámetros.
El robot, no sé si por él mismo o por artefactos del simulador, tiene mucha inercia. Me gustaría poder probarlo con un robot de verdad, porque tampoco se hace uno una idea por la presentación gráfica...
Finalmente conseguí una parametrización medio buena, parece que la práctica acabó saliendo bien.
Prácticas de Robótica
Blog de la asignatura de robótica del master en Sistemas Telemáticos e informáticos de GSYC, Universidad Rey Juan Carlos
jueves, 12 de mayo de 2011
viernes, 6 de mayo de 2011
La segunda práctica: navegación local usando campos de potencial
La segunda práctica consiste en hacer bastante más inteligente nuestro robot. En lugar de limitarse a detenerse y girar aleatoriamente cuando va a chocar, ahora queremos que sea capaz de ir hasta un punto destino esquivando obstáculos que pueda haber en el camino. Para ello usaremos un método relativamente simple: el de campos de potencial generalizados.
Se trata de un método de navegación local, es decir, no basada en mapa sino en sensores, que sirve para objetivos cercanos.
El método consiste en considerar que nuestro robot está sometido a una fuerza atractiva, que depende de la distancia al destino, y de un campo de fuerzas repulsivas, que depende de las distancias a cada obstáculo.
Haremos la fuerza atractiva proporcional a la distancia, con un máximo. Es decir, más allá de una determinada distancia la fuerza atractiva es constante.
La fuerza repulsiva de cada obstáculo percibido es inversamente proporcional a la distancia. La fuerza repulsiva total será la suma vectorial de todos los obstáculos. En el caso del robot Pioneer usaremos el sensor detector de distancias laser, que nos proporciona la distancia a obstáculos con resolución de 1º, de en toda la mitad frontal de nuestro horizonte. Es decir, tendremos 180 distancias a obstáculos con las que calcular nuestra fuerza repulsiva.
La fuerza total se calcula combinando la atractiva y la repulsiva con dos parámetros cuya razón da el grado de timidez o prudencia (avanzamos lentamente hacia el objetivo, nos dan "miedo" los obstáculos) contra temeridad (avnzamos hacia el objetivo ignorando los obstáculos). Una vez calculada la fuerza total, será la que guíe nuestra navegación. Es decir, le daremos órdenes a los sensore en función de su valor y dirección.
Nos recomienda el profesor que primero usemos las rutinas del simulador para dibujar el vector de la fuerza atractiva con origen en el robot. Luego, que pintemos alguna componente repulsiva, luego la suma. Finalmente podemos pintar también la resultante.
Lo hago mientras mantengo las rutinas de navegación choca-gira, y eso me permite familizarizarme y ajustar los parámetros para que las fuerzas tengan un balance razonable.
En la figura se aprecia solo la fuerza atractiva, en rojo, en diagonal hacia el puntero del ratón. Las otras líneas son los ejes de coordenadas del robot.
Se trata de un método de navegación local, es decir, no basada en mapa sino en sensores, que sirve para objetivos cercanos.
El método consiste en considerar que nuestro robot está sometido a una fuerza atractiva, que depende de la distancia al destino, y de un campo de fuerzas repulsivas, que depende de las distancias a cada obstáculo.
Haremos la fuerza atractiva proporcional a la distancia, con un máximo. Es decir, más allá de una determinada distancia la fuerza atractiva es constante.
La fuerza repulsiva de cada obstáculo percibido es inversamente proporcional a la distancia. La fuerza repulsiva total será la suma vectorial de todos los obstáculos. En el caso del robot Pioneer usaremos el sensor detector de distancias laser, que nos proporciona la distancia a obstáculos con resolución de 1º, de en toda la mitad frontal de nuestro horizonte. Es decir, tendremos 180 distancias a obstáculos con las que calcular nuestra fuerza repulsiva.
La fuerza total se calcula combinando la atractiva y la repulsiva con dos parámetros cuya razón da el grado de timidez o prudencia (avanzamos lentamente hacia el objetivo, nos dan "miedo" los obstáculos) contra temeridad (avnzamos hacia el objetivo ignorando los obstáculos). Una vez calculada la fuerza total, será la que guíe nuestra navegación. Es decir, le daremos órdenes a los sensore en función de su valor y dirección.
Nos recomienda el profesor que primero usemos las rutinas del simulador para dibujar el vector de la fuerza atractiva con origen en el robot. Luego, que pintemos alguna componente repulsiva, luego la suma. Finalmente podemos pintar también la resultante.Lo hago mientras mantengo las rutinas de navegación choca-gira, y eso me permite familizarizarme y ajustar los parámetros para que las fuerzas tengan un balance razonable.
En la figura se aprecia solo la fuerza atractiva, en rojo, en diagonal hacia el puntero del ratón. Las otras líneas son los ejes de coordenadas del robot.
jueves, 5 de mayo de 2011
Afinando el choca-gira
Una vez programado el comportamiento base del choca-girar, es decir, los tres estados y la transición entre ellos, me encontré con un problema: el robot tiene mucha inercia, y es relativamente fácil tanto chocar con la pared como volcarlo.
El choque con la pared se produce porque la velocidad adelante que le asignamos no la adquiere instantáneamente, por lo que si la distancia a la que comenzamos a dar orden de retroceder es corta, no le dará tiempo a hacerlo y chocará.
El problema del vuelco típicamente pasa cuando para resolverlo hacemos la velocidad de retroceso más alta. Pasar de golpe una velocidad de ~700 mm/s a una velocidad de -500 mm/s, por ejemplo, volcará el robot.
Para estos problemas hay soluciones posibles:
• aumentar la distancia a la que cambiamos de estado hará más difícil el choque
• reducir las velocidades de avance/retroceso también
• algo más sofisticado, se puede hacer que la velocidad adelante dependa de la distancia al obstáculo, siendo menor cuando nos acercamos a la distancia a la que cambiaremos de estado
Presento una imagen de la simulación.
El choque con la pared se produce porque la velocidad adelante que le asignamos no la adquiere instantáneamente, por lo que si la distancia a la que comenzamos a dar orden de retroceder es corta, no le dará tiempo a hacerlo y chocará.
El problema del vuelco típicamente pasa cuando para resolverlo hacemos la velocidad de retroceso más alta. Pasar de golpe una velocidad de ~700 mm/s a una velocidad de -500 mm/s, por ejemplo, volcará el robot.Para estos problemas hay soluciones posibles:
• aumentar la distancia a la que cambiamos de estado hará más difícil el choque
• reducir las velocidades de avance/retroceso también
• algo más sofisticado, se puede hacer que la velocidad adelante dependa de la distancia al obstáculo, siendo menor cuando nos acercamos a la distancia a la que cambiaremos de estado
Presento una imagen de la simulación.
viernes, 15 de abril de 2011
Problemas en las prácticas
C++ como problema
El primer problema es C++. Siempre me ha parecido un mal lenguaje; un lenguaje supuestamente de alto nivel diseñado de manera que su código fuente sea un superconjunto de C, que es un lenguaje de bajo nivel, ya suena raro. Sobre eso tenemos que mucha gente opina que no es un buen diseño de lenguaje, por diferentes razones: Por ejemplo, Jamie Zawinski dice "C++ es una abominación. Todo está equivocado en él de todas las maneras posibles", para seguir luego "cuando programas en C++ nadie puede ponerse de acuerdo en qué 10% del lenguaje es seguro usar. Siempre hay alguien que decide 'necesito usar plantillas'. Y acabamos descubriendo que no hay dos compiladores que implementen las plantillas de la misma forma".Las críticas cubren tres razones principales:
- el lenguaje es mucho más grande y complejo de lo necesario
- el problema de elegir que subconjunto se usa hace difícil la compatibilidad
- los mensajes de error cuando se usan plantillas son crípticos y complejos de usar
En las prácticas los dos primeros problemas son irrelevantes, ya que nuestro código es un callback al que el sistema llama repetidamente, lo que simplifica mucho el código. Sólo el último problema fue real, encontrando algunos errores relacionados con std::vector<float>, que usamos para recibir los valores del laser. Esos errores eran siempre extraordinariamente oscuros y difíciles de aislar, pero afortunadamente fueron pocos y en seguida pude localizarlos.
Gestión de versiones
El mayor problema, con diferencia, fue que el conjunto de versiones cambiaba continuamente. Para hacer una idea, empezamos con la versión 3.0 de introrob, y acabamos con la 3.8, pasando por todas las intermedias, si recuerdo bien. Normalmente esos cambios de versión eran por problemas en el código, y no eran importantes en sí, salvo que, al no tener el código de introrob (ni el mío, mea culpa) bajo control de versiones, tenía que pasar 30 minutos cada vez que entraba en el laboratorio inspeccionando el código nuevo, para ver si había cambiado algo en la parte que modificábamos nosotros, y luego mezclando el código nuestro en la nueva versión.Casi al final del proceso me di cuenta de que la solución habría sido poner yo bajo git las diferentes versiones de introrob que nos proporcionaban, en una rama tipo "vendor", y mezclarlas con mis modificaciones en ramas "practica1", "practica2", etc
Sin embargo la idea se me ocurrió tarde, cuando ya estábamos en la versión 3.8 y no llegué a implementarla.
Imposibilidad de desarrollar en mis equipos
Cuando probé la instalación en mis equipos, encontré un error: gazebo daba una "violación de segmento". Depurándola con gdb encontré que era en código de OpenGL. El profesor me confirmó que no tenía arreglo, y que pasaba en equipos con determinadas implementaciones de OpenGL. En mi caso un chip gráfico Intel.
Puesto que todos los ordenadores de casa tienen chips gráficos Intel de varias generaciones, cosa normal porque, no juego en el ordenador y desarrollo habitualmente para servidores y no he hecho programación gráfica desde hace la tana de años, resulta que no pude usar el entorno de simulación en mis máquinas, viéndome obligado a ir a los laboratorios linux en Móstoles cada vez que quería probar código.
martes, 12 de abril de 2011
La primera práctica, primeras impresiones
La primera práctica consiste en programar un comportamiento para el robot análogo a esos muñecos "Choca-gira" que detectan cuando chocan con un obstáculo, retrocediendo y girando al azar, para continuar avanzando después.
Una de las técnicas más sencillas para generar el comportamiento de un robot es la de los sistemas reactivos, que consiste en dividir nuestro "mundo", en situaciones mútuamente excluyentes, usando uno o más sensores y, para cada situación, disparar una o más acciones. Un robot reactivo consiste en una función, a la que se llama cada cierto tiempo, y en la que, dependiendo de valores de los sensores, se adopta un valor en los actuadores.
Para simplificar la lógica de los sistemas reactivos y sus "tablas" se adopta en un diseño "modular", en el que la lógica de nuestro robot es la de un autómata de estado finito. Para cada estado tendremos:
Nuestro Choca-gira tiene un diseño relativamente simple:
Una de las técnicas más sencillas para generar el comportamiento de un robot es la de los sistemas reactivos, que consiste en dividir nuestro "mundo", en situaciones mútuamente excluyentes, usando uno o más sensores y, para cada situación, disparar una o más acciones. Un robot reactivo consiste en una función, a la que se llama cada cierto tiempo, y en la que, dependiendo de valores de los sensores, se adopta un valor en los actuadores.
Para simplificar la lógica de los sistemas reactivos y sus "tablas" se adopta en un diseño "modular", en el que la lógica de nuestro robot es la de un autómata de estado finito. Para cada estado tendremos:
- un sistema reactivo simple diferente.
- lógica para cambiar de estado
Nuestro Choca-gira tiene un diseño relativamente simple:
- un estado "avanzando"
- en él la velocidad es hacia adelante
- cuando los láseres indican que estamos cerca de un obstáculo se pasa al estado "retrocediendo"
- un estado "retrocediendo"
- en él la velocidad es hacia atrás
- después de un tiempo, suficiente para separarnos algo del obstáculo, se pasa al estado "girando"
- un estado "girando"
- en él se gira aleatoriamente durante un tiempo
- después de completado ese tiempo se pasa al estado "avanzando"
viernes, 8 de abril de 2011
El entorno de las prácticas
Trabajamos en un entorno simulado con gazebo y JDErobot. En particular, usamos Introrob, un componente que visualiza información de los sensores y controla los actuadores del robot. Introrob usa JDErobot para comunicarse con gazebo. Gazebo es un simulador multirobot que nos permite simular un Pioneer2AT con pleno realismo, y proporciona un mundo en el que probar nuestros algoritmos.
Para lanzar el entorno se deben seguir los pasos siguientes:
Para lanzar el entorno se deben seguir los pasos siguientes:
- lanzar gazebo en el mundo de nuestra simulación. En una terminal hacer:gazebo /usr/local/share/gazebo/worlds/depar2.world
- lanzar gazeboserver para que introrob puedaa comunicarse con la instancia de gazebo. En otra terminal:
cd /usr/local/share/jderobot/glade/
LD_LIBRARY_PATH=/usr/local/lib/jderobot/lib gazeboserver --Ice.Config=../conf/gazeboserver.cfg - Compilar y lanzar introrob. En una tercera terminal:
cd ~/introrob-3.8
LD_LIBRARY_PATH=/usr/lib/gearbox make -f Makefile-introrob && ./introrob --Ice.Config=introrob.cfg
El directorio introrob-3.8 hace referencia al resultado de desempaquetar un tgz que descargamos del código fuente C++ de introrob. En él hay una clase, navega.cpp, que contiene el código de control. El entorno llama al método Navega::iteracionControl repetidamente. En ese método debemos actualizar los valores de los actuadores con información de los sensores.
lunes, 4 de abril de 2011
Arrancando este blog...
Uno de los requisitos de las prácticas de robótica del Master en Sistemas Telemáticos e Informáticos de la Universidad Rey Juan Carlos es que se documente nuestro trabajo en un blog.
Aproveché la ocasión para probar las facilidades de autoría de Blogger, en lugar de añadir otro blog al motor sobrecargado y poco mantenido que uso en memojo.com, tanto para el blog en español (El Agente Secreto) como para el blog en inglés (Boxes and Glue).
Esta entrada es para probar qué tal funciona el motor de Blogger antes de empezar a documentar en serio... seguiremos informando.
Aproveché la ocasión para probar las facilidades de autoría de Blogger, en lugar de añadir otro blog al motor sobrecargado y poco mantenido que uso en memojo.com, tanto para el blog en español (El Agente Secreto) como para el blog en inglés (Boxes and Glue).
Esta entrada es para probar qué tal funciona el motor de Blogger antes de empezar a documentar en serio... seguiremos informando.
Suscribirse a:
Comentarios (Atom)