Está en la página 1de 15

ENTORNO DE SIMULACIN DE CARRERAS DE COCHES: RARS

Antonio Aldea Gmez, Cristina Romero Barbado


Departamento de Ingeniera Telemtica Universidad Carlos III de Madrid Madrid, Espaa {100033997, 100039768}@alumnos.uc3m.es

ABSTRACT
En este paper se estudia el uso de un sistema experto para la conduccin de automviles por medio del simulador RARS, as como el desarrollo de un coche de ejemplo.

en cuenta la informacin suministrada por el usuario y la informacin almacenada en al base de conocimiento, otro de los componentes caractersticos de un sistema experto El usuario accede y establece comunicacin, es decir un dilogo, con el sistema experto a travs del interface de usuario.

Categora
Experimentacin.

1. INTRODUCCIN
Este proyecto est planteado desde el punto de vista de un sistema experto. Utilizando el simulador grfico RARS, hemos desarrollado un coche de ejemplo que en base a un conocimiento es capaz de recorrer distintos escenarios. Un sistema experto es una aplicacin informtica que procura capturar conocimiento y luego utilizarlo para emular el mecanismo de raciocinio de un experto humano, para la resolucin de problemas concretos. Esto se logra automatizando su procedimiento de toma de decisiones. Es decir, los creadores de sistemas de este tipo analizan no slo lo que un experto sabe, sino adems la manera en que resuelve problemas, con el fin de tratar de replicar ese proceso artificialmente. Un sistema experto est constituido por distintos componentes, relacionados entre s de acuerdo al siguiente esquema:
Base de Conocimiento

2. DETERMINACIN DE LOS OBJETIVOS


El fin de este proyecto es ilustrar cmo funciona un sistema experto. Para ello hemos desarrollado un coche al que le hemos dotado de unos conocimientos que le permiten comportarse de una forma u otra segn en la situacin en la que se encuentre dentro de un circuito de carreras. Para ensear al coche, hemos estudiado los casos posibles en los que podra encontrarse (curvas, rectas, etc.), y las mejores respuestas que podra tener. El lenguaje de programacin que hemos utilizado para disear nuestro prototipo es C++. Para poder simular el comportamiento de nuestro coche hemos utilizado el simulador grfico RARS, un simulador de cdigo libre, que nos permite disear el comportamiento de nuestro coche de manera relativamente sencilla. RARS nos propone un modelo fsico que describe el comportamiento del vehculo, y nosotros hemos implementado la lgica de operacin. Toda la parte de representacin grfica vena facilitada por el simulador, por lo que nuestro trabajo se ha centrado en ensearle reglas a nuestro coche para que corriera de forma eficaz y competitiva.

Motor de inferencia Base de Hechos

Interfaz De usuario

USUARIO

Figura 1-1. Esquema Sistema Experto


El motor de inferencia es el elemento principal, siendo el componente encargado de la simulacin del razonamiento. Por consiguiente, es el elemento que obtiene un resultado o conclusin a partir de un proceso de deduccin en el que se tiene

3. SIMULADORES DE COCHES DE CARRERAS EN LA ACTUALIDAD


Aunque los primeros simuladores grficos aparecieron en la segunda mitad del siglo XX, fue en la dcada de los 80 cuando experimentaron su mayor desarrollo. Actualmente existen gran cantidad y variedad de simuladores que atienden a diferentes propsitos: simuladores de vuelo

(Microsoft Flight Simulator, X-Plane, etc.), de trenes (Trainz, BVE, etc.), de la vida (Sims, Spore, etc.), de juegos (golf, ftbol, coches, tenis, etc.). En el caso que nos ocupa, nos centraremos en el estudio de simuladores de juego, y en concreto en simuladores de automovilismo. Pasamos a describir los principales simuladores grficos disponibles hoy en da.

Aunque la gran capacidad grfica y el modelado de los coches que permite TORCS nos hizo inclinarnos por su eleccin como simulador a utilizar, tuvimos que desechar la idea ya que no conseguimos solucionar los problemas surgidos con ciertas libreras al intentar instalar su software. Adems, como este simulador funciona solamente bajo Linux, esto tambin nos gener bastantes complicaciones a la hora de intentar configurar la tarjeta grfica para que soporte esa aceleracin grfica.

Vamos Automotive Simulator


http://vamos.sourceforge.net/ Vamos es un simulador de carreras que pone especial nfasis en el modelado fsico. Otra de sus caractersticas principales es que tiene un buen diseo en C++. Adems, incluye una aplicacin de conduccin 3D en tiempo real que permite experimentar con la simulacin. Su principal propsito es comportarse como banco de pruebas para ciertas libreras, luego realmente no est pensado como aplicacin de usuario final. Por eso hemos descartado el uso de Vamos para desarrollar nuestro trabajo.

RACER
http://xracer.sourceforge.net/ Racer es un proyecto de simulacin de coches de plataforma cruzada para uso no comercial. Utiliza los modelos fsicos de los coches profesionales para conseguir aumentar el realismo. Los coches y los circuitos pueden ser creados de manera relativamente sencilla. El simulador presta especial atencin al aspecto fsico, intentando crear coches cuyo comportamiento se ajuste fielmente a la realidad, es por ello que tambin desechamos esta opcin en favor de RARS, que ofrece un buen compromiso entre realismo y simplicidad.

T1 Car Racing Simulation


http://t1-crs.sourceforge.net/
T1 Car Racing Simulation es un juego de automovilismo en

3D de cdigo libre diseado para ser utilizado tanto en plataformas Linux como Windows usando la capa de la emulacin de Cygwin. T1 Car Racing Simulation ha sido ideado para ser un juego divertido, no para ser un diseo excepcional en su modelado fsico. Por eso tambin hemos descartado este simulador, porque queramos que nuestro trabajo fuera probado en un entorno lo ms realista posible.

4. EL SIMULADOR RARS: ROBOT AUTO RACING SIMULATOR 4.1 Descripcin de RARS.


El Robot Auto Racing Simulator (RARS) fue originalmente diseado y desarrollado por Mitchell E. Timin en 1995. Esta es la descripcin que Timin incluy en el anuncio original: El Robot Auto Racing Simulation (RARS) es un simulador de carreras de coches en el que los coches son conducidos por robots. Su propsito es doble: servir como vehculo para el desarrollo de la Inteligencia Artificial y permitir que desarrolladores de software puedan competir. Es un software libre. Desde el momento de su creacin el simulador ha estado sujeto a continuo desarrollo. RARS consiste en una simulacin fsica del comportamiento de un coche de carreras en un circuito. Se dispone de una serie de variables de entrada comunes propias del circuito (situacin actual del coche en la pista con todas sus variables: longitud del tramo, radio del tramo), que cada coche recibe, las interpreta de alguna

TORCS
http://www.racer.nl/ TORCS (The Open Racing Car Simulator), es un simulador en 3D de carreras de coches que permite competir en carreras contra oponentes simulados por ordenador. El inters principal es desarrollar conductores inteligentes, robots", que compitan en el juego. En TORCS hay 42 coches diferentes, 30 circuitos y ms de 50 oponentes contra los que competir. Las caractersticas del simulador incluyen un modelo simple de daos, colisiones, propiedades de las ruedas y los neumticos (presin, rugosidad, pinchazos...), aerodinmica ("ground effect", spoilers...), etc. Se trata de un simulador con grandes capacidades grficas. Los robots se desarrollan en C/C++ utilizando una API proporcionada por el simulador.

manera y segn el algoritmo utilizado proporciona unas variables de salida propias del coche (velocidad y direccin).

Los resultados de estas primeras carreras dieron como vencedores a los siguientes participantes: Randy Saint - Ramdu (Texas) Jussi Pajala - WappuCar (Finlandia, Wappu = Mayday) Mike Inman - Indretti (Florida) Safai Ma - Burns (Canad) Bill Benedict - Rusty (E.E.U.U., del Rose-Hulman Tech) Grant Reeve - Grant1 (Nueva Zelanda) Oscar Gustavsson- OscCar2 (Suecia) Tristrom Cooke - Bingo (Australia) Patrick Tierney - Heath (Australia) En los ltimos aos los coches han mejorado mucho gracias a la utilizacin de algoritmos genticos, redes neuronales, autoaprendizaje, etc.

4.2 Historia de RARS.


La Historia de RARS (Robot Auto Racing Simulator) comienza en 1995 gracias a Mitchell Timin cuando el 30 de Abril se celebr un meeting en el que los participantes enviaron sus robots a una direccin de Internet programados en ANSI, C o C++. Se utiliz la versin de RARS 0.50. Los coches que producan errores de compilacin (Borland 3.1) o daban errores producidos por otros participantes eran descalificados. Por esta razn, a pesar de haber una fecha lmite para participar, todos los robots estaban listos con muchos das de antelacin. Los concursantes optaban a tres premios: - El primer premio era el software "Street Wizard 5.0", que era un buscador de mapas y direcciones. - El segundo premio era un libro de Mark Watson's McGraw-Hill titulado "C++ Power Paradigms", en el cual se habla de algoritmos genticos, redes neuronales, etc. - El tercer premio era otro libro de Mark Watson's Springer-Verlag llamado "Common LISP Modules. Artificial Intelligence in the Era of Neural Networks and Chaos Theory". La competicin se realiz en 6 pistas y se corra dos veces en cada pista. Se elega un orden de salida aleatorio para la primera carrera y en la segunda se inverta el orden de salida. Las pistas eran las siguientes: ANEW.TRK 8 vueltas OVAL2.TRK 20 vueltas V03.TRK 15 vueltas STEF2.TRK 15 vueltas SPEED2.TRK 10 vueltas ZANDVORT.TRK 8 vueltas El nmero mximo de coches era 16. En caso de haber ms, se recurran a sesiones eliminatorias obteniendo as los 16 finalistas. No se permita que los cdigos de los robots accedieran a zonas de memoria reservada, ni realizaran llamadas al sistema indebidas. En caso contrario eran descalificados. Los robots tenan que estar en cdigo fuente o en un fichero objeto y no podan disponer de ms de 25K de memoria RAM. Se deba ejecutar en no ms de 3 milisegundos con el fin de no ralentizar la carrera y que pareciera lo ms real posible.

4.3 Modelo Fsico.


El comportamiento del coche viene determinado por el valor de ciertas variables fsicas. Vamos a explicar este modelo fsico apoyndonos en la siguiente figura.

Figura 4-3. Modelo Fsico V Vector de velocidad del coche. P Vector de apuntamiento del coche. Es un vector unitario que indica la direccin a la que apunta el coche. ngulo de separacin de los vectores anteriores. W Vector de velocidad de los neumticos con respecto a la pista. Ha de cumplir: W = -P *vc, siendo vc la velocidad que ha de llevar el coche.

L Vector de derrapaje. Se divide en componente tangencial (Lt) y componente normal (Ln). F Fuerza de traccin, esto es, vector de fuerza que empuja el coche. Su direccin es opuesta a la de L. Se divide en componente tangencial (Lt) y componente normal (Ln).

4.4 La estructura situation


El esquema bsico de funcionamiento del robot conductor consiste en determinar lo que est ocurriendo en cada momento y calcular las salidas de control, o bien elegirlas de entre varios valores posibles, tal y como se muestra en el siguiente esquema:
ROBOT
INPUT Situacin: s

Figura 4.4.2. Variables del robot s.to_rgt Distancia al borde derecho del circuito. s.to_lft Distancia al borde izquierdo del circuito. s.cur_rad Radio del segmento del circuito en el que nos encontramos. Un radio nulo representa una recta. s.nxt_rad Radio del siguiente segmento del circuito, que ser una curva. s.cur_len Longitud del segmento del circuito. Si se trata de una recta la unidad de medida son los pies, mientras que si se trata de una curva son los radianes. s.nxt_len Longitud del siguiente tramo en curva. s.to_end Distancia que existe desde el punto en que se encuentra el vehculo en este instante hasta el siguiente segmento del circuito. Es la distancia que queda por recorrer del segmento actual. s.v Velocidad que tiene el coche en cada momento. Es medida en pies por segundo (feet per second, fps). s.vn Componente de la velocidad normal a la direccin del circuito en fps. Si es positiva indica que el coche se mueve hacia la derecha. Si es negativa, indica que el coche se mueve hacia la izquierda.

OUTPUT

Velocidad: vc ngulo: alpha

Figura 4.4.1. Sistema del robot

vc Es la velocidad que se le imprime al coche a partir de la situacin en la que se encuentre y en la que se va a encontrar, teniendo en cuenta si nos encontramos en una curva, si esta es cerrada, si estamos en una recta, si el tramo siguiente es una curva, si estamos adelantando, etc. alpha Indica el grado de inclinacin del coche, marcado por el que forman la velocidad y la direccin que lleva el coche, como quedo explicado anteriormente. Al igual que con vc, hay que tener en cuenta multitud de parmetros, sobre todo en las curvas, donde segn el algoritmo el coche tendr un comportamiento muy diferente, puesto que en las rectas este factor no influye en gran medida, salvo a la hora de adelantar o realizar algn giro brusco.

4.5 Programa de Control.


Nuestro robot se ha basado en el cdigo bsico de ejemplo del Tutorial 4, que est disponible en el siguiente enlace http://rars.sourceforge.net/help.html El algoritmo que utiliza es muy bsico. Simplemente se preocupa de mantener el coche junto al lateral de la calzada. Para ello utiliza la variable lane que hace que en las rectas se quede en la situacin en la que se encuentra, y en las curvas se pegue al lado interno de la calzada. Nosotros hemos modificado ligeramente este algoritmo, como pasaremos a explicar a continuacin, pero a grandes rasgos, lo que hacemos es estudiar en qu situacin est el coche y en que situacin pasar a estar en el siguiente instante, y as determinar de qu velocidad y ngulo conviene dotar al vehculo para que tenga una trazada limpia y rpida.

Para comprender mejor el funcionamiento del robot es necesario explicar los datos de entrada de los que disponemos para, observando sus valores, conocer la situacin actual del vehculo. Estos datos son variables de la estructura situation, las cuales son accesibles por todos los coches a travs de la librera cars.h. Para su mejor comprensin nos apoyaremos en la siguiente figura:

En cuanto a la velocidad, el algoritmo utilizado tambin es muy sencillo, simplemente acelera en las rectas hasta llegar a una curva, donde calcula la velocidad de entrada en curva y lo mantiene a lo largo de esta. Nosotros tambin hemos mejorado este aspecto haciendo que la velocidad en curva vaya variando gradualmente segn el coche va abandonando esta. El tercer aspecto, y quizs el ms importante a la hora de trazar una curva, es el ngulo alpha de inclinacin del coche respecto a su direccin. Para ello tiene en cuenta la posicin en la que esta, y en la que debera estar, as saca el ngulo con el que girar el coche. A ste ngulo se le aade una componente bias que le har aumentar en el caso de las curvas, para as poder trazar mejor. El problema de este algoritmo es que slo tiene en cuenta la curva en la que est para modificar este valor. Nosotros, en cambio, hemos realizado un algoritmo basado en un rbol de profundidad 3, es decir miramos la curva en la que estamos y las dos siguientes y en funcin de esto modificamos el ngulo de una forma u otra. El ltimo aspecto a tener en cuenta es como se afrontan las colisiones. Este algoritmo trata de evitarlas bien, frenando si no tiene otra opcin, o tratando de adelantar al coche que ha detectado por donde tenga espacio en la pista, pero no tiene en cuenta si la siguiente curva va a ser a un lado u otro. Puesto que siempre es conveniente coger el lado bueno de la pista, ser conveniente adelantar por un lado u otro segn convenga. ste aspecto si lo tenemos en cuenta en nuestro cdigo.

En ella podemos configurar diversas opciones de la carrera tales como el circuito en el que deseamos correr, los coches que queramos que corran, el nmero de vueltas o el tipo de visualizacin del circuito (normal, zoom, etc.) Una vez hayamos seleccionado el circuito en el que queremos correr y los coches que van a participar en la carrera, as como el resto de opciones, pulsaremos el botn Start Race que dar paso a la siguiente pantalla, que muestra la carrera y otras opciones. En la siguiente figura podemos apreciar cmo es esta pantalla:

Figura 4.6.2. Carrera en el simulador En esta pantalla podemos volver a cambiar el tipo de vista del circuito, utilizando la barra de men. Las opciones que nos permite son Classic, OpenGL - FullScreen, OpenGL - Window, Telemetry y Zoom. Para que la carrera d comienzo, tendremos que pulsar una de las tres teclas que indican las distintas velocidades, S, D o F, o sus correspondientes opciones de la barra de men. Para visualizar la trazada de un determinado coche, navegaremos con las teclas Av Pg y Re Pg, que nos desplazarn sobre los distintos vehculos, hasta elegir el deseado. En la parte inferior de la pantalla se van mostrando varias variables relevantes en la carrera como las velocidades de cada coche, la posicin que ocupan, los daos que tiene cada coche, el carburante as como el tiempo al coche que va a la cabeza.

4.6 Funcionamiento del Simulador.


Cuando ejecutamos el programa, la primera pantalla que nos muestra la siguiente interfaz grfica:

Figura 4.6.1. Configuracin del simulador

5. NUESTRO ROBOT
Nuestro algoritmo: Nuestra propuesta para el desarrollo del robot ha sido en s misma una toma de decisiones continua sobre diferentes variables que se nos fueron presentando durante su implementacin. A continuacin detallamos alguna de ellas. En primer lugar, con respecto al algoritmo utilizado, sopesamos los costes y conclusiones que obtendramos dirigindonos por cada uno de los distintos mtodos que planea cada uno de los robots, que vienen como ejemplo en la pgina oficial. Tras descartar tentativas como las de precmputo del circuito, a travs de algoritmos basados en bsqueda A* o de entrenamiento de redes neuronales (por el tiempo de que disponamos para realizar la prctica), nos decantamos por un sistema experto que decidiese en concordancia con las variables de entrada actuales, sin tener en cuenta ningn otro parmetro pasado o futuro. Nuestro robot intenta imitar lo ms fielmente posible la ejecucin de un ser humano a los mandos de un coche, de esta manera no es difcil imaginar las actuaciones que llevara a cabo en cada situacin: En las curvas, que es el lugar donde realmente se ganan o se pierden segundos, el coche tiende a abrirse antes de tomarla, y tras haberla tomado, para salir de la misma con la mayor velocidad posible (como ya sabemos suele ser mas efectivo salir con la mxima aceleracin de la curva, que entrar a esta con mayor velocidad). Las distintas variables y trazadas de curvas dependern de otros factores, tales como que divisa nuestro conductor en el horizonte(es decir, que viene despus otro par de enlazadas, una larga recta una curva suave a favor...). Dicho horizonte no se encuentra formado ms que por una jerarqua de tres niveles, proporcionadas por la estructura de situacin que recibimos como parmetro de entrada a nuestro cdigo. Cada uno de estos niveles, representa el tramo de la carretera en que nos encontramos actualmente, as como los dos tramos siguientes, que sern tomados como referencia para las decisiones de conduccin (no es lo mismo si despus viene una recta donde tenemos que empezar a acelerar, que si viene otra curva donde tenemos que intentar seguir la trazado lo mas pegados posible a los pianos).

Mientras que en las rectas el comportamiento, como se puede prever, ser mucho mas dependiente de factores externos (como coches con los que podamos colisionar o obtener un buen posicionamiento para mejorar el ngulo alpha de trazada en la siguiente curva), puesto que las actuaciones, no sern mas que imprimir la mxima aceleracin posible a nuestro vehiculo con el fin de aumentar la velocidad todo lo posible, hasta el punto de frenada siempre que nos permita afrontar con garantas el siguiente tramo.

Aspectos secundarios que hemos tenido en cuenta a la hora del desarrollo de nuestro cdigo son: Los adelantamientos: Este aspecto viene incluido en la porcin que intenta evitar choques con otros coches, puesto que, a la vez que nos planteamos adelantar (la mayora de veces en recta) por el interior o exterior, segn las circunstancias de carrera, procuramos no interferir con la trazada de ningn otro coche, pues seria mayor el perjuicio en cuestin de daos para nuestro coche que la ganancia de conseguir una posicin mas elevada. El repostaje: Como comentbamos en el punto anterior, los daos producidos durante los diversos lances de carrera, perjudican el rendimiento del coche de tal manera que, llegado determinado punto, las prestaciones se resienten sobremanera. Dadas estas circunstancias, cuando nuestro dao en el vehculo supera un cierto umbral a partir del cual su eficiencia no es aceptable, entramos a boxes para reparar el vehculo. Aunque tambin puede darse el caso inverso, que entremos a boxes para repostar y aprovechemos para reparar los daos. El clculo de la carga de gasolina se realiza al inicio de la carrera, estimando a travs del consumo medio del coche y el nmero de vueltas a realizar.

Por ltimo, una consideracin final que se debe tener en cuenta, es la aleatoriedad de las carreras, es decir, el simulador es real hasta el punto que el mismo coche corriendo solo sobre un mismo circuito no realiza, en sucesivas iteraciones, los mismos tiempos. Como sucede en el mundo real, llegndose a obtener diferencias de hasta varios segundos en distintas vueltas. Si a lo anteriormente comentado, le sumamos el comportamiento del resto de participantes en la carrera, obtenemos que hasta el coche mas rpido puede acabar fuera de pista debido a los encontronazos de otros participantes. Por otro lado, el hecho de intentar evitar cualquier colisin proveniente de otro participante, reduce de manera ms que significativa la

velocidad del coche, por lo que realizar un sobreajuste al algoritmo de deteccin de colisiones provocara un detrimento del rendimiento del vehculo, cuando otros participantes se encontraran en los alrededores. Por tanto, hay que realizar una ponderacin entre los tiempos obtenidos y el ajuste de parmetros del sistema de anticolisin, obteniendo el compromiso ms ptimo para las circunstancias de la carrera. Vas de desarrollo: Bsicamente, como resulta natural, los coches que obtienen un mejor resultado, son aquellos que conocen de antemano el circuito y llevan a cabo un precmputo del mismo para obtener la trayectoria ptima. Como es lgico, este planteamiento no sirve de nada para un sistema experto de, por ejemplo, conduccin automtica. En este caso nuestro planteamiento sera el nico acertado, aunque no hay que confundir conceptos pues nuestro vehculo realiza una conduccin adecuada a los circuitos, y en la vida real, prima mucho ms mantenerse dentro de la calzada que mejorar la velocidad. Pero, una vez salvadas estas distancias, quizs, un sistema como el nuestro que procesara las circunstancias actuales sin conocimiento de propiedades futuras fuera la solucin. Como propuesta, una mejora al planteamiento para este tipo de sistema, podra ser un entrenamiento on-line; es decir, basarse de tramos ya superados para afrontar los siguientes dado que, como sabemos, en la mayora de los casos esto nos ayudara en el futuro. Este aspecto, puede ser desarrollado tanto en circuitos donde se realizarn varias vueltas superando en diversas ocasiones la misma curva, como en trazados no cclicos. Sirva como ejemplo, que si todas las curvas durante las diez ultimas millas han sido tomadas con un grado alpha de inclinacin muy bajo (curvas muy suaves), probablemente nos encontramos en un tramo del estilo autopista, y esto nos permita, tomarnos ciertas licencias a la hora de afrontas los siguientes tramos. Por tanto, proponemos un sistema de almacenaje y tratamiento de la informacin pasada, para su procesado y mejora del sistema de manera gradual al devenir de la carrera.

la versin adecuada para ejecutar el proyecto, etc., no hemos podido desarrollar un gran robot. Podramos haber realizado una implementacin ms compleja, utilizando otro tipo de algoritmo, como pueden ser los que calculan un camino ptimo previo, utilizando tcnicas de aprendizaje por realimentacin o redes neuronales. Tambin podramos haber diseado, como otros coches que trae el proyecto, robots basados en conocimiento, que usan la informacin previa que tienen de cada circuito. Todos estos mecanismos requieren un gran trabajo y esfuerzo, que por razones temporales no hemos podido realizar. An as, estamos contentos con nuestro trabajo, ya que nuestro robot consigue aumentar significativamente las prestaciones respecto al robot de ejemplo, e incluso es capaz de superar a algunos de los robots que vienen implementados. Tambin queremos mencionar que disear un robot de estas caractersticas es bastante complejo, ya que hay que tener en cuenta multitud de variables fsicas que influyen en la trayectoria del coche. Pero tambin hay que reconocer que RARS facilita mucho el trabajo con todas las libreras que incluye, haciendo que el desarrollador solamente tenga que ocuparse del algoritmo que desea que siga su coche, adems del simulador que incluye, que aunque no sea tan potente como puede ser por ejemplo el de TORCS, es muy bueno y representa bastante bien la realidad.

7. REFERENCIAS
Pgina oficial de RARS: http://rars.sourceforge.net Pgina oficial de Vamos Automotive Simulator http://vamos.sourceforge.net/ Pgina oficial de T1 Car Racing Simulation http://t1-crs.sourceforge.net/ Pgina oficial de TORCS http://torcs.sourceforge.net/ Pgina oficial de RACER http://www.racer.nl/ Pgina de la asignatura:
http://www.it.uc3m.es/~jvillena/irc/practicas/propuestas/torcs.htm Wikipedia: http://es.wikipedia.org/wiki/Portada

6. CONCLUSIONES
Podemos concluir que la realizacin de este pequeo estudio nos ha servido para aprender cmo disear un sistema experto. Nos ha resultado muy interesante observar cmo ensendole unas cuantas reglas al robot, es capaz de utilizarlas y desenvolverse con soltura en el circuito. Debido a la falta de tiempo, ya que empleamos la mayor parte de l eligiendo el simulador, instalndolo, buscando

8. ANEXO: CDIGO DEL ROBOT


//-------------------------------------------------------------------------// I N C L U D E //-------------------------------------------------------------------------#include #include #include #include <stdlib.h> <math.h> "car.h" "track.h"

//-------------------------------------------------------------------------// D E F I N E S //-------------------------------------------------------------------------#define min(x,y) ((x)<(y)?(x):(y)) // // // // parameters to tinker with: accelerations are in feet/second per second. slips are in feet/second distances are in feet const double CORN_MYU = 0.9; // lateral g's expected when cornering const double BRAKE_ACCEL = -33.0; // acceleration when braking on straight const double BRAKE_SLIP = 6.5; // tire slip when braking const double BRK_CRV_ACC = -27.0; // acceleration when braking in curve const double BRK_CRV_SLIP = 3.5; // tire slip for braking in curve const double MARGIN = 10.0; // target distance from curve's inner rail const double MARGENIZQ = 8.0; //distancia al margen izquierdo const double MARGENDCH = 8.0; //distancia al margen derecho const double MARG2 = MARGIN+10.0; // target for entering the curve const double ENT_SLOPE = .33; // slope of entrance path before the curve const double STEER_GAIN = 1.0; // gain of steering servo const double DAMP_GAIN = 1.2; // damping of steering servo const double BIG_SLIP = 8.0; // affects the byass of steering servo const double CURVE_END = 4.0; // when you are near end of curve, widths const double TOO_FAST = 1.02; // a ratio to determine if speed is OK in curve const double DELTA_LANE = 2.5; // if collision predicted, change leftDistance by this

double tang = 0.0; int brake = 0; static int rad_was = 0; // 0, 1, o -1 para indicar el tipo del segmento anterior double brakeDistance = 0.0; //margen para haber cambiado de lado ante una curva double rightCurveAngle = 0.0; //ngulo para el cambio de lado ante una curva a derecha. double leftCurveAngle = 0.0; //ngulo para el cambio de lado ante una curva a izquierda. static double leftDistance; // target distance from left wall, feet static double leftDistance0; // value of leftDistance during early part of straightaway int straightInit = 0; double rightRadius = 0.0; double leftRadius = 0.0; double third = 0.0; double byass = 0.0; // added to servo's alpha result when entering curve //-------------------------------------------------------------------------// Clase YEAH //-------------------------------------------------------------------------// devuelve la mxima velocidad de paso por curva, fps double corner_speed(double radius){ return sqrt(radius * 32.2 * CORN_MYU); } // Calcula la distancia critica necesaria para llevar al coche desde la velocidad v0 // a v1 cuando la aceleracin de frenado es "a", ft/sec^2. Velocidad en f/s. // ("a" should be negative) double CriticalDistance(double v0, double v1, double a) { double dv; dv = v1 - v0; if(dv > 0.0) return(0.0);

return (v0 + .5 * dv) * dv / a; } //Mtodo que calcula el ngulo necesario para trazar una diagonal en una recta double changeWay(double anchura,double distancia){ return atan(anchura/distancia); } // Esta es la funcin del robot conductor con_vec YEAH(situation &s){ con_vec result = CON_VEC_EMPTY; // Esta es la estructura que se devuelve track_desc td; //Esta estructura muestra la descripcin del circuito double alpha, vc; // componentes del resultado double speed; // velocidad objetivo para la siguiente curva si estamos en recta double speed_next = 0.0; // velocidad objetivo para la siguiente curva si estamos en curva double width; // ancho del circuito, feet double to_end; // distancia al final del segmento actual int first = 1; static double leftDistance_inc = 0.0; // ajuste de "leftDistance", para adelantamientos td=get_track_description(); //obtenemos la descripcin del circuito if(stuck(s.backward, s.v,s.vn, s.to_lft,s.to_rgt, &result.alpha,&result.vc)) return result; width = s.to_lft + s.to_rgt ; // Fijamos "leftDistance" durante las curvas para intentar mantener // una pequea distancia al lado interior de la curva // Si estamos en curva if(s.cur_rad != 0.0){ if(s.to_end > 4/5*s.cur_len){//primer quinto third = -0.7;//-1.3;//-1.3;//-0.8; } else if(s.to_end > 3/5*s.cur_len){//segundo quinto third = -0.6;//-0.8;//-0.4;//.2 } else if(s.to_end > 2/5*s.cur_len){//tercer quinto third = -0.4;//-0.8;//-0.4;//.2 } else if(s.to_end > 1/5*s.cur_len){//cuarto quinto third = -0.2;//-0.8;//-0.4;//.2 } else//quinto quinto third = -0.1;//0.1;//1.3;//1.5 if(s.to_end > 2/3*s.cur_len){ third=-1.1; } else{ if(s.to_end > s.cur_len/3){ third=-0.8; } else{ third=-0.2; } } if(s.cur_rad>0){//Si la curva es a izquierdas leftDistance = 3*MARGIN; rad_was=1; } //Si la curva es a derechas

else{ leftDistance = width - 3*MARGIN; rad_was=-1; } straightInit = 0; brake=0; } //Si estamos en recta else{ //indica que venimos de una curva: transicion if(rad_was!=0){ rad_was=0; brakeDistance=0.2*s.cur_len ; if(s.nex_rad < 0.0){ //Siguiente curva a la dcha rightCurveAngle = changeWay((width-s.to_rgt-1.75*MARGIN),(s.to_end-brakeDistance)); leftDistance=1.75*MARGIN+tan(rightCurveAngle)*(s.to_end-brakeDistance) ; } else { if(s.nex_rad > 0.0){ //curva a la izq leftCurveAngle = changeWay((width-s.to_lft-1.75*MARGIN),(s.to_end-brakeDistance)); leftDistance=width-(1.75*MARGIN+tan(leftCurveAngle)*(s.to_end-brakeDistance)) ; } } } else{ //estoy y estaba en una recta brakeDistance=CriticalDistance(s.v, speed, BRAKE_ACCEL-12); if(s.to_end < brakeDistance){//Tenemos que frenar e iniciar la curva //curva a la derecha if (s.nex_rad<0){ if(brake==0){//Inicio de la frenada. Calculo de trayectoria ideal rightCurveAngle=changeWay(0.75*width-s.to_lft,s.to_end); brake=1; } leftDistance=0.75*width-(1/2*sin(2*rightCurveAngle)*s.to_end); } //curva a la izquierda else if(s.nex_rad>0){ if(brake==0){ leftCurveAngle=changeWay(s.to_lft-0.25*width,s.to_end); brake=1; } leftDistance=0.25*width + 1/2*sin(2*leftCurveAngle)*s.to_end; } } // Si aun no estamos en la frenada else{ if (s.nex_rad<0){//curva a la derecha a la vista leftDistance=1.75*MARGIN + (1/2*sin(2*rightCurveAngle)*s.to_end); } if(s.nex_rad>0){ leftDistance=width-1.75*MARGIN-(1/2*sin(2*leftCurveAngle)*s.to_end); } } } } // // // // // // // // // // // set the byass: Bias is an additive term in the steering servo, so that the servo doesn't have to "hunt" much for the correct alpha value. It is an estimate of the alpha value that would be found by the servo if there was plenty of settling time. It is zero for straightaways. Also, for convenience, we call the corner_speed() function here. On the straightaway, we call it to find out the correct speed for the corner ahead, using s.nex_rad for the radius. In the curve we of course use the radius of the curve we are in. But also, we call it for the next segment, to find out our target speed for the end of the current segment, which we call speed_next. if(s.cur_rad == 0.0) { if(byass != 0.0){ byass= byass*0.7;

if (s.to_end <0.6*s.cur_len){ byass= byass*0.4; } if (s.to_end <0.4*s.cur_len){ byass = 0.0; } } if(s.nex_rad > 0.0) speed = corner_speed(s.nex_rad + MARGIN); else if(s.nex_rad < 0.0) speed = corner_speed(-s.nex_rad + MARGIN); else speed = 250.0; // This should not execute, for a normal track file } else{ // we are in a curve: if(s.nex_rad == 0.0) speed_next = 250.0; else speed_next = corner_speed(fabs(s.nex_rad) + MARGIN); speed = corner_speed(fabs(s.cur_rad) + MARGIN + fabs(leftDistance_inc)); speed = speed + 0.2*third*speed; byass =((s.v*s.v/(speed*speed)) * atan(BIG_SLIP/speed))+(1-(s.to_end/s.cur_len))*curveExit(s); if(s.cur_rad < 0.0) // byass must be negative for right turn byass = -byass; } // set alpha: (This line is the complete steering servo.) /* if (s.cur_rad < 0.0) alpha = STEER_GAIN * (-s.to_rgt + leftDistance)/width - DAMP_GAIN * s.vn/s.v + byass; else*/ alpha = STEER_GAIN * (s.to_lft - leftDistance)/width - DAMP_GAIN * s.vn/s.v + byass; // set vc: if(s.cur_rad == 0.0){ // If we are on a straightaway, // if we are far from the end, brakeDistance=CriticalDistance(s.v, speed, BRAKE_ACCEL); //brakeDistance=0.25*s.cur_len *brakeDistance; if(s.to_end > CriticalDistance(s.v, speed, BRAKE_ACCEL)) vc = s.v + 80.0; // pedal to the metal! else{ // otherwise, adjust speed for the coming turn: if(s.v > TOO_FAST * speed) // if we're a little too fast, vc = s.v - BRAKE_SLIP; // brake hard. else if(s.v < speed/TOO_FAST) // if we're a little too slow, vc = 6 * speed; // 1.1 accelerate hard. else // if we are very close to speed, vc = 3*(s.v + speed); // approach the speed gently. } } else{ // This is when we are in a curve: (seek correct speed) // calculate distance to end of curve: if(s.cur_rad > 0.0) to_end = s.to_end * (s.cur_rad + MARGIN); else to_end = -s.to_end * (s.cur_rad - MARGIN); // compute required braking distance and compare: // This is to slow us down for then next curve, if necessary: if(to_end <= CriticalDistance(s.v, speed_next, BRK_CRV_ACC)) vc = s.v - BRK_CRV_SLIP; // but if there is a straight, or a faster curve next, then // we may want to accelerate: else if(to_end/width < CURVE_END && speed_next > speed) vc = (s.v + speed_next)/cos(alpha); else // normally, just calculate vc to maintain speed in corner vc = (s.v + speed)/cos(alpha); } ////////////COLISIONES ///////////////////// //El estudio de comportamiento ante colisin nos indica de manera emprica que las actuaciones //llevadas a cabo con el fin de evitar las colisiones con un numero de participantes igual o superior //a 4 producen un deterioro en el rendimiento //del coche mayor que el beneficio en daos evitados para nuestro robot por lo que se desaconseja su //uso en este tipo de situaciones.

// // // //

Cdigo de adelantamientos y anticolisin: Este cdigo primero intenta predecir una colisin. Si no se prev ninguna no hace nada. La prediccin de colisin es aproximada, y se basa en extrapolacin lineal.

// Si se prev una colisin, cambiamos la variable leftDistance_inc que a su vez // modifica alpha. Intentamos adelantar siempre tomando el interior de la curva actual // o de la siguiente en caso de no poder o de que no nos encontremos en una curva, // siempre que encontremos hueco por ese lado. Si no podemos adelantar por el interior, // nos quedaremos detrs, de forma que podamos empezar a acelerar antes a la salida. // Esto es as salvo que nos encontremos en una recta y aun nos quede suficiente // espacio para pasar al otro coche, en cuyo caso, aceleraremos y le pasaremos por el // "lado malo". Adems, si estamos en una curva y no podemos obtener el interior, pero // a continuacin viene una curva hacia el lado opuesto, intentaremos obtener el interior // en la segunda curva, para lo que nos abriremos ligeramente en la primera. // Cuando se deja de prever colisin leftDistance_inc se vuelve gradualmente a cero. // Si vamos a colisionar inmediatamente con un coche que va mucho mas lento que nosotros, // frenamos fuerte y tratamos de esquivarlo, para evitar grandes daos en el coche, // tratando de evitar en todo momento que nos salgamos de la pista. double x, y, vx, vy, dot, vsqr, c_time, y_close, x_close; int kount; kount = 0; for(int i=0;i<3;i++){ if (s.nearby[i].who<16){ // si tenemos un coche cerca y=s.nearby[i].rel_y; // obtenemos la distancia en y (centro a centro) x=s.nearby[i].rel_x; // obtenemos la distancia a la derecha (entre centros) vx=s.nearby[i].rel_xdot; // obtenemos la distancia relativa en x vy=s.nearby[i].rel_ydot; // obtenemos la velocidad relativa en y: -: Aproximndose // +: Alejndose // Si los coches se estn acercando, el producto escalar de las posiciones // relativas y los vectores de velocidad ser negativo. dot = x * vx + y * vy; // producto escalar de los vectores if(dot > -0.1) // si no se aproxima no hacemos nada continue; vsqr = vx*vx + vy*vy; // calculamos la velocidad relativa cuadrada c_time = -dot / vsqr; // Tiempo de la aproximacin mas cercana if(c_time > 3.0) // Si es superior a 3 sec, lo ignoramos continue; x_close = x + c_time * vx; y_close = y + c_time * vy; // coordenada x de la mxima aproximacin // coordenada y de la mxima aproximacin

// Comprobamos si habr colisin antes de la mxima aproximacin // y en ese caso reduce c_time y recalcula x_close e y_close: if(x_close * x < 0.0 && y < 1.1 * CARLEN){ c_time = (fabs(x) - CARWID) / fabs(vx); x_close = x + c_time * vx; // x coord at closest approach y_close = y + c_time * vy; // y coord at closest approach } // Comprobamos si chocarn if(fabs(x_close) > 2 * CARWID || fabs(y_close) > 1.25 * CARLEN) continue; // Predecimos una colisin ++kount; // Contamos el numero de coches con los que podemos colisionar if(kount > 1){ // Si hay mas de un coche con el que colisionar vc = s.v - BRK_CRV_SLIP; //frenamos } //Si estamos a punto de colisionar y va a menos de la cuarta //parte de nuestra velocidad if(c_time<0.75 && fabs(vy)>0.75*s.v){ vc = s.v - BRK_CRV_SLIP;//frenamos e iniciamos maniobra evasiva if(x>0){ //Esta a nuestra derecha //elusiva a la izqda si cabemos. Si no, a la derecha brusco if(s.to_lft>CARWID/2) leftDistance_inc -= DELTA_LANE; else leftDistance_inc += 1.2*DELTA_LANE; }

else{ //Esta a nuestra izquierda //elusiva a la derecha si cabemos. Si no, a la derecha brusco if (s.to_rgt>CARWID/2) leftDistance_inc += DELTA_LANE; else leftDistance_inc -= 1.2*DELTA_LANE; } } else{ //Estamos en curva a la izquierda if(s.cur_rad > 0.0){ // si el coche rival esta a tu izqda (en el interior) if(x_close < 0.0){ //Siguiente:curva a la dcha if (s.nex_rad<0.0 && s.to_rgt>MARGIN/2){ //nos abrimos para tomar el interior de la siguiente leftDistance_inc += DELTA_LANE/2; } //Si lo siguiente es curva no es a la derecha, evitamos el choque else{ leftDistance_inc -= DELTA_LANE/2; vc=vc*0.9; //Acoplamiento } } //si estamos mas al interior else{ //Si podemos, nos pegamos al interior...y pasamos si cabemos if(s.to_lft > MARGIN/2) { leftDistance_inc -= DELTA_LANE; if(s.to_lft+x_close>2*CARWID) vc=vc*1.05; } } } //Curva a la derecha else if(s.cur_rad < 0.0) { // si el coche rival esta a tu derecha (en el interior) if(x_close > 0.0){ //Siguiente:curva a la izqda if (s.nex_rad>0.0 && s.to_lft>MARGIN/2){ //nos abrimos para tomar el interior de la siguiente leftDistance_inc -= DELTA_LANE/2; } else{ leftDistance_inc -= DELTA_LANE/2; vc=vc*0.9; //Acoplamiento } } else{ //Si podemos, nos pegamos al interior...y pasamos si cabemos if(s.to_rgt > MARGIN/2){ leftDistance_inc += DELTA_LANE; if(s.to_rgt-x_close>2*CARWID) vc=vc*1.05; } } } //estamos en una recta else{ //intentamos ganar el lado interior de la frenada //curva a derecha y cabemos if(s.nex_rad<0 && s.to_rgt-x>2*CARWID && s.to_rgt>MARGIN/2){ //tomamos el interior leftDistance_inc += DELTA_LANE; //y si ya esta a nuestra izquierda, aceleramos vc=1.1*vc; } //curva a izquierda y cabemos else if(s.nex_rad>0 && s.to_lft+x>2*CARWID && s.to_lft>MARGIN/2){ //tomamos el interior y aceleramos leftDistance_inc -= DELTA_LANE; vc=1.1*vc; } //no cabemos x el interior else{

//si no estamos en la frenada if(s.to_end>brakeDistance){ //si le tenemos a la izquierda, le pasamos x la dcha, si cabemos if(x < 0.0 && s.to_rgt>MARGIN/2){ leftDistance_inc += DELTA_LANE; vc=vc*1.1; } //si le tenemos a la derecha, le pasamos x la izqda, si cabemos else if(x > 0.0 && s.to_lft>MARGIN/2){ leftDistance_inc -= DELTA_LANE; vc=vc*1.1; } else vc=vc*0.9; } } } } } } // Reducimos gradualmente leftDistance_inc si no se prevee collision if(!kount) if(leftDistance_inc > .1) leftDistance_inc -= .5*DELTA_LANE; else if(leftDistance_inc < -.001) leftDistance_inc += .5*DELTA_LANE; ////////////COLISIONES ///////////////////// // Al inicio de la carrera, mantenemos la trayectoria, y hacemos el calculo de fuel if(s.starting){ leftDistance = leftDistance0 = s.to_lft; //calculamos la cantidad de fuel optima para afrontar la carrera. Se consumen en //torno a 1.5 galones/milla result.fuel_amount = min(td.length/5280*s.laps_to_go*1.5,MAX_FUEL); } // leftDistance_inc representa un ajuste de la variable leftDistance. Se realiza // modificando alpha result.vc = vc; result.alpha = alpha - STEER_GAIN * leftDistance_inc / width; // // // // Vamos al Pit: si no tenemos suficiente fuel para completar una vuelta o el coche esta demasiado daado Fuel: Calculamos el minimo fuel para llegar Damage: Reparar todo if(s.fuel<td.length/5280*1.7 || s.damage>24000 ){ result.request_pit = 1; result.repair_amount = s.damage; if (s.fuel<td.length/5280*1.7*s.laps_to_go){ result.fuel_amount = min(td.length/5280*s.laps_to_go*1.8,MAX_FUEL)-s.fuel; } } return result; } //Funcin que influye en el ngulo de toma de la curva alpha por medio de la adicin de un termino de //inclinacin a nuestro coche a travs de la componente byass desde donde es llamada. Se basa en un //estudio de la situacin actual y futura de la carretera. double curveExit(situation &s) { double abrir = -0.50; double cerrar = -0.20; if(s.nex_rad ==0)//recta { if(s.after_rad ==0)//recta {

return abrir; // (IZQ o DCH) RECTA RECTA // si estoy en una curva y los dos tramos siguientes son rectas } else //estoy en curva y lo siguiente es una curva { if(s.after_rad >0) ////estoy en curva y lo siguiente es una recta y luego curva a izq { if(s.cur_rad <0) return abrir;// DCH RECTA IZQ return abrir; // IZQ RECTA IZQ } else //curva derch { if(s.cur_rad <0) return abrir; // DCH RECTA DCHA return abrir; // IZQ RECTA DCHA } } /**********/ } else // lo siguiente es una curva { if(s.nex_rad >0)//curva izq { /********/ if(s.after_rad == 0) //recta { if(s.cur_rad <0) return abrir; // DCHA IZQ RECTA return cerrar; // IZQ IZQ RECTA } else { if(s.after_rad >0)//curva izq { if(s.cur_rad <0) return abrir; // DCHA IZQ IZQ return cerrar; // IZQ IZQ IZQ } else //curva derch { if(s.cur_rad <0) return abrir; // DCHA IZQ DCHA return cerrar; // IZQ IZQ DCHA } } /*********/ } else //curva derch { /*********/ if(s.after_rad ==0)//recta { if(s.cur_rad <0) return cerrar; // DCHA DCHA RECTA return abrir; // IZQ DCHA RECTA } else { if(s.after_rad >0)//curva izq { if(s.cur_rad <0) return cerrar; // DCHA DCHA IZQ return abrir; // IZQ DCHA IZQ } else //curva derch { if(s.cur_rad <0) return cerrar; // DCHA DCHA DCHA return abrir; //IZQ DCHA IZQ } } /*********/ } } }

También podría gustarte