PRÁCTICA 1. INTRODUCCIÓN AL SIMULADOR DE
ENTORNOS
0 Objetivos de la práctica
Los objetivos de la práctica son:
• Entender cómo se usa el simulador a nivel de instalación, arranque, carga de entornos
y simulación.
• Aprender a programar comportamientos de robots para ser simulados
• Entender completamente la cinemática diferencial
1 Primer contacto con el simulador
En las siguientes subsecciones se pretende cubrir el primer objetivo de la práctica. Por ello,
hasta que no se entienda perfectamente esta sección no se puede pasar a la siguiente.
Adicionalmente a lo que se explica en esta sección en la web se encuentra una documentación
más detallada sobre el simulador "Manual de usuario del simulador".
1.1 Instalación
Para ello hay que bajarse de la página web el fichero simulador.zip y descomprimirlo en la
unidad local de cada grupo, en un directorio llamado simulador (ejemplo:
d:\robots\simulador\).
1.2 Arranque
Una vez hecho instalado el simulador, para hacer una simulación es necesario seguir los
siguientes pasos:
• Ejecutar el programa simulador.exe.
• Cargar el entorno entornofacil. Entornos->Cargar entornos.
• Cargar el robot móvil robot_ideal. Entornos->Añadir obstáculo móvil. Elegir
robot_ideal y escribir dllsencilla.dll en el cuadro de texto “dll asociada”.
• Situar el robot en el entorno. Hacer doble clic sobre el robot y situarlo en las
siguientes coordenadas: orientación = 180, posición X = 30, posición Y = 12.
• Comenzar la simulación. Simular->Empezar.
• Parar la simulación. Simular->Parar.
• Para que la simulación sea más rápida, cambiar el tiempo de muestreo a medio
segundo. Simular->Intervalo simulación y escribir 500 en el cuadro de texto que
aparece.
• Empezar la simulación. Simular->Empezar.
Sistemas Electrónicos Digitales.
•
Parar la simulación. Simular->Parar.
De esta manera se ha realizado una simulación usando el entorno entornofacil y el robot
robot_ideal con el comportamiento definido en dllsencilla.
El robot_ideal tiene los siguientes sensores, ver Figura 1, (como se verá más adelante el orden
importa): 8 sensores de distancia, una brújula, un GPS (sistema de posicionamiento global) y
dos encoder, uno en cada motor. Los sensores de ultrasonido se emplean para reconocer los
obstáculos del entorno, el GPS con la brújula se usa para poder saber cuál es la posición y
orientación del robot, y los encoders sirven para estimar la posición y orientación del robot
usando odometría. Cada encoder indica en valor absoluto el desplazamiento que ha sufrido
una rueda. Tiene dos actuadores que son el motor de corriente continua m1 y m2. Según el
sistema de referencia que se muestra en la Figura 1, la situación del motor m1 se corresponde
con una orientación de -90º, en cambio la orientación del motor m2 se corresponde con 90º.
Esta descripción también se puede ver en el simulador en Configuración->Robots->Tipos de
robots. Hacer doble clic sobre robot_ideal. ¿cuánto mide el diametro del robot?
Ultrasonido (u1)
Ultrasonido 64º (u2)
Ultrasonido (u3)
m2
GPS
Brújula
Ultrasonido 13º (u4)
(b)
Ultrasonido -13º (u5)
m1
Ultrasonido (u6)
Ultrasonido -64º (u7)
Ultrasonido (u8)
Figura 1: descripción del robot_ideal
Para analizar a simple vista qué mide cada sensor se puede hacer lo siguiente:
• Para que la simulación sea lenta, cambiar el tiempo de muestreo 2 segundos. Simular>Intervalo simulación y escribir 2000 en el cuadro de texto que aparece.
• Empezar la simulación. Simular->Empezar.
• Hacer doble clic sobre el robot y analizar las medidas que aparecen en pantalla (a lo
mejor es necesario hacer la ventana un poco más grande para que se vean todas las
medidas). ¿qué sistema de referencia usan las medidas?, ¿qué significa cada medida?,
etc.
• Parar la simulación. Simular->Parar.
1
Sistemas Electrónicos Digitales.
2 Primer contacto con la DLL que define el comportamiento de un
robot
Una vez que se ha aprendido a hacer una simulación, el siguiente paso consiste en
personalizar los comportamientos de los robots. Para ello hay que entender qué es una DLL
(como lo es dllsencilla.dll), y cómo se programa la DLL que necesita el simulador para
entender lo que hace un robot y así poder integrarlo en la simulación.
2.1 Introducción a las librerías dinámicas (DLL)
Las librerías dinámicas son librerías en código máquina directamente interpretables por el
sistema operativo igual que un ejecutable. La diferencia con un ejecutable es que una librería
no se puede ejecutar por sí sola, sino que necesita de un programa ejecutable que la cargue.
En esta práctica se van a utilizar librerías dinámicas para definir el comportamiento de robots
en un simulador. De esta manera el alumno podrá comprobar las ventajas que tienen las
librerías dinámicas:
• Permite añadir código a un programa ejecutable y por ello es independiente del
compilador y del lenguaje de programación usado para generar el ejecutable o la
librería dinámica.
• Permite la reutilización de código, al igual que cualquier otra librería, pero con la
diferencia de que se puede reutilizar código generado con cualquier lenguaje de
programación y compilador.
• Depurar una librería dinámica es más fácil que depurar toda una aplicación. Como
siempre el principio de divide y vencerás prevalece.
En cualquier caso cualquier librería dinámica es dependiente del sistema operativo, en
Windows las librerías dinámicas tienen extensión DLL y en Linux tienen extensión O.
La creación de una librería dinámica no es igual que la creación de un programa. La
diferencia fundamental es que no hay un main, ya que no se puede ejecutar directamente y
necesita una aplicaciónn que la cargue. La aplicación cargadora de la librería dinámica en esta
práctica va a ser el simulador de robots Simulador.exe. Lo único que necesita saber una
aplicación cuando usa una DLL es su interfaz; es decir, la declaración de las funciones que
tiene que usar.
2.2 La librería dinámica que define el comportamiento de un robot
Cuando un programa maneja una DLL, sabe el contenido de la misma. Esto viene definido
por el interfaz que presenta la DLL con exterior. En concreto el interfaz que tiene la DLL, que
define el comportamiento de un robot para el simulador, está formado por las funciones
siguientes:
void
__stdcall
iMedidas)
InicioSimulacion(float*
pfMedidas,
int
Esta función es invocada por el simulador en el momento que comienza la simulación. Es un
buen lugar para poner el código encargado de abrir ficheros y de inicializar variables. El
simulador da a la función el conjunto de medidas generadas por los sensores justo antes de
2
Sistemas Electrónicos Digitales.
comenzar la simulación, en pfMedidas que es un puntero a un vector de iMedidas
elementos. Este vector contiene las medidas en el orden en el que se definieron los sensores
del robot; como se comentó en las secciones anteriores el orden de definición de los sensores
importa para saber en qué posición de este vector viene cada medida. Para el robot
robot_ideal, estas medidas son:
• Medida de los sensores u8, u7, u6, u5, u4, u3, u2, u1. (pfMedidas[0] hasta
pfMedidas[7]) (¡Ojo al orden!). El valor de la medida es –1 si el obstáculo más
cercano se encuentra fuera del rango de medida del sensor.
• Medidas exacta de la coordenada X (pfMedidas[8])
• Medida exacta de la coordenada Y (pfMedidas[9])
• Medida exacta de la orientación (pfMedidas[10]) ¡Ojo en grados no en
radianes!. Para convertir usar #define PI 3.14159265358979.
• Medida exacta del desplazamiento de la rueda correspondiente al motor m1 y m2,
pfMedidas[11] y pfMedidas[12] respectivamente (¡Ojo el desplazamiento
siempre es positivo aunque la rueda vaya para atrás!, usar el mando aplicado a
un motor en el instante anterior para saber si el desplazamiento es positivo o
negativo).
void __stdcall FinSimulacion(void)
Esta función es invocada por el simulador en el momento que termina la simulación. Es un
buen lugar para poner el código encargado de cerrar ficheros.
void __stdcall Inicializa(void)
Esta función se llama cuando el robot se pone en el simulador Entornos->Añadir obstáculo
móvil. Se suele usar para crear objetos y reservar memoria.
void __stdcall Finaliza(void)
Esta función se llama cuando el robot se quita del simulador Entornos->Eliminar obstáculo
móvil. Se suele usar para borrar objetos y liberar memoria.
void __stdcall CalculaMando(float*
float* pfMandos, int iMandos)
pfMedidas,int
iMedidas,
Esta función es llamada en cada ciclo de simulación. El simulador da a la función el conjunto
de medidas generadas por los sensores y espera recibir la información de los mandos que debe
aplicar a los servos de los motores en pfMandos, que es un puntero a un vector con
iMandos elementos que debe rellenar el comportamiento del robot para que se mueva. El
motor m1 se comanda con pfMandos[1] y el motor m2 se comanda con pfMandos[0].
3
Sistemas Electrónicos Digitales.
Ya se ha usado la DLL dllsencilla en la sección anterior. El código de esta librería se
encuentra en la web, fichero dllsencilla.zip en Proyecto DllSencilla. Descomprimir este
archivo en el directorio local de cada grupo, por ejemplo d:\robots\. De esta manera se crea un
directorio llamado Dllsencilla donde se guarda el proyecto.
A continuación se va a hacer un ejercicio de depuración de la librería:
• Copiar los ficheros del simulador menos Simulador.exe y dllsencilla.dll al directorio
donde está el proyecto. Esto es necesario porque cuando se depura el directorio de
ejecución para el simulador es donde está el proyecto, lugar donde deben estar todos
los ficheros para inicializarlo.
• Abrir el proyecto dllsencilla.vcproj recientemente descomprimido con el Microsoft
Visual C++.
• Indicar al compilador qué aplicación carga la librería. Ir a Proyecto>Propiedades, elegir Propiedades de configuración, categoría Depuración (en
configuración: Active(Debug)) y rellenar el cuadro de texto que indica Comando
navegando hasta d:\robots\simulador\simulador.exe usando el botón para este
menester.
• Poner un breakpoint en la librería. Seleccionar el fichero donde está el código
principal de la librería, en Explorador de soluciones->SourceFiles->dllsencilla.cpp.
Situar un breakpoint en la función CalculaMando:
• Ponerse encima de la línea Navegador->Navega(pfMedidas,
pfMandos)
• Pulsar botón derecho del ratón
• Seleccionar Punto de interrupción->Insertar Punto de interrupción
• Poner un breakpoint en la función InicioSimulacion, Inicializa y
Finaliza.
• Ejecutar el programa. Seleccionar Depurar->Iniciar Depuración o pulsar la tecla
F5.
• Cargar el entorno entornofacil. Entornos->Cargar entornos.
• Cargar el robot móvil robot_ideal. Entornos->Añadir obstáculo móvil. Elegir
robot_ideal y escribir d:\robots\Dllsencilla\Debug\dllsencilla.dll en el cuadro de texto
“dll asociada” (alternativamente se puede utilizar una ruta local del estilo de
..\dllsencilla\debug\dllsencilla.dll referida a la ruta del simulador). ¡Ojo que la DLL
que se va a usar no está en el directorio del propio simulador y por ello es
necesario poner toda la ruta de directorios!. En este paso debería haber saltado el
breakpoint de la función Inicializa. En el menú Debug o en la barra de
herramientas Debug, se encuentran los típicos comandos para depurar. En este caso se
va a pulsar F5 para que continue la ejecución, ver Figura 2.
• Situar el robot en el entorno. Hacer doble clic sobre el robot y situarlo en los
siguientes coordenadas: orientación = 180, posición X = 30, posición Y = 12.
• Comenzar la simulación. Simular->Empezar. En este paso debería haber saltado el
breakpoint de la función InicioSimulación. Pulsar F5 para que continue la
ejecución.
4
Sistemas Electrónicos Digitales.
•
•
A los dos segundos debe saltar el breakpoint de la función CalculaMando.
Experimentar con las herramientas de debug, para depurar por dentro de la función
Navega.
Cuando se quiera parar de depurar, quitar el breakpoint, pulsar F5 para continuar la
ejecución, ir al simulador y parar la simulación, quitar el robot del entorno (ojo esto
hará saltar el breakpoint de la función Finaliza, pulsar F5 para continuar) y
finalmente salir del mismo. Existe un método más radical que es Depurar->Finalizar
todo, pero tiene el problema de que el comportamiento no termina de forma normal,
ya que no se ejecuta ni la función FinSimulación ni Finaliza.
Figura 2: Ventanas de depuración
3 Cinemática diferencial
Partiendo del proyecto de la sección anterior; es decir, aprovechando el algoritmo de
navegación, hacer un programa que estime la pose del robot (X, Y, orientación respecto del
sistema de referencia global situado en la esquina superior izquierda de la pantalla) usando las
medidas de los encoders situados en las ruedas del robot. Tanto la estimación anterior de la
pose, como la pose real del robot medida por el GPS y la brújula ideal, se deben guardar en un
fichero. Comprobar que la estimación coincide con los valores reales.
3.1 Pistas para terminar antes
• Tenga en cuenta que el ángulo que da el simulador va en grados y los senos y cosenos
necesitan radianes.
• Tenga en cuenta que hablar de desplazamiento y de velocidad en el simulador es lo
mismo, ya que los incrementos de tiempo son constantes.
5
Sistemas Electrónicos Digitales.
•
•
•
Cuando un encoder mide 8. ¿qué significa? pues depende, pueden ser 8 km, 8 cm, 8
km/h, 8 m/s, según se quiera. Lo que sí que es claro es que si se elige que 8 signifique
8 cm, entonces el robot medirá de ancho 40 cm.
Tenga en cuenta que los encoders indican el desplazamiento de una rueda en valor
absoluto.
No se olvide de inicializar las variables.
3.2 Pistas para escribir en un fichero
En C++ la información se envía a ficheros usando el operador << . Ejemplo:
#include <fstream>
...
std::ofstream
f("c:/nombre_fichero.txt”,std::ios::app);
if (!f.fail()) { // si se puede abrir
f << " i: " << i << std::endl;
f << " d: " << d << std::endl;
f << "Adios" << std::endl;
}
...
4 Sistematización!!!
Cada vez que se quiera empezar un proyecto para generar un comportamiento del robot:
•
•
•
Se partirá del proyecto DllSencilla que está en la web.
Se copiará a un directorio dedicado al problema que se quiera resolver.
Se copiarán los ficheros de configuración del simulador al directorio del proyecto.
Es importante darse cuenta de que hay que tener todo perfectamente organizado, debe llevarse
un control exhaustivo de versiones y se debe aplicar cualquier otro procedimiento que ayude a
trabajar de forma eficiente y ordenada. ¡Nada de desorden!, y ¡estableced un método de
trabajo, con procedimientos adecuados para trabajar en equipo!
5 Ejercicio opcional para aquellos que les sobre tiempo
Hacer un algoritmo de navegación por el entorno que consista en que el robot no se choque.
Si el comportamiento del robot no evita que el robot se choque, el robot se puede salir del
6
Sistemas Electrónicos Digitales.
entorno ya que el simulador lo permite; es decir, si el comportamiento lo requiere el robot
puede pasar por encima de una pared, ya que esto aumenta la flexibilidad del mismo.
Evidentemente se deben borrar del proyecto Dllsencilla las líneas de código que tienen que
ver con el procedimiento de navegación que viene en la misma.
7