Esta es mi primera incursión en la robótica. Objetivo: programar un robot que siga un circuito pintado en el suelo, basándose únicamente en la información visual.
![]() |
Figura 1: Robot Pioneer 2DX simulado en Gazebo. |
El robot a programar es un Pioneer 2DX con sistema de dos cámaras y sensor láser, aunque únicamente se utilizará una de las cámaras, la izquierda.
![]() |
Figura 2: Circuito de Montmeló simulado en Gazebo.
|
Las pruebas se realizarán en el simulador Gazebo, sobre una aproximación virtual del Circuito de Montmeló (Circuit de Barcelona-Catalunya).
Se programará sobre el código fuente del componente Introrob, que recibe los datos de los sensores simulados del robot y permite controlar sus actuadores, 8 veces por segundo.
PRIMER PASO: VISUAL
El primer paso consiste en extraer información visual de la escena, a través de la cámara del robot. Ya que el objetivo del robot es únicamente el de seguir un camino dibujado en el suelo, la información que se necesita es dónde está el camino. Es decir, se debe segmentar el trazado (separar los píxeles de la imagen que correspondan al trazado de los que no), y calcular sus coordenadas.
Para este caso bien acotado, está claro que lo que diferencia el trazado del resto de la imagen es su color, por lo que se realiza una segmentación de color. Se realiza sobre el espacio de colores HSV, que se ve mucho menos afectado por los cambios de iluminación que el espacio RGB por defecto (hay que tener en cuenta que incluso en este escenario acotado, se tienen sombras), por lo que la segmentación se hace en base a un umbral del canal H (hue, matíz). El análisis se hace fila a fila y pixel a pixel, cambiando el color de aquellos que pertenezan al trazado a un verde puro. Para propósitos meramente demostrativos, en la Figura 3 se han pintado también de azul todos los píxeles no pertenecientes al trazado.
Una vez segmentado el trazado de la imagen, hace falta calcular la posición del mismo, en este caso en coordenadas en píxeles (el punto (0,0) corresponde a la esquina superior izquierda de la imagen). El haber pintado los píxeles del trazado de verde no sólo permite una inspección visual de la segmentación realizada por el algoritmo, sino que también facilita encontrar los bordes de la línea, ya que se compara el color de un píxel con sus vecinos inmediatos en la fila, de modo que si un píxel es verde pero el anterior no lo era, pertenece al borde izquierdo del trazado, y si es verde pero el siguiente no, pertenece al borde derecho. Una vez se tienen los bordes del trazado, encontrar el centro del mismo es tan simple como sumar borde izquierdo con borde derecho y dividir entre dos. Cabe destacar que al no tratarse de un camino recto infinito, vamos a tener casos en los que el trazado desaparezca por uno de los laterales del campo de visión de la cámara, de modo que en la imagen falte uno de sus bordes, izquierdo o derecho. Para estos casos, realizaré el cálculo tomando el último pixel visible, el que toca con el borde de la imagen, como si fuese el borde del trazado.
También hay que tener en cuenta que se darán ocasiones en que aparezca más de un trazado en la imagen, como ocurre en la Figura 4. En estos casos, se calcularían varios centros de trazado. Se soluciona tomando únicamente el centro de trazado que más cerca esté del centro de la imagen. Ya que se asume que el robot viajará centrado en el camino, esto se cumple generalmente. Sin embargo, pueden darse casos en que una curva se desvíe de tal manera que uno de los bordes del otro trazado esté más centrado, y se utilice para calcular el punto central (véase el punto blanco aislado en la parte superior de la Figura 4). Pero esto son únicamente casos aislados, que además se dan únicamente en la parte superior de la imagen, cuyo uso, como veremos a continuación, es limitado.
![]() |
Figura 5: franjas en que se analiza la imagen. |
A partir de las coordenadas del centro del trazado obtenidas en estas franjas, se controla el robot. Veamos cómo.
SEGUNDO PASO: CONTROL
Ambas franjas tienen el mismo propósito, pero actúan en momentos diferentes. A partir de la información extraída de la primera franja (en la imagen, la de "arriba") se controla el comportamiento del robot en las situaciones generales. Analiza el tramo a cierta distancia, todavía por llegar, de manera que el robot tiene más tiempo para reaccionar y por tanto puede ir más rápido, y con una información más completa del trazado general de una curva.
La segunda franja (en la imagen, la de "abajo") analiza el tramo inmediatamente cercano, y sólo ejerce control cuando no se tiene información del trazado a partir de la primera franja, cosa que ocurre con curvas muy cerradas.
Para cada franja, se calcula una media del punto central del trazado. A partir de esta media se calcula un coeficiente C que representa la distancia de dicho punto central respecto al centro horizontal de la imagen (con una cierta corrección para compensar el hecho de que la cámara no esté en el centro del robot), y que será positiva o negativa dependiendo de si el giro es a derecha o izquierda. La velocidad y el giro del robot dependerán de este coeficiente, mediante un controlador proporcional. Como con todo controlador proporcional, determinar la ganancia correcta se ha realizado mediante experimentación, ajustándola hasta obtener la mayor velocidad posible sin que el robot se saliese del recorrido.
El comportamiento del robot se modela como un autómata de estado finito, con seis estados diferentes.
![]() |
Figura 6: esquema general del algoritmo. |
En el estado general, la primera franja contiene información sobre el camino y a partir de ella se ordena al robot avanzar a una velocidad de 80mm/s con una corrección negativa basada en C, de manera que contra más recto sea el trazado, más rápido irá (hasta el máximo de 80), y contra más pronunciada sea la curva, más despacio. Se ha establecido además una velocidad de giro proporcional, de manera que realice correctamente el trazado de las curvas, sin salirse por ninguno de los laterales.
Estado de Recta
Se ha definido una recta como un tramo en el cual el punto central medio de ambas franjas se sitúa en el centro de la imagen (con un margen de unos pocos píxeles) y se mantiene durante al menos 10 ciclos. En los casos en que se detecte una recta, el robot pasa al estado Recta y acelera hasta una velocidad de 90mm/s. Más allá de eso, he comprobado que el robot iría a una velocidad demasiado alta para poder detectar una curva y frenar a tiempo, más aún en este circuito, cuyas rectas terminan en curvas cerradas. Se utiliza la misma velocidad de giro proporcional que en el estado general, que funciona perfectamente para corregir ese margen de pocos píxeles y realizar los pequeñísimos ajustes que puedan darse en una recta. Este estado se abandona cuando el tramo deja de ser recto, es decir, se detecta una posible curva, y se pasa al estado de Frenado.
Estado de Frenado
Si estando en el estado Recta se detecta una curva, no basta con resumir el estado general, pues no se corregiría a tiempo la elevada velocidad del robot. Se establece una etapa de frenado de una duración de 5 ciclos desde que se detectó la curva, tras lo cual este estado se abandona. Dependiendo de la información de los sensores pasará a cualquiera de los otros estados, aunque, como ya he dicho, en este circuito las rectas terminan en curvas cerradas y por tanto por norma general pasará al estado de Curva Cerrada.
Estado de Curva Cerrada
En los casos en que la primera franja no detecta la línea, la velocidad lineal se ha reducido drásticamente a 10mm/s con corrección negativa basada en C, porque este estado se alcanza cuando el robot se halla al principio de una curva muy cerrada, que debe tomarse despacio (si bien este estado puede darse también si el robot se inicializa lejos del trazado). En cuanto a la velocidad de giro, parecería que ya que la velocidad lineal es baja, se podría aumentar la velocidad de giro para realizar la curva más rápido, pero la experimentación me ha enseñado que, de hacerlo así, en cuanto la primera franja volviese a tomar el control, se crearía un efecto de sobrecompensación que haría que el robot girase demasiado y se saliese momentáneamente del trazado, por lo que la velocidad de giro también es baja y las curvas cerradas, aunque correctamente, se toman con lentitud.
Estado de Búsqueda
Otro caso que hay que tener en cuenta es qué debe hacer el robot si no encuentra la línea. Siempre hay que tener este tipo de situaciones en cuenta, por muy bien que realice su labor el robot de normal, si uno no quiere enfrentarse a que el robot se quede quieto, inútil, o peor aún, viaje sin rumbo hasta estrellarse. En este caso, he programado el robot de manera que si no encuentra el trazado en ninguna de las dos franjas, detenga su velocidad lineal por completo, y empiece a girar sobre si mismo, en la misma dirección en que giró por última vez antes de perderse. Los casos más generales en que el robot puede perder el trazado por completo es en una curva, y por subviraje, o al final de una recta, por no frenar lo suficiente rápido. Para las velocidades y tiempos de reacción con que trabaja este robot, se detiene nada más perder la línea, por lo que si gira sobre sí mismo, la volverá a encontrar. Y haciendo que gire en la misma dirección en que giró por última vez, caso de haberse perdido en el transcurso de una curva, volverá al recorrido en la dirección correcta, evitando que pueda volverse por donde ha venido. Este estado se abandona cuando cualquiera de las dos franjas detecta el trazado, y se pasa al estado de Vuelta al Camino.
Estado de Vuelta al Camino
La vuelta al camino se hace a velocidades lineal y de giro bajas, para evitar comportamientos oscilatorios. Una vez que se detecta que el robot está centrado en el camino (respecto a cualquiera de las dos franjas), se abandona este estado y, dependiendo de si la franja 1 detecta o no camino, se volverá al estado de Avance o de Curva Cerrada.
RESULTADOS
En el siguiente vídeo se muestra el robot en funcionamiento:
Cabe decir que el comportamiento del simulador Gazebo depende mucho del equipo con que se trabaje. El vídeo se ha grabado a partir de un ordenador portátil core i5 con 8gb de RAM y tarjeta gráfica Nvidia Geforce 720M. Así mismo, el programa utilizado para grabar el vídeo a afectado al rendimiento, puesto que en un recorrido sin dicho programa ni ningún otro proceso funcionando, se consigue un tiempo de vuelta mejor, de aproximadamente 1:55 min.