Tec de Monterrey Campus Cuernavaca Robot Evasor de Obstáculos Materia: Robótica Inteligente Profesor: Dr. Enrique Sucar Equipo: Andrés Corral Julián Tame Moisés Memije Cuernavaca, Mor., a 11 de Marzo de 2002 Planteamiento del problema. Se desea participar en la categoría de evasión de obstáculos del concurso de robótica que se realizará en la Ciudad de México. Dicha categoría consiste en colocar en una pista con obstáculos un robot que no exceda las dimensiones de 210mm X 300mm y que deberá llegar hasta una zona de meta guiado por un emisor de luz infrarroja. La pista medirá aproximadamente 2m X 3m y en ella habrán obstáculos cilíndricos de un diámetro de 25mm y una altura de 150mm. La distancia mínima entre obstáculos será de 350mm. La fuente de luz infrarroja estará a 200mm de altura y emitirá a 40kHz. El robot no podrá derribar ningún obstáculo y ni salir de la pista porque sería descalificado. El recorrido se deberá hacer en menos de 4 minutos y se considerará que el robot ha llegado a su destino cuando todos sus puntos de apoyo hayan superado la línea de meta. Objetivos. Los objetivos de esta primera etapa en el desarrollo del robot son los siguientes: Elección de plataforma y arquitectura. Finalizar todo el diseño mecánico y de sensores. o Probar el buen funcionamiento del vehículo y sus sensores, para poder dar una estructura preeliminar del software. Armar la pista con obstáculos y crear un circuito emisor de infrarrojos para la meta según las especificaciones del concurso. Realizar algunas pruebas iniciales con el software de programación del PPRK. Elección de plataforma y arquitectura. Se tenían 2 opciones: armar un robot con los componentes LEGO Mindstorms o bien utilizar uno de los robots PPRK (Palm Pilot Robot Kit). Se decidió utilizar un robot PPRK por su versatilidad a la hora de moverse y porque nos daba la oportunidad de agregarle más sensores además de los que trae incluidos. Otra ventaja de este robot es que se controla por medio de un dispositivo Palm, lo que nos da una muy buena capacidad de cómputo. El PPRK es una plataforma con arquitectura fija a diferencia de el LEGO, asi que no tuvimos que hacer mucho mas que ensamblar el PPRK. Diseño mecánico y de sensores. En cuanto a la mecánica, con esta plataforma no tenemos mucho de donde escoger, además el robot no se modificara para cumplir su objetivo. Pensamos que la configuración mecánica que tiene le permite realizar las funciones necesarias para el concurso de evasión de obstáculos. Una observación clave es que el PPRK esta en el limite de tamaño, por lo que la implementación de nuevos sensores se dificulta. Se decidió finalmente utilizar los 3 sensores de proximidad que incluye el PPRK además de otros 2 tipos de sensores: De choque. El robot tendrá “bumpers” en 2 de sus lados para poder detectar algún objeto cuando ya se está en contacto directo con él. Detector de infrarrojos a 40kHz. Servirá para detectar la meta y éste irá colocado en una especie de torreta que se proyectará hasta 20 cm del piso para poder detectar correctamente la meta. Respecto a los sensores, hicimos pruebas con los de proximidad, de detección de la meta, y de golpe. No hicimos pruebas con la brújula Dinsmore, ya que la interfaz aun no está lista. El sensor de la meta funcionó a la perfección. Al detectar sólo pulsos de 40 khz, se elimina la interferencia de la luz ambiental, pero al mismo tiempo se vuelve excesivamente sensible por lo que lo cubrimos con cartón negro para eliminar rebotes. Los sensores de proximidad funcionan a la perfección, detectan objetos entre 8 y 80 cm de distancia, con resolución de mas o menos 1 cm, pero su zona de detección es justo enfrente solamente. Los sensores de golpe funcionan a la perfección, un problema es que son 4 sensores y solo hay 2 entradas disponibles, por lo que se usará sólo una entrada para los cuatro, haciendo uso de un divisor de voltaje. Algoritmo preliminar. Antes de moverse y de tomar decisión alguna, el robot dará un tercio de giro sobre su propio eje y registrará los obstáculos próximos a él, el área libre y la meta. Teniendo toda esta información, el robot tomará la decisión de qué ruta tomar. Si por alguna razón ese sensado del medio fallara, siempre se contará con la información de los sensores de choque. Cada que el robot se mueva aproximadamente 80 cm, que es el alcance de los sensores, volverá a hacer un reconocimiento del lugar. Pista con obstáculos y emisor de la meta. Para armar la pista utilizamos las maderas del laboratorio y los postes azules que ahí tenían. Los pegamos a la pista de tal forma que no se cayeran fácilmente. La distancia mínima entre obstáculos especificada por el concurso es de 35 cm, nosotros pusimos todos los obstáculos separados por 35 centímetros y alguno por 32 centímetros, para probar nuestro robot en situaciones mas difíciles que las reales y así obtener un mejor rendimiento. Según las especificaciones del concurso, el emisor de la meta consta de 3 LED’s infrarrojos: uno al centro y los otros dos a cada lado del central separados por un ángulo de 40°, emitiendo un pulso de luz infrarroja a 40 Khz. Para hacer este emisor utilizamos un CI 555, como oscilador, dio buenos resultados. Utilizando este emisor y el receptor con las modificaciones finales, el receptor pudo detectar la meta a una distancia máxima de 5 metros con un error de más ó menos 4°. Software. El robot se programa en un editor llamado Code Warrior IDE, en el cual se crean los proyectos y se compilan. Se necesitan 2 librerías para poder ejecutar los programas en la Palm. MSL Runtime PALM OS (4i) MSL Runtime PALM OS (2i) Además se necesita un emulador de Palm para probar los programas antes de instalarlos en la Palm. Se recomienda probar en el emulador los programas antes de cargarlos a la Palm, ya que si no funcionan correctamente puede bloquear el dispositivo, se tendría que desarmar para desconectar la pila y se pudiera cargar la configuración de nuevo. Al compilar el proyecto se genera un .prc que es el archivo a instalar en el dispositivo. Pruebas de software. Tuvimos muchos problemas para hacer pruebas de software. Por una parte es difícil realizar todo esto por la falta casi total de manuales o guías. El conseguir las librerías y clases para poder controlar el PPRK también fue difícil ya que no siempre están disponibles en el sitio de PPRK. A la hora de compilar algunos programas pide librerías extras que no tenemos. Para probar que estuviera bien ensamblado y conectado el PPRK utilizamos algunos programas de ejemplo ya compilados y la prueba fue exitosa, nos sirvió para darnos una idea mas atinada acerca de la sensibilidad de los sensores. Programación Para empezar a crear una arquitectura específica para el robot evasor de obstáculos, se contaba con 3 paradigmas distintos: reactivo, deliberativo y mixto. Los dos primeros no suelen adaptarse muy bien por sí solos al problema en cuestión, por lo que se decidió que finalmente se utilizaría una arquitectura mixta para poder aprovechar las características de las otras dos, las cuales se adaptarán a nuestras necesidades específicas. La arquitectura planeada corresponde al siguiente algoritmo que pudiera ser implementado tentativamente en el robot: 1. 2. 3. 4. 5. 6. Buscar la meta. Mapear los obstáculos. Decidir hacia cuál obstáculo dirigirse. Ir al obstáculo. Rodear el obstáculo. Regresar al paso 1. Como no podemos confiar en la infalibilidad del algoritmo, se tiene además un sistema de emergencia activado por los parachoques del robot. En caso de que el robot tenga un choque, significaría que no fue guiado satisfactoriamente, por lo que habría que corregir la trayectoria haciendo nuevos cálculos. El robot tendrá 2 módulos de software: operación y emergencia. Operación. Emergencia. El módulo de operación se hará cargo de controlar el robot mientras éste no choque. En caso de que el robot chocara, se activaría el módulo de emergencia y al terminar su ejecución, regresaría al módulo de operación. Mediante el siguiente diagrama se pretende representar la funcionalidad del software del robot: Operación. Rodear obstáculo. Ir al obstáculo. Emergencia. Choque . Detener el robot. Elegir obstáculo. Mapear obstáculos. Buscar meta. Alejarse del obstáculo. De esta manera creemos que el robot se comportará de una manera muy robusta y así podremos tener una mayor probabilidad de éxito y menos posibilidades de ser descalificados por derribar los obstáculos de la pista. Software Estos son los módulos que hemos programado. void muevele(int a, int b, int c){ Drive(Vel_To_Value(a),Vel_To_Value(b),Vel_To_Value(c)); } int acm(int tiempo){ return(tiempo*100/15); } int agrados(int tiempo){ return(tiempo*100/36); } void inicializa(int ori){ ULong inicio2; DisplayIR(1, ori); int cosa=240-ori; Turn(Left,Slow); inicio2 = TimGetTicks(); while ( TimGetTicks() } StopRobot(); ori=240; < (inicio2 + agrados(cosa) ) ) { } void empareja(int ori){ ULong inicio2; Turn(Right,Slow); inicio2 = TimGetTicks(); while ( TimGetTicks() } ori=ori-60; StopRobot(); } < (inicio2 + agrados(60) ) ) { void cosachistosa(void){ ULong inicio2; int sen, sentido; int arreglito[4][10]; int orientacion; orientacion=240; //ciclo que asigna valores a las casillas según su desocupación y la de sus vecinos for (int i=1;i<pasos-1;i++){ if(arreglito[0][i]==0){ //cuando una casilla y sus 2 vecinas est·n libres, toma el valor de 6 if(arreglito[0][i-1]==0 && arreglito[0][i+1]==0){ buenas[0][i]=6; //cuando una casilla y una de sus vecinas est·n libres, toma el valor de 2 }else if( (arreglito[0][i-1]==0 && arreglito[0][i]==0) || (arreglito[0][i]==0 && arreglito[0][i+1]==0) ){ buenas[0][i]=2; }else{ //cuando solamente una casilla est· libre, toma el valor de 1 buenas[0][i]=1; } } if(arreglito[1][i]==0){ if(arreglito[1][i-1]==0 && arreglito[1][i]==0 && arreglito[1][i+1]==0){ buenas[1][i]=6; }else if( (arreglito[1][i-1]==0 && arreglito[1][i]==0) || (arreglito[1][i]==0 && arreglito[1][i+1]==0) ){ buenas[1][i]=2; }else{ buenas[1][i]=1; } } if(arreglito[0][i]==0){ if(arreglito[2][i-1]==0 && arreglito[2][i]==0 && arreglito[2][i+1]==0){ buenas[2][i]=6; }else if( (arreglito[2][i-1]==0 && arreglito[2][i]==0) || (arreglito[2][i]==0 && arreglito[2][i+1]==0) ){ buenas[2][i]=2; }else{ buenas[2][i]=1; } } //buenas[3][] es el renglón que se analizara y por eso se le suman todos los valores de buenas[][] buenas[3][i]=buenas[0][i]+buenas[1][i]+buenas[2][i]; //tamaño proporcional del ángulo de apertura central int aper=(pasos/4); //valor en el que empieza el ángulo de apertura central int dista=(pasos-aper)/2; //incrementa el valor de las casillas del centro if(buenas[3][i]>0 && (i> dista && i<dista+aper ) ){ buenas[3][i]++; } } //incrementa el valor de las casillas con "prioridad de lado" for(int i=0;i<(pasos/2);i++){ if(sentido==1){ buenas[3][i]++; buenas[3][i]++; }else{ buenas[3][i+(pasos/2)]++; buenas[3][i+(pasos/2)]++; } } int ondeando=5; int cuantofue=0; for(int i=0;i<pasos;i++){ if (buenas[3][i]>cuantofue){ cuantofue=buenas[3][i]; ondeando=i; } } //int mas=arreglito[1][pasos/2]; //calcula la distancia que hay que recorrer int distancia=arreglito[3][ondeando]+arreglito[4][ondeando]+arreglito[5][ondeando]; //coloca el sensor 1 frente a la direccion a la que se dirigir· Turn(Left,Slow); inicio2 = TimGetTicks(); int cualquiera=(cuantos*pasos)-(ondeando*cuantos); while ( TimGetTicks() < ( inicio2 + agrados(cualquiera) ) ) { } StopRobot(); orientacion=orientacion+cualquiera; //mueve el servo 1 a donde estaba el sensor 1 Turn(Right,Slow); inicio2 = TimGetTicks(); while ( TimGetTicks() < (inicio2 + agrados(60) ) ) { } StopRobot(); orientacion=orientacion-60; //inicia el movimiento del robot hacia la zona indicada Move(ToServo1); int inicio; inicio2 = TimGetTicks(); // int si=0; while ( TimGetTicks() < ( inicio2 + acm(distancia-10) ) ) { //calcula el tiempo que caminar· el robot segÝn la distancia //si los parachoques detectan algÝn contacto, entonces el robot retrocede if(Sensor(4)>40){ Move(RToServo1); inicio = TimGetTicks(); while ( TimGetTicks() } // < ( inicio + 100 ) ) { si=; StopRobot(); break; } } StopRobot(); //funciÛn que debe colocar al robot nuevamente en direcciÛn a la meta int cosa; cosa=240-orientacion; Turn(Left,Slow); inicio2 = TimGetTicks(); while ( TimGetTicks() } StopRobot(); < (inicio2 + agrados(cosa) ) ) { DisplayIR(1, orientacion); orientacion=240; //cambia la prioridad para dirigirse al lado contrario al que fue el robot la última vez sentido*=-1; } }