sábado, 18 de junio de 2011

Vídeos de resultados

Esta probablemente será la última entrada que publicaré antes de la entrega y presentación de mi PFC; en esta entrada mostraré vídeos en los que se observará resultados de aprendizajes, adelantamientos, persecuciones, bloqueos a rivales, carreras contra rivales y usos de la herramienta gráfica. Serán vídeos en los que me apoyaré durante la defensa de mi proyecto, por lo que tendré especial cuidado en su acabado.
Iré actualizando la entrada con los vídeos que vaya editando con el software Camtasia (que por cierto es genial para hacer presentaciones en vídeos y hacer capturas de pantalla).


Vídeo 1: Aprendizaje en Street1


martes, 14 de junio de 2011

Aprendizaje

Aunque ya está prácticamente cerrado el PFC, he seguido añadiendo algunas mejoras. La última ha sido incorporarle un sistema de aprendizaje de circuitos. Este sistema es simple, pero muy eficaz. Se basa en tener una tabla hash en la que tengo como clave los puntos kilométricos del circuito, y como objeto asociado a cada clave un booleano que indica si hay peligro en dicho punto o no.
Esta tabla se carga durante la primera vuelta que se da al circuito, y marca como "1" aquellos puntos en los que se produce un incremento de daños (es decir, que se ha dado un porrazo :) ).
En las siguientes vueltas, se comprobará con una antelación de 150 metros si hay algún punto peligroso, y si lo hay, se reduce la velocidad a menos de 100km/h. Cuando se ha pasado el punto peligroso, se vuelve al estilo de conducción normal.

En el siguiente vídeo se puede ver un ejemplo de aplicar esta estrategia. En la primera vuelta que realiza se producen algunos impactos, pero en la siguiente vuelta recuerda dónde se produjeron los impactos y va a menor velocidad en esos puntos.


Vídeo de carrera contra más rivales. Aún no es competitivo, pero se puede observar que al menos ya no tiene problemas de dirección, y se controla decentemente la velocidad. Hay que mejorar los adelantamientos.




PD: Llevo unas 30 páginas de la memoria del PFC escritas de momento.

domingo, 29 de mayo de 2011

Controlador PD

He estado trabajando en mejorar el comportamiento de la dirección del vehículo. En las últimas entradas comenté que al modificar la velocidad máxima del cliente ya no funcioaba correctamente el control de dirección que venía por defecto, así que diseñé uno desde cero. Una buena solución fue aplicar un controlador P (controlador proporcional) en el vehículo, con lo que se se conseguía un nivel de giro proporcional a la distancia a los bordes:

giro=giro+Kp*error

Tomé como Kp -0.001, después de probar con varios valores. Aunque existen algunas técnicas, en algunas fuentes de bibliografía recomendaban ajustarla a ojo esta constante mediante pruebas.

Este controlador me proporcionaba unos resultados muy aceptables, pero el vehículo tendía a oscilar un poco rectas, y probé con un controlador PD, que estuve informandome sobre su comportamiento y era muy adcuado para suavizar las salidas del sistema (el giro de volante en nuestro caso).

giro=giro+Kp*error+Kd*(error-error_anterior)

En este caso tomé la misma Kp y como Kd -0.01, y los resultados han sido muy buenos, ya que el coche no se ha salido de la calzada en ningún momento en los circuitos probados (óvalos, ciudades y uno real de Montmeló), y no solo eso, sino que además el coche tiende a ir por el centro de la calzada. Y todo ello de forma suave.

domingo, 22 de mayo de 2011

Ajuste de reglas, corrección de errores y finalización del proyecto

Después de varios meses de desarrollo, ha comenzado la fase final del proyecto. En esta etapa mis objetivos serán los siguientes:

- Desarrollo de una máquina de estados, que nos permitirá seleccionar un conjunto de reglas apropiado a la situación del vehículo.
-------------------------------------------------------------------

En principio tendré 3 estados: Inicial, persecución y adelantamiento.
  • El estado inicial será el estado básico, y estará asociado a un conjunto de reglas que se seleccionarán siempre que no haya rivales en un radio cercano.
  • El estado persecución tendrá como objetivo buscar un hueco entre el rival y el borde de la calzada que sea mayor que la anchura de nuestro vehículo. El objetivo consistirá en posicionarse en paralelo a dicho hueco.
  • El estado adelantamiento consistirá en realizar la maniobra de acelerar en paralelo al rival hasta rebasarlo. Esta maniobra se realizará si nos da tiempo antes de que llegue una curva.
Se realizará la transición de estados inicial->persecución cuando se de el evento de que se detecte un vehículo rival.
La transición persecución->adelantamiento se lanzará cuándo el vehículo alcance una buena posición para poder iniciar una maniobra de adelantamiento.
También se tendrá una transición persecución->Inicial si por algún motivo hay que desistir de buscar una posición para adelantar. Esto puede darse por ejemplo si se aproximan curvas cerradas.
La transición adelantamiento->Inicial se activará cuándo se rebase al rival en el adelantamiento.
La transición adelantamiento->persecución se acerca una curva mientras se está rebasando al rival.

Una posible mejora ( que de momento no se aplicará) sería tener distintos modos de conducción (modo conducción agresiva o conducción relajada) que nos permitiese o no hacer maniobras de adelantamiento en curvas.

Ajuste de reglas
--------------------------------------
Esta parte será la que más tiempo de desarrollo requerirá. Consistirá en diseñar el conjunto de reglas para cada uno de los estados.

Ejemplos:
ESTADO INICIAL
0 rival_frente(cerca)->cambio_estado(persecucion)
1 rival_frente(medio)->cambio_estado(persecucion)

ESTADO PERSECUCIÓN
0 huecoMayor(derecha)&posicion_pista(derecha)->cambio_estado(adelantar)
1 huecoMayor(derecha)&posicion_pista(izquierda)->direccion(-0.6)
2 huecoMayor(derecha)&posicion_pista(centro)->direccion(-0.4)
3 huecoMayor(izquierda)&posicion_pista(izquierda)->cambio_estado(adelantar)
4 huecoMayor(izquierda)&posicion_pista(derecha)->direccion(0.6)
5 huecoMayor(izquierda)&posicion_pista(centro)->direccion(0.4)

ESTADO ADELANTAMIENTO
0 entorno(recta)&tiempo_adel(si)->acelerar(1)
1 rival_atras(cerca)->cambio_estado(inicial)
2 rival_atras(medio)->cambio_estado(inicial)
3 entorno(curva)->cambio_estado(persecucion)
4 rival_derecha(si)-> acelerar(1)
5 rival_izquierda(si)-> acelerar(1)


Hay que señalar que estos conjuntos de reglas están diseñados pensando en un solo rival a batir.
En el caso de tener varios rivales, la complejididad del problema de adelantamiento se incrementa sustancialmente.

Finalización de representaciones gráficas
-------------------------------------------
Consistirá en terminar de representar las gráficas que faltan referentes a acciones (aceleración, freno, y marcha).

Corrección de bugs
-----------------------------------------
La aplicación actualmente tiene diversos fallos puntuales, principalmente son sobre refrescos de gráficos. Se hará todo lo posible por corregirlos.

Diseño de un controlador difuso para la tracción del vehículo
----------------------------------------
Si se tiene el suficiente tiempo antes de la finalización del PFC, se diseñará un controlador difuso para la tracción. En principio se iba a diseñar con controlador fuzzy para las marchas, pero no era adecuado este tipo de controlador para esta variable, ya que se trata de una variable discreta, y los sitemas fuzzy son adecuados para variables continuas. Por ello, se decidió que se podría realizar un controlador fuzzy para la tracción, tomando como entradas la velocidad del vehículo y la velocidad objetivo y como salida el nivel de aceleración a aplicar para evitar que patine el coche.

martes, 17 de mayo de 2011

Experimentos

Últimamente he estado realizando algunos experimentos para calcular la velocidad óptima de cambio de marcha, y también otros experimentos para comprobar que el circuito se reconocía adecuadamente.

El primer experimento consistió en partir de meta en el circuito Villarello Death (circuito tipo óvalo con rectas muy largas) en 1ª, 2ª, 3ª, 4ª , 5ª, 6ª y 7ª marcha y tomar los datos de como íba variando la aceleración. Se observa que inicialmente para cada marcha se tiene una aceleración creciente, luego estable y luego decreciente. La idea era observar el punto en el que se cruzan la aceleración decreciente de una marcha con la aceleración de la siguiente marcha, siendo ese punto la velocidad de cambio de marcha óptima.

Otro de los experimentos cosistió en representar gráficamente los radios de curvatura (calculados mediante geometría y álgebra -detallado hace varias entradas-) que se fuesen reconociendo durante la carrera. Exte experimento se realizó sobre el circuito F-speedway1. Se obtuvieron los siguientes resultados:



Se observa que se reconocieron hasta 3 tipos de curvatura para cada curva del circuito, siendo esto correcto, ya que comprobamos que en el fichero xml de definición del circuito, cada curva se componía de 3 subcurvas cada una en ese circuito. Además, el radio calculado era exactamente el reflejado el el fichero de XML, luego el sistema de detección estaba correctamente diseñado.

lunes, 25 de abril de 2011

Cálculo de huecos para adelantamientos

Una de las últimas mejoras en las que he podido progresar ha sido la detección de la zona por la que hay hueco suficiente para poder adelantar.
Para diseñar esta mejora he necesitado aplicar bastante trigonometría:

En esta imagen he representado cómo se calcularía la distancia del oponente al borde izquierdo (para el cálculo al borde derecho sería similar). Supongamos que la zona negra de la imagen es una carretra recta, el rectángulo rojo nuestro vehículo, y el círculo rojo un oponente. Nuestro objetivo es calcular la distancia D_op_b (distancia desde el oponente al borde). Para calcular, básicamente lo que hay que hacer es hallar la diferencia entre D_total (distancia desde nuestro coche al borde) y D_op_x (distancia desde nuestro vehículo al oponente). El problema surge en el cálculo de cada distancia, ya que no es tan simple como pueda parecer, porque entra en juego la variable alpha (ángulo respecto al eje de la pista).
En primer lugar calculamos la D_total; para ello tomamos la distancia proporcionada por S0 (S18 en el caso del cálculo de la distancia del oponente al borde derecho) y la multiplicamos por el coseno de alpha: D_total=S0*cos(Cº). Notar que C=alpha. A continuación necesitamos calcular D_op_x, y para ello necesitamos el ángulo bº. Este ángulo se obtiene mediante la fórmula :

b=( (S_oponente*10) - s.getAngleToTrackAxis())-90

(suponiendo las unidades en grados y siendo S_oponente el índice del sensor que nos ha detectado un oponente).

Una vez que hemos calculado b, podemos cacular D_op_x.

D_op_x=abs( dist_op*cos(b) )

Finalmente, tenemos que calcular si el oponente está a nuestra derecha o izquierda, para sumar o restar el valor D_op_x a D_total. Para realizar este cálculo, previamente tenemos que saber cuál es nuestro "sensor de referencia", esto es, qué sensor está paralelo al eje de la carretera. Esto se calcula fácilmente con la fórmula

referencia=18-(int)(Math.toDegrees(s.getAngleToTrackAxis())/10);

Una vez que sabemos cual es este sensor de referencia, simplemente tenemos que comprobar si el sensor dónde está el oponente tiene un índice menor o mayor. Si el índice es menor, entonces el oponente está a nuestra izquierda, y si es mayor, está a nuestra derecha.

En el caso de que esté a la izquierda, D_op_b =D_total-d_op_x
En el caso de que esté a la derecha, D_op_b =D_total+d_op_x

Con esto, ya tenemos calculado el "hueco", dato que nos servirá para comprobar si nuestro coche es mayor que dicho hueco, y en caso de que sea el mayor hueco que se haya detectado, podríamos plantearnos adelantar si se dan las condiciones (por ejemplo, que nos de tiempo de adelantar antes de llegar a una curva).

En siguientes entradas continuaré ampliando los progresos y trataré con más detalle aspectos que se comentaron en entradas anteriores.

lunes, 18 de abril de 2011

Detección precisa de rectas y curvas

Actualmente me encuentro en la etapa de diseño de reglas, y para ello es imprescindible detectar correctamente cuándo se está en una curva o una recta.
Hasta ahora esto lo detectaba a través del sensor que me proporcionase la mayor distancia, pero daba algunos problemas al encontrarse en curvas y en paralelo al eje de la pista (daba como resultado que estaba en una recta en ese caso). La forma correcta de hacer esta comprobación es la siguiente:

- Hay que calcular la pendiente entre el sensor 0-1 y el 1-2 para la zona izquierda del coche y comprobar si son aproximadamente iguales, esto es, que estén alineados.
Se comprobará que sean aproximadamente iguales porque una recta perfecta no existe en TORCS.

- Para la zona derecha el método es el mismo pero para los pares 16-17 y 17-18.

Si tanto en la derecha como en la izquierda se detectan que los puntos están alineados, entonces se podrá afirmar con seguridad que se está en una recta, y en caso contrario, en una curva. Para saber el sentido de la curva si se podrá utiliza el sensor que nos proporcione la máxima distancia, aunque previamente habrá que calcular cuál es el eje de referencia, que dependerá del ángulo del coche respecto al eje de la pista.

He de decir que tras realizar multitud de pruebas, no me salían alineados los puntos cuándo el coche estaba en una recta y no estaba parelelo al eje, y descubrí a qué era debido... vi que en el fichero SimpleDriver, los autores modificaban los ángulos de separación de los sensores de distancia al inciarse el conductor (en la función initAngles), y por defecto no están a 10º como pensábamos, sino que tienen distintas precisiones. Por ello, cuando estaba en la fase del diseño de la GUI de telemetría no me salían correctamente las distancias... es decir que no era necesario calcular el radio pequeño que se comentó hace varias entradas.
Aquí dejo una captura en la que se puede ver que ahora se perciben las rectas con gran precisión.



Y aquí dejo otra captura mostrando el método que he nombrado anteriormente. Lo he modificado de forma que los sensores queden separados cada 10º.


Una vez que tenga resuelto el problema de detección de curvas/rectas pasaré a diseñar una máquina de estados, que me servirá para poder elegir distintos conjuntos de reglas, según la situación en la que se esté.
En principio se tendrán los siguientes estados: Inicial, Recta, Curva, Adelantamiento.
Se cambiará de estado cuándo se dispare alguna regla que contenga como consecuente un cambio de estado.

Ejemplo de reglas del estado "adelantar":
0 hay_hueco(izquierda)&da_tiempo(adelantar)->adelantar(izquierda)
1 hay_hueco(derecha)&da_tiempo(adelantar)->adelantar(derecha)
2 hay_hueco(centro)&da_tiempo(adelantar)->adelantar(centro)

Se puede observar que cada vez los antecedentes y los consecuentes están siendo más complejos e inteligentes.

También hay algunas ideas más por desarrollar como:

- La comprobación de la velocidad del oponente para ver si es alcanzable antes de que se llegue a una curva (esto es imprescindible para poder tener antecedentes del tipo "me da tiempo de adelantar").
- El diseño de un controlador difuso para el control de las marchas.
- Diseñar un controlador PID (http://es.wikipedia.org/wiki/Proporcional_integral_derivativo) para realimentar la entrada con la dirección.
- Aplicar teoría del campo eléctrico para realizar adelantamientos (basándose en el comportamientos de cargas del mismo signo, que se repelen)



Y para finalizar esta entrada, dejo 2 vídeos más sobre los adelantamientos que se están logrando



viernes, 8 de abril de 2011

Primer adelantamiento con reglas reactivas

Aquí dejo un vídeo en que se puede observar el resultado de aplicar un conjunto de reglas para lograr adelantamientos (en rectas de momento)

Como curiosidad decir que se está obteniendo un comportamiento inteligente a partir de reglas reactivas muy básicas (swarm intelligence).

La primera versión del conjunto de reglas que estoy utilizando es esta:

0 entorno(recta)&posicion_pista(centro)&dist_op_izq(lejos)&dist_op_centro(cerca)&dist_op_der(lejos)->acelerar(0.9)&frenar(0)&direccion(-0.7)

1 entorno(recta)&posicion_pista(derecha)&dist_op_izq(lejos)&dist_op_centro(cerca)&dist_op_der(lejos)->acelerar(0.9)&frenar(0)&direccion(0.8)

2 entorno(recta)&posicion_pista(izquierda)&dist_op_izq(lejos)&dist_op_centro(cerca)&dist_op_der(lejos)->acelerar(0.9)&frenar(0)&direccion(-0.8)

3 entorno(recta)&posicion_pista(centro)&dist_op_izq(cerca)&dist_op_centro(lejos)&dist_op_der(lejos)->acelerar(0.9)&frenar(0)&direccion(-0.8)

4 entorno(recta)&posicion_pista(centro)&dist_op_izq(lejos)&dist_op_centro(lejos)&dist_op_der(cerca)->acelerar(0.9)&frenar(0)&direccion(0.8)

5 entorno(recta)&posicion_pista(derecha)&dist_op_izq(cerca)&dist_op_centro(lejos)&dist_op_der(lejos)->acelerar(0.9)&frenar(0)&direccion(-0.5)

6 entorno(recta)&posicion_pista(derecha)&dist_op_izq(cerca)&dist_op_centro(cerca)&dist_op_der(lejos)->acelerar(0.9)&frenar(0)&direccion(-0.5)

7 entorno(recta)&posicion_pista(izquierda)&dist_op_izq(lejos)&dist_op_centro(cerca)&dist_op_der(cerca)->acelerar(0.9)&frenar(0)&direccion(0.3)

8
entorno(recta)&posicion_pista(izquierda)&dist_op_izq(cerca)&dist_op_centro(cerca)&dist_op_der(lejos)->acelerar(0.9)&frenar(0)&direccion(-0.7)

miércoles, 6 de abril de 2011

Guía rápida de la aplicación de telemetría para TORCS

Se trata de una aplicación Java que proporciona un entorno de estudio para vehículos del juego TORCS.
Los datos se envían desde el cliente Java de TORCS a la aplicación de telemetría a través de sockets UDP, por lo que se pueden tener la aplicación de telemetría y el cliente Torcs en equipos distintos.

La interfaz gráfica de la aplicación consiste en una serie de pestañas y una barra de menú con distintos botones:

Pestañas
--------
La pestaña Gráficas muestra gráficamente la velocidad, las revoluciones por minuto y la aceleración del vehículo durante la carrera. En cada vuelta la línea tiene un color distinto. Una vez finalizada la carrera, se puede acceder a un control de reproducción, en el que se puede seleccionar el instante deseado. Una vez seleccionado el instante deseado, se mostrará en distintas cajas de textos los valores de las percepciones en dicho instante.
(Diseñado, a falta de testear)



La pestaña Gráficas II muestra gráficamente el nivel de fuel y la marcha del vehículo durante la ejecución de la carrera. En cada vuelta la línea tiene un color distinto.
(Diseñado, a falta de testear)



La pestaña Gráficas acciones muestra gráficamente la aceleración y el frenadodel vehículo.
(Por diseñar, es necesario disponer primero del módulo de IA que está en su fase de diseño para conocer qué acciones se envían)


La pestaña Telemetría muestra en un panel a la izquierda la representación de las distancias tomadas por los 19 sensores de distancia que hay distribuidos en el vehículo cada 10º , a la derecha se muestra un volante que representa la dirección que está tomando el vehículo, y también hay algunas cajas de texto que muestran el entorno por el que está circulando el vehículo ( recta o curva con su correspondiente radio de curvatura). En una futura versión también se incluirá una gráfica de abrras que representará el nivel de acelerado/frenado.
(Diseñado y estable)



La pestaña Mapa va mostrando el mapa del circuito según las distancias tomadas por los sensores.
(Por diseñar)

Menú de opciones
Es una barra con 3 botones en la versión actual:

-Un botón para abrir ficheros log (en formato .xls) y poder analizarlo mediante las gráficas y el control de reproducción.



-Un botón de opciones que de momento solo contiene la opción de si guardar en log o no las percepciones de cada instante de la carrera. Permite al usuario seleccionar el directorio dónde desea almacenar el fichero xls.



-Un botón de acerca de.




Por supuesto hay que señalar que la interfaz será mejorada en futuras versiones y se terminarán de implementar/refinar todas la funcionalidades.

martes, 5 de abril de 2011

Inteligencia artificial

La siguiente fase del PFC consistirá en diseñar e implementar el módulo de IA. Estará compuesto por:

- Un razonador para realizar adelantamientos.
- Un controlador fuzzy para los cambios de marcha.
- Un 'cerebro' en el que almacenar todas las percepciones.

El razonador será un motor de selección de reglas del tipo

(1) P) A1 ^ A2^A3^....^An -> C

Las reglas estarán expresadas mediante lógica de predicados de primer orden (http://es.wikipedia.org/wiki/L%C3%B3gica_de_primer_orden).


Es decir tenemos un conjunto de reglas, y un conjunto de hechos (percepciones y medidas sintetizadas a partir de las percepciones), y a partir de esta base de conocimiento, deducimos la acción a realizar.

R |= A ( " Del conjunto de reglas, se deduce la acción ")

En la fórmula de ejemplo (1)La P representa la prioridad, los Ai son los antecedentes ( condiciones que provienen de cálculos y análisis de las percepciones) y C será la acción consecuente.
Las reglas serán tanto simbólicas, como no simbólicas (es decir, representaremos valores tanto con cadenas de letras -- cerca, lejos, etc- como con valores numéricos - 20, 10, etc- según el caso).

El funcionamiento es como se describe a continuación:
Inicialmente leemos el fichero o la base de datos en la que tengamos las reglas almacenadas.
A continuación se ordenan por orden de prioridad (0...N).
El motor se activará cada vez que se detecte algún rival mediante los sensores de oponentes.
Una vez activado, se pasará a un bucle en el que se irá evaluando cada regla, y en el momento que sean verdaderos todos los antecedentes, se seleccionará dicha regla y se disparará la acción consecuente ( la acción estará compuesta por 3 acciones propias de Torcs -aceleración,frenado y dirección).

La evaluación de la regla consistirá en analizar la regla mediante un parser, tokenizando cada antecedente y comprobando que su valor sea cierto para el instante actual. Si todos los antecedentes son ciertos, entonces la regla será evaluada como verdadera y será seleccionada.
A continuación una vez seleccionada, se analizará la parte consecuente y se enviará el conjunto de acciones al cliente.

El controlador fuzzy consistirá en diseñar un controlador difuso de tipo Mamdani, en el que las reglas representarán etiquetas con grados. En próximas entradas se describirá con más precisión y de forma práctica, ya que la teoría en la que se basa es algo tediosa.

El cerebro, en realidad ya existe desde hace varias versiones, es la lista de todas las percepciones tomadas en cada instante.

sábado, 19 de marzo de 2011

Finalizando GUI y comienzo de módulo de IA

En la versión actual del proyecto, la interfaz gráfica ya está casi finalizada, solo quedan por pulir errores menores de refrescos, y se han añadido algunos componentes nuevos:

-Un gráfico que muestra las direcciones tomadas por el vehículo; ésto se hará representando un volante.



-Representación de las de gráficas de las acciones (aceleración, frenado, dirección). Para ello ha sido necesario implementar un nuevo parser para la recepción de acciones. En la versión actual está configurado para recibir las acciones por parte del cliente, pero en futuras versiones, las acciones serán las que se determinen en el módulo de IA.

- Permitir cargar/guardar logs en .xls.


-Ajuste de escalas en las gráficas (por ejemplo en la gráfica de aceleración, la escala era demasiado grande).


-Cálculo del radio de curvatura a partir del radio de la circunferencia de la curva. Este punto ya es trivial, ya que en la versión anterior tenía ya calculado el radio de la circinferencia. Ahora simplemente tengo que hacer la inversa de este valor para obtener el radio de curvatura.

Radio curvatura=1/Radio circunferencia.

Cuánto menor sea el valor del radio de curvatura, significará que la curva es más abierta.

-Se ha mejorado también en esta versión el sistema de detecciones de curvas, ahora en vez de calcular las medias de los sensores derecho, central e izquierdo, simplemente se calculará cuál es el sensor que indica la máxima distancia, y ese sensor nos determinará hacia dónde va la curva o si se trata de una recta el entorno percibido.

-Se ha implementado los botones "Abrir fichero", "Opciones" y "Ayuda". El botón abrir fichero muestra una ventana desde la que se puede seleccionar un fichero .xls con datos a cargar. El botón opciones permite seleccionar si se desdea guardar o no un log de la carrera y también se puede seleccionar la ruta dónde se creará. El botón ayuda muestra una breve guía explicativa sobre las funciones de la aplicación.





También se ha comenzado 2ª fase del proyecto, el diseño e implementación del módulo de Inteligencia Artificial :
Este módulo constará de una serie de reglas con prioridad modificable que serán ejecutadas según la decisión que tome el motor de selección de reglas.
Las reglas se leerán desde ficheros externos Excel y estarán formadas por etiquetas booleanas.




Cuando se avance más en este módulo se explicará en má detalle.


Saludos.

lunes, 14 de marzo de 2011

Últimos avances

Después de haber pasado la época de exámenes, de nuevo he conseguido poder avanzar en el PFC.
En esta nueva versión hay múltiples cambios, mejoras y componentes nuevos, que describiré a continuación.
Resumiendo, he desarrollado los siguientes puntos:

  1. Mapa aparte
  2. Controles de reproducción centralizado para todas las pestañas.
  3. Colores en las gráficas VRA
  4. Cálculo del pequeño radio de distancia que hay desde el centro de la circunferencia formada por los sensores de distancia a cualquiera de los sensores.
  5. Corregir parpadeos en los gráficos.

Mapa aparte
---------------
Hay una nueva pestaña en la que se dibuja el mapa del circuito a la vez que se ejecuta la carrera.
Para pintarlo me baso en la estructura Entorno. Esta estructura contiene una cadena que define el tipo de entorno reconocido, así como el radio de curvatura en caso de ser una curva el entorno reconocido ( -1 si no es curva o es desconocido), y también contiene una estructura con el ciclo completo.
A partir de esta información se puede ir reconstruyendo una aproximación al circuito.
Tengo el problema de que al solo estar almacenando cambios de entorno, no sé con precisión cómo de larga tengo que representar por ejemplo una recta. En una siguiente versión este punto se mejorará. Quizá una posible solución sea almacenar los entornos de cada instante, y no solo en los instantes de cambio de entorno.

Controles de reproducción
----------------
Se ha independizado la barra de controles del resto de pestañas. Ahora aparece debajo de todos los paneles de pestañas, y cuándo se produce un evento relacionado con esta barra quedan afectados los paneles de gráficas VRA y el panel de telemetría.

Colores en las gráficas VRA
------------------
Una novedad importante es la mejora de la pestaña "gráficas". En esta pestaña se representan la velocidad, las revoluciones por minuto y la aceleración (de ahí el nombre VRA, para abreviar). Para cada vuelta, se representan las gráficas con un color distintos y cada vez que comienza una nueva vuelta se empieza a pintar desde el extremo izquierdo de cada gráfica. Una vez que ha terminado la ejecución, se puede seleccionar el instante deseado desde la barra de reproducción, señalándose en cada gráfica VRA el instante mediante una línea vertical negra. Esto último ha sido bastante costoso de implementar, he tenido que usar 2 búferes de imágenes, con la idea de que en el momento previo a pintar la línea vertical de marcado, se pintase de nuevo las gráficas con el estado que tenían al finalizar la ejecución, apareciendo así la ilusión de que se mueven las líneas verticales al mover el control de reproducción.
También se han incluído en esta pestaña varias cajas de texto, que muestran la distancia desde la salida, la velocidad , las revoluciones por minuto y la aceleración para un instante seleccionado.

Cálculo del radio de la circunferencia formada por los sensores de distancia
--------------------------------------------------------------------------
Esta parte está comentada en la entrada anterior.


Corrección de parpadeos en los gráficos
---------------------------------------
Para evitar que las actualizaciones de los gráficos interfieran entre las distintas pestañas solapándose, se ha empleado fundamentalmente el método setVisible(boolean v) . Al cambiar de pestaña se activan/desactivan los paneles adecuados.

Otras mejoras
-------------------
Otra mejora que he desarrollado ha sido la refactorización del código fuente, se han creado las clases MemGraficas y GraficasVRA.
La clase MemGraficas se ha utilizado para tener un histórico sobre qué coordenada x, velocidad, rpm, aceleración y nº de vuelta corresponde a cada tick (muestreo). Esta estructura es de gran utilidad cuándo hay que marcar instantes en las gráficas.

La clase GraficasVRA la diseñé para equilibrar la cohesión y el acoplamiento de la clase GUI_Telemetria, que ya estaba teniendo demasiada responsabilidad y se estaba dificultando la comprensión del código. Esta nueva clase tiene la responsabilidad de todas las operaciones de refresco, pintar un nuevo instante, representación de marcado, etc de las gráficas VRA.

A continuación incluyo una captura de la versión actual:


Un saludo y hasta la próxima actualización.

viernes, 28 de enero de 2011

Cálculo del radio de la semicircunferencia de los sensores

En la última reunión con mi director de proyecto, estuvimos comentando que los sensores no parten de un mismo punto, sino que est´distribuidos formando una semicircunferencia; de ahí que no se representasen bien las distancias en el gráfico de telemetría cuándo el coche estaba en una recta, ya que estuve considerando que todos los sensores partían del mismo punto.
Surgió entonces un nuevo problema: es necesario calcular el radio de esa pequeña circunferencia para poder representar correctamente las distancias que hay desde el centro de dicha circunferencia.

Después de pensar varias estrategias sobre cómo calcular el radio formado por los sensores, di con esta solución:

La componente "x" de cada distancia en coordenadas polares de la zona de los sensores de la derecha (o izquierda) es la misma cuándo el coche está en una recta. Esto se observa mejor en la siguiente imagen que he diseñado en Photoshop para ilustrar la solución:

Matemáticamente ya tengo resuelto este problema, pero ahora hay que trasladarlo a TORCS, y hay un pequeño problema, que es que para aplicar ésto el coche tiene que estar paralelo al eje de la carretera (trackAngle = 0 ó lo más cercano posible).

He obtenido estos resultados en rectas largas de diferentes circuitos:
ángulo: 1.71836E-4 9.90371 19.8133 RADIO:6.733958448107313
ángulo: 0,000171836 RADIO:6.733958448107313

ángulo 9.63449E-4 Sensor0º:9.15691 S40º:18.3444 RADIO:6.2490239668582515
ángulo 9.64467E-4 Sensor0º:11.963 S40º:23.9661 RADIO:8.164038600679886
ángulo -9.91996E-4 Sensor0º:11.9658 S40º:23.8905 RADIO:8.092102355791852
ángulo 3.01992E-7 Sensor0º:6.66667 S40º:13.3333 RADIO:4.52927539845111

Parece ser que el valor del radio está alrededor de 6.5 , pero tengo que realizar más pruebas para comprobarlo. En el caso de no conseguir un rango más pequeño de variaciones del radio, creo que habría que tomar la media de radios conseguidos, aunque en teoría el valor del radio debe ser exacto.

Saludos.

domingo, 23 de enero de 2011

Geometría y Álgebra

Por fin he conseguido calcular el centro de las circunferencias de las curvas.
Apliqué la idea que escribí en el comentario del post anterior con unos resultados excelentes. Finalmente resolví el sistema de ecuaciones mediante la regla de Cramer. Hice una prueba ayudándome de Matlab para representar gráficamente lo que obtenía en Java y aquí está el resultado :
Como se puede observar, he conseguido una circunferencia que pasa por 3 puntos de forma exacta, y ya he cumplido mi objetivo de poder obtener el centro de la circunferencia, y de ahí la distancia a uno de los puntos, con lo que tengo el radio de la curva.
Ahora me queda integrarlo con el módulo de telemetría, pero ya la parte más dura está conseguida.
Para conseguir ésto, me basé en fórmulas de Geometría y de Álgebra, y tengo que decir que no encontré ninguna librería en Java adecuada a mis necesidades y tuve que diseñar todas las funciones geométricas necesarias (construcción de ecuaciones de rectas dados un punto y una pendiente, cálculo de distancias euclídeas, cálculo del punto medio, cálculo de recta perpendicular), así como implementar un módulo para resolver ecuaciones 2x2 mediante Cramer.

sábado, 1 de enero de 2011

Novedades y correcciones

Tras el parón navideño, he comenzado a modificar varias cosas en el proyecto. He estado modificando la interfaz, ahora la ventana contendrá 2 pestañas, una para las gráficas de velocidad, RPM y aceleración y otra pestaña para la telemetría.
Además estas gráficas las diseñaré desde 0, ya que las que diseñé con la librería JFreeChart tienen el problema de que no se podía modificar la variable del eje X, e interesa poder modificar ese eje para representar la distancia desde la salida en él.

Por otra parte, la idea que comenté en la entrada anterior no era correcta, ya que lo correcto es calcular el radio de curvatura para ver lo abierta o cerrada que es una curva. Para ello emplearé fórmulas matemáticas de Geometría, tales como la fórmula para calcular una circunferencia dados 3 puntos. Imaginando que estos 3 puntos son A,B y C ésto consistiría en calcular la mediatriz entre los puntos AB y también BC. El punto dónde se corten las mediatrices será el centro de la circunferencia, y sabiendo el centro ya si se podrá calcular el radio (y por tanto sabremos la curvatura, a más radio será mas abierta).

También, como era de esperar, me han surgido nuevos problemas en la interfaz:
- El gráfico de telemetría aparece también en la otra solapa de gráficas por algún problema de refresco.
-Tengo que tomar una decisión sobre qué hacer cuándo la gráfica de velocidad (y de RPM y aceleración) lleguen al límite derecho del panel cuando lo represento. Lo ideal (pero que no se como implementarlo de momento), sería que se desplazase dinámicamente tal y como sucedía con la librería JFreeChart. También he pensado que otra solución sería que cuándo llegue al borde del panel, comience a pintar de nuevo desde el principio, en el borde izquierdo. Y otra posible solución sería que fuese scrollable (algo parecido a la idea que tenía para representar el mapa, pero que no funcionaba también por problemas de refresco).


Además de estas correcciones, también tengo que comprobar como están espaciados los sensores del coche, ya que parece ser que no parten todos desde el mismo punto.

Saludos.