Práctica primera sobre sistemas reactivos

Buenas tardes,

a través de este post intentaré explicar mi experiencia con la práctica primera que emplea JDERobot, el framework desarrollado por el departamento de Robótica de la URJC y que sirve como nexo práctico con el mundo de la robótica móvil.

Introducción

La práctica primera tiene como objeto desarrollar un robot móvil reactivo el cual tenga que realizar 3 comportamientos en su ejecución:

  • Un comportamiento de avanzar
  • Un comportamiento de retroceder
  • Un comportamiento de giro

Para ello desarrollaremos una programa empleando una plantilla que nos proporciona el profesor y sobre ella desarrollar la logica.

Con JDERobot es posible desarrollar logica desacoplada separando la parte de control de la parte grafica. Esta particularidad puede estar bien para programas sencillos pero para logicas complicadas puede ser engorroso. En la primera practica no hubo falta, pero en la segunda practica si me estoy encontrando con particularidades. Desde un punto de vista de ingeniería, el desacoplar tiene que ser una decisión del desarrollador, no del framework.

Con respecto al año pasado, el entorno de desarrollo esta mucho mejor explicado y la instalación es muy sencilla a través de un paquete Debian, pero la documentación es muy escasa no como ocurre con ROS. De todas formas el salto de C a C++ se nota mucho. Estaría muy bien tener un ejemplo del uso de Java y ver la potencia de ICE.

Los puntos negativos del entorno de practicas que veo este año son:

Versión de Gazebo antigua: Actualmente estamos usando una versión antigua de Gazebo
Problemas de 2D en entornos 3D: ¿Por que para hacer estas practicas no usamos un entorno 2D ? Existen soluciones 2D como Player/Stage que bien vendrían. Lo importante es el algoritmo que aprendemos y las ideas de diseño y no el middleware y para el tipo de problema que se usa, es posible emplear otras alternativas como por ejemplo Javaclient3 o usar Gazebo desde ROS. Ademas, el modelo de robot que se emplea es un Pioneer pero para comprender los conceptos teóricos, podríamos emplear cualquier modelo de robot que tenga un sistema de navegación diferencial. en ROS existe la posibilidad de usar diferentes lenguajes de programación para crear nodos.

La practica.

A través del ejemplo introrob3.6 se editara el fichero navega.cpp donde añadiremos nuestra lógica. En este caso la programación es iterativa de tal manera que cada vez que se ejecuta el bucle de control del robot, el sistema evaluara en que estado esta y tomara acciones.

En este curso empleamos C++ que tiene la capacidad de desarrollo orientado a objetos como Java. El desarrollo se baso en:

  • Conocer como funciona el objeto de tipo robot y conocer las funcionalidades básicas de avance, giro y orientación.
  • Diseño de los estados
  • Manejar el concepto de tiempo

La solución que se presenta es muy sencilla y tiene parámetros personalizables para la ejecución del robot:

INICIO BLOQUE

int estadorobot = 1;
 //1. Avanzar
 //2. Retroceder
 //3. Girar

 int contador = 0;

 CvPoint3D32f myPoint;    

 int random_integer = 0;

 int orientacionInicial = 0;
 int orientacionActual = 0;
 int orientacionFinal = 0;

//Parametros
 float avance = 600.0;
 float retroceder = -500.0;
 float girar = 5.0;

 //Avanzar
 if(estadorobot == 1){
 std::cout << "Avanzar \n";

 //Leer laser
 numLasers = this->navegacion->cogerLaser(&laser);

 valorCentral = laser[90];
 std::cout << "OBSTACLE: ";
 std::cout << valorCentral;
 std::cout << "\n";

 if(valorCentral > distanciaMinima){
 //Caso avanzar
 this->controller->setV(avance); // mm./s.
 this->controller->setW(0.); // deg./s.
 }else{
 //Caso Parar
 this->controller->setV(0.); // mm./s.
 this->controller->setW(0.); // deg./s.

 //Ir al caso 2
 std::cout << "Parar. Ir a estado2 ";
 estadorobot = 2;
 }
 //Retroceder
 }else if(estadorobot == 2){
 std::cout << "Atras \n";

 //Caso retroceder
 this->controller->setV(retroceder); // mm./s.
 this->controller->setW(0.); // deg./s.

 contador++;

 if(contador > 50){
 contador = 0;
 std::cout << "Parar. Ir a estado3 ";

 random_integer = (rand()%360)+1;

 this->navegacion->cogerPosicion(&myPoint);
 orientacionInicial =  myPoint.z;

 orientacionFinal = orientacionInicial + random_integer;

 if(orientacionFinal > 360){
 orientacionFinal = orientacionFinal - 360;
 }

 //Ir a estado 3
 estadorobot = 3;
 }
 //Girar
 }else if(estadorobot == 3){
 //std::cout << "Girar \n";

 std::cout << "Inicial: ";
 std::cout << orientacionInicial;
 std::cout << "\n";

 this->navegacion->cogerPosicion(&myPoint);

 orientacionActual = myPoint.z;
 std::cout << "Actual: ";
 std::cout << orientacionActual;
 std::cout << "\n";

 std::cout << "Final: ";
 std::cout << orientacionFinal;
 std::cout << "\n";

 std::cout << "Random: ";
 std::cout << random_integer;
 std::cout << "\n";

 if(orientacionActual == orientacionFinal){

 std::cout << "Parar\n";
 this->controller->setV(0.); // mm./s.
 this->controller->setW(0.0); // deg./s.

 //Ir a estado 1
 estadorobot = 1;
 }else{
 std::cout << "Girar\n";
 this->controller->setV(0.); // mm./s.
 this->controller->setW(girar); // deg./s.
 }

 }else{
 std::cout << "Estado desconocido \n";
 std::cout << estadorobot;
 std::cout << "\n";
 std::cout << contador;
 std::cout << "\n";
 } 

FIN BLOQUE

Como se observa el desarrollo emplea un Láser SICK para detección de obstáculos en vez de sistemas mas sencillos como un anillo de sensores de ultrasonidos por ejemplo. En este ejemplo, el sistema tiene en cuenta un angulo en concreto y si detecta un obstáculo cambia de estado.

Como se observa, la solución se basa en un FSM, una maquina de estados finita. Las maquinas de estado finito están muy bien para estas soluciones, pero si el problema crece es interesante emplear HSM, maquinas de estado con jerarquía y mejor aun las CHSM que permiten concurrencia en los comportamientos.

Actualmente estoy probando soluciones CHSM con Java y el paquete Smach de ROS.

http://chsm.sourceforge.net/

http://crasnopolski.com/alpha/javaDPP.htm

http://www.ros.org/wiki/smach

Las soluciones presentadas se basan en los trabajos de Miro Samek que presenta su solución en el libro “Practical UML Statecharts in C/C++, Second Edition”

http://www.state-machine.com/doxygen/qpcpp/index.html#PSiCC2

Conclusiones de la practica

La práctica me ha permitido reforzar los conceptos sobre máquinas de estado finito y descubrir sus límites.

La investigación me ha permitido encontrar el concepto de jerarquías de comportamientos y el trabajo que existe con jearquías, UML y sistemas de tiempo real. En la investigación, he encontrado diferentes soluciones, pero todas ellas se basan en el trabajo de Samek. He encontrado que ROS dispone del paquete Smach y el uso de los grafos de nodos es muy interesante.


Por otro lado, no me parece correcto que tengamos que compilar muchas veces la práctica por que hay cambios en el ejemplo base introrob que pasamos de una versión inicial a la versión 3.6. Esto quita tiempo para comprender conceptos en la materia. Creo que se podría mejorar las prácticas empleando Scripting sobre los engines de simulación directamente y no usar JDERobot que normalmente es la fuente de las dudas del foro de la asignatura. De todas formas del año pasado a este año, las prácticas han mejorado mucho, pero existen muchas dudas teóricas que los alumnos tenemos que solventar a base de horas cuando un PDF lo podría resolver.

Espero que la segunda practica sobre VFF vaya todo mas rodado.

http://www-personal.umich.edu/~johannb/vff&vfh.htm

Leave a Reply

Spam Protection by WP-SpamFree