LEJOS NXJ


DESARROLLO DE ALGORITMOS PARA EL NXT 

Creador: Ude

Web: MooGate

E-mail contacto: Ude

DIARIO: 

 

Práctica 3: Radar

Semana del

  • En esta parte de la practica hemos ampliado lo que nos pedia, ya que la practica solo pedia sacar por pantalla el escaneo de los ultrasonidos usando un nuevo motor.

              AMPLIACIONES DE LA PRACTICA ORIGINAL

  •    1) Para el desarrollo de estra practica hemos modificado el diseñor del robot para conseguir que la cabeza (ultrasonidos) tenga una libertad total.
  •    2) Através de los datos recogidos por el ultrasonidos podemos viajar por el mundo sin chocar contra los objetos, a traves de un algoritmo que hemos creado de fuerzas reactivas y atractivas.
  •   3) En el algoritmo usado para mover la cabeza 180º se ha creado un sistema de correccion, ya que para conseguir que la cabeza fuera muy rapido a veces descuadraba de los 1801, asi que se creo un control para posicionarse despues de una barrida donde debiera.
  •   4) Nuestro robot a traves de los 2 algoritmos implementados conseguira viajar por el mundo eligiendo la ruta donde haya menos obstaculos y por donde pueda viajar sin problemas.

                    DESARROLLO DE LA PRACTICA

  •     La practica se puede dividir en 2 partes:
  1. Algoritmo de radar.
  2. Fuerzas reactivas.

              RADAR 

  1. Algoritmo de radar.
  • Para que el radar girara de seguido y no grado a grado ( con el resultante efecto de ir dando tirones la cabeza), hemos utilizado la tacometria del motor.
  • Para comprobar que el valor del tacometro tras 180º hicimos varias pruebas con un programa externo que creamos. Una vez comprobado que 180º eran 180 pulsos para el tacometro nos dimos cuenta que esto nos resolveria muchos problemas a la hora de almacenar en el array la distancia y los grados.
  • En la parte del escaneo del radar hara 2 barridas de 180º, e ira introduciendo los valores de las distancias en la posicion del array que pertenezca al grado en el que ha recodigo el dato.
  • A la vez que recoge los datos, los imprime por pantalla. Para poder conseguir que imprimiera desde la parte dentral inferior cogiamos el valor del tacometro (que correspondia al angulo que estabamos ) y lo pasamos a radianes que es con lo que trabaja la libreria MATH.
  • Ya que nosotros teniamos las coordenadas polares y no las rectanguales con las que podriamos imprimir por pantalla, creamos un algoritmo para ello.

  x = (int)(distancia*(Math.sin (aradi)));    
                       y = (-1)*(int)(distancia*(Math.cos (aradi)));                 
 pantalla.drawLine(50, 64, x+50,y+64);

  • El echo de que cuando pintamos por pantalla la linea se posicione en el (50,64) es porque el eje superior izquiero es el (0,0) como se muestra en la imagen ed acontinuación.

     

  • Nuestra intencion es sacar lineas desde el (50,64) hasta donde el sensor de ultrasonidos nos diga.
  • La venta roja es el display que veremos desde robot.
  • Para conseguir que sacara la vision del robot como si fuera un sonar real, hicimos que cuando imprimiera, si la distancia era mayor a 50 pixeles solo pintara 50 de distancia (aunque dentro del array si guardara la distancia real). De esta forma el dibujo resultante por pantalla era como el de un avanico.

 

       - PROBLEMAS EN EL RADAR -

  •    Hubo serios problemas cuando hacia las barridas, ya que cuando barria del 0º a 180º y vicebersa, cuando llegaba al 180º no frenaba en seco,( lo que probocaba que se descuadrase nuestro centro (90º)).

  - SOLUCIÓN -

  • Para solventar esto, una vez que el algoritmo llegaba o pasaba de 180º se llamaba la funciona rotar para que cuadrara la cabeza para el siguiente barrido.

              FUERZAS REACTIVAS 

  1. Fuerzas reactivas.
  • Para decidir que dirección tomar hemos hecho un algoritmo que suma las fuerzas atractivas y repulsivas y con estas sacamos una fuerza resultante que es la dirección que tiene que tomar el robot .
  • El array de datos es de 180 posiciones siendo cada posición los grados en que se encuentra la cabeza. En cada posición del array guardas el valor del sensor de ultrasonidos que es el radio por lo que cada celda del array es una coordenada polar.
  • Para calcular las fuerza atractiva miramos cada posición del array si el valor recogido es mayor o igual que 30 pasamos la coordenada polar de esa posición del array a cartesianas y se la sumamos a la fuerza atractiva total en su coordenada x e y por lo que al final tendremos una fuerza atractiva total.
  • Para calcular las fuerza repulsiva miramos cada posición del array si el valor recogido es menor de 30 pasamos la coordenada polar de esa posición del array a cartesianas y se la sumamos a la fuerza repulsiva total en su coordenada x e y por lo que al final tendremos una fuerza repulsiva total.
  • Una vez obtenido la fuerza atractiva y repulsiva total en coordenadas cartesianas estas las sumamos y obtenemos la fuerza repulsiva que es la que nos da la dirección.
  • Una vez obtenido la fuerza resultante tenemos que girar el robot para donde nos indique la fuerza, esto lo hacemos pasando las fuerza resultante de coordenadas cartesianas a polares y así obtenemos el ángulo y podemos calcular el giro que tiene que hacer el robot.
  • Lo que se muestra a continuación es lo explicado anteriormente, visto graficamente. La primera resultante es A (proveniente de el calculo de la fuerza 1 y 2), la segunda es B (calculandola de la anterior A y 3), y por último la fuerza resultante por donde viajara es C ( de sumarle B y 4).

  • Una vez hecho todos estos cálculos y posicionado el robot  lo siguiente que hace es andar hacia adelante hasta que encuentre un objeto. Pero aquí nos surgía un problema y es que al tener el sensor de ultrasonidos tan adelante alguna veces no detectaba las latas de los lados y estas daban en las ruedas.
  • Para solucionar esto, hemos hecho que  mientras va para adelante la cabeza vaya girando de 15 en 15 grados para un lado y otro parando en el medio también, con esto conseguiríamos que detectara las latas de los lados.
En esta parte hemos tenido mucho problemas con los datos recogidos por el sensor ya que muchas veces no detectaba las latas y era debido a que justamente al ser la lata redondeada en su parte superior desviaba las ondas de lso ultrasonidos. 

  • Cuando encuentra un objeto se para el robot y vuelve a hacer el escaneo y recoger datos para calcular que dirección tomar según los datos recogidos.
  • El código de la practica es el siguiente:

 radar.txt

 

 

Práctica 2: Sigue líneas

Semana del 3-12 al ...

  • La practica se ha planteado no como un robot que constantemente pierda la línea y haga barridos para encontrarla. Esta solución plantea una serie de grabes problemas, como el caso que si al realizar el barrido encontrara otra linea colindante creeria que esa era la buena, además pensamos que la solucion de los barridos nos parecía poco eficiente.
  • Nuestra táctica se centra en no perder la línea en ningún momento, por ello se llevarán acabo 2 calibraciones para compensar en todo momento el nivel máximo y mínimo de luz.
  • Una vez conseguido el máximo y el mínimo de luz, el robot reconocera el color aproximado de la zona  blanca y el aproximado de la zona negra, ya que en varios puntos puede contener diferentes intensidad de blanco y de negro (por deficiendias del terreno).
  • La táctica planteada contiene un caso base y un segundo caso, que es el que se utilizará tras haber superado las condiciones del caso base.
  • El caso base es, la busqueda por primera vez de la línea negra, una vez encontrada ya no volvera a entrar en este caso.
  • Para que el robot no pierda nunca la línea llevara un control triple. Dónde esta en todo momento respecto al centro de la linea (guardando el anterior valor calculado), cual fue la direccion de la última curva. El tercer caso de control entraría si por algun motivo perdiera la línea .

 

 PROBLEMAS: 

  1. Rotaciones: 
  •  Inicialmente usamos para las rotaciones el "rotate", pero tenía un problema, si la rotación era grande hasta que no cumpliera los grados asignados no buscaria si estaba en la linea negra, y era muy probable que se pasara. 
  • Por el contrario si la rotación era muy pequeña tardaba demasiado en corregir.
  •  Después de hacer multiples pruebas y encontrar un punto medio, nos dimos cuenta que tampoco era efectivo, porque en muchos casos iva dando vandazos de un lado para otro y en otros casos se pasaba ligeramente la línea y giraba en redondo al lado contrario.
  •  Por ello preferimos usaran los forward y backward, que no solo era mucho más fácil a la hora de saber si estabamos en la línea. Sino que al no comprobar constantemente la rotación ( rotar-parar-rotar, lo cual probocaba que fuera dando saltitos), el uso del forward resultaba un movimiento fluido.

           b. Lectura del terreno: 

  • Uno de los problemas que teníamos es que el robot cuando encontraba una curva empezaba a dar bandazos, y pensabamos que era culpa de que el sensor de luz del robot era impreciso por el movimiento, por lo que probamos una solución reduciendo el número de veces que leía el terreno a la mitad, pero el problema no residia aquí, ya que muy al contrario de lo que pensabamos el sensor leia muy preciso y el problema lo solucionamos con lo que explicamos a continuación. 
  • Nuestro segundo gran problema vino al comprobar que el robot hacia un exceso de comprobaciones de cual era el valor del color. Esto venia dado porque el código no estaba depurado (sobraban lecturas,bucles y comprobaciones). Corregido esto, el robot no solo iva mas rapido y fluido, sino que además cometia menos fallos a la hora de seguir la linea.

          c. Hacia que lado sería el proximo giro. 

  • Hasta cierto punto, el código solo recogía que el robot siguiera la línea, almacenando cual era la  posición anterior del robot respecto al centro, pero no guardaba cúal era el anterior giro, corrigiendo esto, el robot se perdía menos ya que automaticamente presuponia que la proxima vez que girara, seria la misma  que para la ultima vez que giró.

         d. Perdida de la línea. 

  • El último problema a la hora de seguir la linea, era que en ciertos momentos el robot por situaciones puntuales perdía la línea, con lo cual hicimos una ultima comprobacion que corregia si recibia que la anterior posicion leida y la siguiente se encontraba completamente en zona blanca corrigiera al lado contrario. De esta forma solventabamos que no se diera la vuelta.

 

 ANÁLISIS: 

  • Hemos realizado un testeo para la demostración del rango de valores aproximado que toma.
  • Los valores son son del tipo: 1mm dato. Cada linea verde representa 1 mm separado de lo que reconoce como negro, en cuanto el haz rojo salga la linea azul clara empieza a contabilizar.
 

Milímetros separado del dato 0

Rango medio recogido por el lector de luz

1 mm

20

2 mm

35

3 mm

49

4 mm

64

5 mm

83

6 mm

91

7 mm

93

8 mm

95

 

 

  SOLUCIÓN Y EXPLICACIÓN: 

  • Realmente el robot pocas veces permanece en el centro y tampoco hay diferentes niveles de negro dentro de la linea, lo que ocurre es lo siguiente:

 

  •    El foco de luz rojo que proyecta no es milimetrico, de echo abarca exactamente 0,9 cm,  por lo cual mientras que el haz de luz este dentro de la línea negra,  marcará 0 ( ó el mínimo que hubiera calculado), cuando se separa un poco del centro recoge parte de la zona blanca del tablero y da un valor superior al testeado como valor central (el valor recodigo como negro).

  

  •  De esta forma, lo que el robot hace basicamente es: cuando se sale de la línea, lee un valor de la luz que recibe y la guarda, cuando gire para volver a la línea negra, lee otra vez y lo compara. Si es menor el nuevo dato, es que ha girado en la dirección correcta y guarda que dirección ha elegido, que no, gira a la otra dirección y guarda que esta nueva direccíon ha sido la buena.

Sigue_linea.txt 

 

Práctica 1: Bump & Go

Semana del 26-11 al 2-12-2007

  • Una vez familiarizados con el entorno de programación y habiendo concluido la practica 0 hemos iniciado la practica 1 cuyo enunciado se encuentra en la sección de enlaces de esta pagina.

Con sensor de choque:

  • En esta primera parte de la práctica tenemos que hacer que nuestro robot avance hasta que choque con algo y retroceda aproximadamente 30 cm y gire de manera aleatoria. Para ello se utilizaran dos motores y el sensor de choque.  
  • Diseñado el primer algoritmo, el robot avanza recto hasta que encuentra un obstáculo. Cuando choca, retrocede una distancias para un motor y gira sobre si mismo durante 1 segundo.
  • Aun nos faltan modificar para que solo retroceda 30 cm, que gire aleatoriamente y poner un segundo actuador de choque en la parte trasera.
  • Como problemas que han surgido, por alguna razón el robot va extrañamente lento mientras se desplaza, creemos que puede ser que este rozando la rueda con laguna pieza o tener baja la batería. 
  • Lo que pasaba es que no le habiamos dado una velocidad a los motores esto se hace con la función setSpeed.

  • En una segunda versión del algoritmo, el robot avanza para alante hasta que choca, retrocede y gira como antes pero ahora solo retrocede 30 cm aproximadamente y cada vez hace un giro diferente. 
  • Para que solo retroceda 30 cm hemos utilizado los valores de odometría del robot y más o menos hemos calculado cuanto sería este valor cuando ha recorrido 30 cm, como es marcha atras nos da un número negativo. Para saber los valores de odometría hemos utilizado la función getTachoCount(). 
  • Para que cada vez que girara lo hiciera con un ángulo diferente hemos utilizado la función random que nos recomiendan en el enunciado de la práctica. Esta función devuelve un numero aleatorio entre 0 y 1 cada vez que se ejecuta, para que nos de un valor entre 45 y 315 como nos piden en el enunciado al valor de random hay que multiplicarlo por 315-45 y a eso sumarle 45. Habiendo obtenido este valor solo hay que pasarselo directamente a la funcion rotateTo() para que gire el motor hasta el angulo que le pasamos.   
  •  Hemos tenido un problema porque el robot cuando iva hacia adelante se giraba un poco esto era debido a que como tenemos un bucle while aunque el robot fuera hacia adelante ejecutabamos siempre forward() y esto hacia que se girara el robot, para solucionarlo antes de ejecutar forward miramos si el robot ya va para delante con la instrucción isForward() asi solo la ejecutabamos solo si hacia falta.
  • La primera parte de la practica Bump & Go queda terminada y el codigo es el siguiente:
 
Con sensor de ultra sonido: 
  • En esta segunda parte de la practica hay que hacer practicamente lo mismo que en la primera lo unico que el robot no tiene que llegar a chocarse para ello utilizamos el sensor de ultra sonido con el que podemos detectar los objetos sin chocarnos.
  • En esta segunda pate hemos tenido menos problemas ya que el codigo es practicamente el mismo menos una instrucción por lo que nos ha llevado poco tiempo terminarla.
  • El codigo de esta segunda parte es el siguiente:
     
     
Versión mejorada:
  • Se ha ampliado la práctica  montando un segundo actuador de tipo choque en la parte trasera del robot, ya que en muchos casos cuando retrocedia, si tenía una pared detras golpeaba contantemente hasta haber recorrido los 30 cm., para ello hemos incluido un segundo sensor que consigue solventar este problema.
  • También se ha ampliado haciendo que no siempre rote a la derecha o a la izquierda, sino que rote cada vez a un lado.
  • Tubimos un serio problema ya que por alguna razon cuando subimos el ultimo programa, resultaba que cuando lo lanzabamos en el robot, la pantalla salian un monton de letras y números. Para ver que podia ser quisimos probar un programa anterior y  también fallaba. Para solucionarlo borramos todos los programas y volvimos a meterlos, de esta forma solventamos el problema.
  • El código de la primera parte de la practica con dos sensores de choque uno en la parte delantera y otro en la parte delantera del robot sería el siguiente.
  • El código de la segunda parte de la practica mejorada con el sensor de ultra sonidos en la parte delantera y un sensor de choque en la parte trasera del robot sería el siguiente.

US_Choque_1.txt

Segunda versión mejorada:

  • También se ha ampliado haciendo que no siempre rote a la derecha o a la izquierda, sino que rote aleatoriamente a la derecha o a la izquierda.
  • El código de la primera parte de la practica con dos sensores de choque uno en la parte delantera y otro en la parte delantera del robot sería el siguiente.
  • El código de la segunda parte de la practica mejorada con el sensor de ultra sonidos en la parte delantera y un sensor de choque en la parte trasera del robot sería el siguiente.
 

 

Práctica 0: 

Semanas del 12-11 al 16-11-2007 y del 19-11 al 23-11-2007 


  • Inicialmente se han tenido problemas con el gedit .bashrc ya que para mi caso (Eduardo) que no he dado linux desconocía como funcionaban los export ,el PATHy las variable de entorno. Solucionado ese apartado, en la laboratorio donde se llevan acabo las practicas no ha habido ningún problema mas, pero, para poder trabajar desde casa aun se nos plantean varios problemas. Ya que no se consigue encontrar la misma versión de java de la cual se dispone en la sala de libre. 
  • Una vez solucionado los problemas anteriores hemos empezado la practica 0 cuyo enunciado esta en la sección de enlaces de esta pagina. Hemos hecho una primera versión en la que los valores mostrado son los correctos pero al cabo de unos segundos salta un excepción, esta salta debido a que se agota la memoria del robot, esto es a que dentro del bucle teníamos instrucciones como drawString("...string...",0,0); esto lo que hace es crear cada vez que se ejecutaba un nuevo string en memoria del robot por lo que al final se agotaba.
  • Para solucionarlo hemos definido variables estáticas con lo que la instrucción quedaría de la siguiente manera:
 drawString(varableEstatica,0,0);

  • Otro problema que teníamos, era  que daban valores erróneos por pantalla cuando recibía por el sensor de luz y del ultrasonido, venían dados porque en el bucle, no hacíamos un clear de pantalla cada vez que mostrábamos, creyendo que solo con el refresh valía.
  • Para solucionarlo hemos añadido la instrucción LCD.clear(); al principio del bucle solucionando asi este problema.
  • Una primera versión de nuestro código sería la siguiente: