Bump-Go en RobotC

Bump&Go2En el artículo de hoy voy a explicar el Bump Go en RobotC. El Bump Go es un programa en el que el robot se mueve aleatóriamente por una habitación esquivando obstáculos cuando los detecta. Puesto que el movimiento es aleatorio llegará un momento en que se haya movido por toda la habitación. Este tipo de robot ya existe, y tiene uso comercial, como la aspiradora Roomba, que es capaz de aspirarte la casa automáticamente.

El Bump&Go es un programa bastante sencillo que se puede implementar de varias maneras, en nuestro caso lo haremos con sensores de contacto. A diferencia del de LeJOS, este lo haremos con dos sensores de contacto, para tener una mayor precisión. Como montaje recomiendo un tribot modificado, de manera que el parachoques quede mirando hacia adelante y no no en diagonal como el montaje estandar de tribot del del LEGO Mindstorms NXT. pero no es muy difícil de implementar.

Manejo básico de los motores:

Vamos a hacer un pequeño recordatorio del manejo de motores en RobotC. La forma más sencilla de manejar los motores era mediante la función motor:

motor[nombre_motor] = int potencia: Ponemos el motor deseado (MotorA, MotorB, MotorC, o motores que hayamos definido nosotros mismos) a la potencia indicada. Potencias negativas significan que el motor rotará en sentido contrario, y una potencia de 0 parará el motor.

Si queremos que el motor A se mueva hacia adelante a máxima potencia sería:

motor[motorA] = 100;

No serán necesarias más funciones para este programa.

Manejo del sensor de contacto:

El sensor de contacto es el más simple de los sensores del NXT. Básicamente tiene dos estados, pulsado o sin pulsar. Por tanto la función que se utiliza para determinar su estado devolverá un booleano con true en caso de que esté presionado, o false en caso contrario. Lo primero que necesitamos hacer es definir los puertos a los que van anclados dichos sensores, esto se hace de la siguiente manera:

#pragma config(Sensor, puerto, nombre, tipo_sensor): Anclamos el sensor del tipo deseado al puerto que elijamos, utilizaremos el nombre que le hemos dado aquí para referirnos a el dentro del programa.

Si quisiésemos poner dos sensores de contacto, en los puertos 1 y 2, se haría de la siguiente manera:

#pragma config(Sensor, S1, contacto1, sensorTouch)
#pragma config(Sensor, S2, contacto2, sensorTouch)

Una vez definidos podremos utilizarlos. Se usa la función SensorValue(nombre_sensor) para tomar el valor del sensor. En este caso nos devolverá un booleano, por lo que podríamos utilizarlo en las condiciones de los bucles o de las sentencias selectivas if. Un ejemplo sería:

if (SensorValue[contacto1]){

Bump&Go1

Bump&Go:

Bump&Go es un robot móvil que se mueve erráticamente por una habitación o piso, esquivando cualquier obstáculo que encuentre a su paso. En este caso, y dado que usaremos el sensor de contacto, podemos decir que más que esquivar lo que el robot irá haciendo cada vez que colisione con un obstáculo es dar marcha atrás y girar para encontrar otra posible ruta sin obstáculos. Puesto que contamos con dos sensores de contactos podemos tener en cuenta si se ha presionado uno, otro o los dos, para saber a donde girar para esquivar dicho obstáculo. Si queremos además que el giro sea un número aleatorio de grados, usaremos la función matemática random(max) de RobotC, que nos devuelve un número aleatorio entre 0 y max. Suponiendo que queramos un rango entre un número distinto de 0 y el máximo que elijamos no tendríamos más que sumarle nuestro valor min, por ejemplo:

int aleatorio = 1000 + random(5000);

Nos devolveria en aleatorio un valor entre 1000 y 6000.

Puesto que su comportamiento va a ser aleatorio, está claro que será capaz de recorrer una habitación entera. Es solo cuestión de tiempo el que lo logre. Implementado así es un tipo de navegación muy simple, y tiene la ventaja de no exigir la necesidad de ningún sistema de localización, puesto que al tratarse de un movimiento aleatorio no se requiere conocer la posición del robot. (Versiones más avanzadas permiten que el robot pueda volver a la base para recargar las baterías. El problema de volver a una ubicación determinada sí requiere de un sistema más evolucionado).

El programa en RobotC sería:

#pragma config(Sensor, S1, contacto1, sensorTouch)
#pragma config(Sensor, S4, contacto4, sensorTouch)

#pragma platform(NXT)

task main(){
int tiempoMA, tiempoGiro;

while(true){
motor[motorB] = 100;
motor[motorC] = 100;

if (SensorValue[contacto1]){
tiempoMA = 200 + random(300);
motor[motorB] = -100;
motor[motorC] = -100;
wait1Msec(tiempoMA);
tiempoGiro = 200 + random(400);
motor[motorB] = 0;
wait1Msec(tiempoGiro);
}

if (SensorValue[contacto4]){
tiempoMA = 200 + random(300);
motor[motorB] = -100;
motor[motorC] = -100;
wait1Msec(tiempoMA);
tiempoGiro = 200 + random(400);
motor[motorC] = 0;
wait1Msec(tiempoGiro);
}

}
}

A continuación explicaré las lineas más importantes:

13 – En mi caso el contacto1 esta en el lado derecho del parachoques, teniendo en cuenta esto:

14 – Calculamos un tiempo aleatorio de milisegundos para dar marcha atrás, este número estará entre 200 y 500 milisegundos.

15, 16 y 17 – Damos marcha atrás durante el tiempo deseado.

18 – Calculamos un tiempo aleatorio de giro en milisegundos, este número estará entre 200 y 600 milisegundos. Por supuesto los tiempos los elegís vosotros, quizás os venga mejor otro número para vuestro robot.

19 y 20 – IMPORTANTE, aquí giramos el robot hacia la izquierda (motorC es dondo está mi rueda izquierda, al rotar marcha atrás el robot girará hacia la izquierda). Hacemos esto lógicamente porque nos hemos chocado por la derecha, por lo que es la mejor manera de esquivar el obstáculo.

23 a 31 – Repetimos el proceso, pero en este casi si nos hemos chocado por la izquierda. Por tanto el robot después de dar marcha atrás girará hacia la derecha.

Todo esto está dentro de un búcle infinito. En caso de que se presionen los dos sensores a la vez se ejecutará el primer if, como si hubiera chocado por la derecha. En realidad nos es indiferente en este caso.

En resumidas cuentas lo que hace este programa es que el robot ande marcha adelante hasta chocarse con un obstáculo; entonces dará marcha atrás, girará en una dirección determinada según que sensor de contacto haya sido presionado un número aleatorio de grados, y seguirá otra vez moviéndose adelante. El robot solo detendrá la ejecución del programa cuando presionemos el botón ESCAPE del NXT. Aquí os pongo un vídeo demostrativo con el mismo programa que os he escrito en el artículo (recordad hacer un buen parachoques o puede que se os atasque):

Si tenéis alguna duda podéis postearla en el foro.

Comments are closed.