miércoles, 9 de marzo de 2011

Práctica 3 { parte 4: Comportamiento de ir hacia la luz evitando obstáculos}

En esta parte haremos que el robot siga la luz evitando los obstáculos que encuentre por el camino.

Evitaremos los obstáculos mediante el sensor de contacto, es decir, cuando choque con el objeto retrocederá y lo esquivará rodeándolo.

El montaje será el mismo que para la parte anterior, el robot con los dos sensores de luz y el de contacto.

Usaremos los comportamientos andar, luz y EvitarObs, explicados en entradas anteriores.

El "arbitro" para esta parte será el siguiente código:



import lejos.robotics.subsumption.Arbitrator;
import lejos.robotics.subsumption.Behavior;

public class LuzObs {
    public static void main(String [] args) {
      Behavior b1 = new Andar();
      Behavior b2 = new Luz();
      Behavior b3 = new Evitar();
      Behavior [] bArray = {b1, b2,b3};
      Arbitrator arby = new Arbitrator(bArray);
      arby.start();
    }
}

Aquí podemos ver el vídeo:

Práctica 3 { parte 3: Comportamiento de ir hacia la luz}

En esta parte el objetivo será que el robot vaya siguiendo una luz.

Se montará con dos sensores que nos han proporcionado los profesores para esta parte.

Aquí vemos una foto del montaje:




El funcionamiento es sencillo, si el sensor de la derecha capta más luz que el de la izquierda girará a la derecha y al revés.

Para ello seguiremos basándonos en comportamientos y usaremos andar y luz. (estos comportamientos están mostrados en la entrada anterior)

Como los sensores de luz que usamos son del robot anterior, tendremos que usar la clase lejos.nxt.addon.RCXLightSensor.


En el comportamiento luz nos declararemos luz derecha y luz izquierda de RCXLightSensor. También deberemos declararnos viajar de la clase TachoPilot.
Guardaremos los valores de luz del sensor en variables derecha/izquierda y compararemos para ver dónde debemos ir.
Con take control hacemos que entre al comportamiento si izquierda - dcha es mayor que 30 o al revés.
En supress lo que haremos será que se pare, y la acción será que si el de la izquierda tiene más luz de la derecha gira a la izquierda, y si el de la derecha tiene más luz que el de la izquierda, irá a la derecha.



El "árbitro" será SeguirLuz y el código es el siguiente:



import lejos.robotics.subsumption.Arbitrator;
import lejos.robotics.subsumption.Behavior;

public class SeguirLuz {
    public static void main(String [] args) {
      Behavior b1 = new Andar();
      Behavior b2 = new Luz();
      Behavior [] bArray = {b1, b2};
      Arbitrator arby = new Arbitrator(bArray);
      arby.start();
    }
}

Aquí podemos ver el vídeo:

Práctica 3 { parte 2: Comportamiento de evitación de obstáculos usando el sensor de ultrasonidos}

En esta parte el objetivo será que el robot evite un obstáculo sin tocarlo. Para ello se hará uso del sensor de ultrasonidos, montado en la cabeza del robot.

No hemos logrado el objetivo pero ponemos aqui los avances:

Hemos creado un comportamiento EvitarUltra que es el siguiente:



import lejos.robotics.navigation.TachoPilot;
import lejos.robotics.subsumption.Behavior;
import lejos.nxt.*;

public class EvitarUltra implements Behavior {
    UltrasonicSensor sonar = new UltrasonicSensor(SensorPort.S4);
    TachoPilot viajar = new TachoPilot(5.6f,10.85f,Motor.C,Motor.B);
    int dist,menor,angulo;
    final double dx=70;
    final double dy=70;
    double ox,oy,rx,ry,df;
    public boolean takeControl() {
      sonar.continuous();
      dist=sonar.getDistance();
      return dist< 30;
    }
    public void suppress() {
      viajar.stop();
    }
    public void action() {
      viajar.stop();
      Motor.A.rotate(-45);
      sonar.continuous();
      menor=sonar.getDistance();
      while(Motor.A.getTachoCount()< 45){
        Motor.A.rotate(5);
        dist=sonar.getDistance();
        if(dist< menor){
          menor=dist;
          angulo=Motor.A.getTachoCount();
        }
      }
      Motor.A.rotateTo(0);
      oy=Math.sin(Math.toRadians(angulo))*menor;
      ox=Math.cos(Math.toRadians(angulo))*menor;
      rx=ox+dx;
      ry=oy+dy;
      angulo=(int) Math.atan2(ry, rx);
      df=Math.sqrt(rx*rx+ry*ry);
      viajar.rotate((float) Math.toDegrees(angulo));
      viajar.travel((float) df);
      viajar.rotate((float) Math.toDegrees(-angulo));
    }
}

Este comportamiento junto con el andar (comentado en entradas anteriores) será utilizado por el arbitro siguiente:



import lejos.robotics.subsumption.Arbitrator;
import lejos.robotics.subsumption.Behavior;

public class UltraObs {
    public static void main(String [] args) {
      Behavior b1 = new Andar();
      Behavior b2 = new EvitarUltra();
      Behavior [] bArray = {b1, b2};
      Arbitrator arby = new Arbitrator(bArray);
      arby.start();
    }
}

Pese a esto, no hemos conseguido el objetivo

Práctica 3 { parte 1: Comportamiento de evitación de obstáculos usando sensores de contacto}

El objetivo en esta parte será que el robot camine por el terreno, y cuando el sensor de contacto detecte un objeto lo esquive retrocediendo y haciendo un arco adecuado.

El montaje será el robot con las ruedas y un sensor de contacto en el centro como vemos en la foto:



En la parte del código, en esta práctica usaremos una nueva forma de programar el robot. Esta forma es mediante comportamientos.
Los comportamientos se heredan de la clase behavior. Hay que implementar tres métodos:
- boolean takeControl(). Devuelve verdadero si se dan las condiciones necesarias para que cierto comportamiento tome el control del robot.
- void action(). El código de este método se ejecuta cuando el comportamiento se activa.
- void suppress(). Este método debe terminar inmediatamente el código que
ejecuta el método action(). Puede terminarlo de inmediato (si es un bucle
infinito, o la ejecución es larga) o esperar a que termine, si la ejecución es
corta.

A lo largo de toda esta práctica vamos a usar los siguientes comportamientos:


>>Andar


import lejos.robotics.subsumption.Behavior;

import lejos.nxt.*;

public class Andar implements Behavior {

    public boolean takeControl() {

      return true;

    }

    public void suppress() {

      Motor.B.stop();

      Motor.C.stop();

    }


    public void action() {

      Motor.B.forward();

      Motor.C.forward();

    }

}



>>Evitar



import lejos.robotics.navigation.TachoPilot;

import lejos.robotics.subsumption.Behavior;

import lejos.nxt.*;


public class Evitar implements Behavior {

    TouchSensor touch = new TouchSensor(SensorPort.S4);

    TachoPilot viajar = new TachoPilot(5.6f,10.85f,Motor.C,Motor.B);

    public boolean takeControl() {

      return touch.isPressed();

    }

    public void suppress() {

      viajar.stop();

    }


    public void action() {

      viajar.stop();

      viajar.travel(-5);

      viajar.rotate(-90);

      viajar.steer(40,120);

      viajar.rotate(-45);


    }

}


>>Luz


import lejos.robotics.navigation.TachoPilot;

import lejos.robotics.subsumption.Behavior;

import lejos.nxt.*;

import lejos.nxt.addon.RCXLightSensor;


public class Luz implements Behavior {

    RCXLightSensor LuzIzda = new RCXLightSensor(SensorPort.S1);

    RCXLightSensor LuzDcha = new RCXLightSensor(SensorPort.S2);

    TachoPilot viajar = new TachoPilot(5.6f,10.85f,Motor.C,Motor.B);

    int Izda,Dcha,i;

    public boolean takeControl() {

      Izda=LuzIzda.getNormalizedLightValue();

      Dcha=LuzDcha.getNormalizedLightValue();

      return (((Izda-Dcha)>30)||((Dcha-Izda)>30));

    }

    public void suppress() {

      viajar.stop();

    }


      public void action() {

      Izda=LuzIzda.getNormalizedLightValue();

      Dcha=LuzDcha.getNormalizedLightValue();

      if ((Izda-Dcha)>30){

        viajar.rotate(5);


        if ((Dcha-Izda)>30){

          viajar.rotate(-5);

        }

      }
    }


    Para esta primera parte que consistía en esquivar un obstáculo usaremos andar y evitar, y el árbitro será obstáculos:

    Para el comportamiento evitar nos definiremos touch de la clase TouchSensor y viajar de la clase TachoPilot. En take control pondremos si está presionado el sensor para que de control al comportamiento. En supress haremos que el robot se pare, y en action haremos que se pare, retroceda y gire mediante el steer para bordear el obstáculo. Antes y después del steer usamos rotate para que el robot se oriente en su dirección de destino, es decir, que después de esquivar el objeto siga con la dirección que llevaba.



    Aquí podemos ver el código:



    import lejos.robotics.subsumption.Arbitrator;

    import lejos.robotics.subsumption.Behavior;


    public class Obstaculos {

      public static void main(String [] args) {

        Behavior b1 = new Andar();

        Behavior b2 = new Evitar();

        Behavior [] bArray = {b1, b2};

        Arbitrator arby = new Arbitrator(bArray);

        arby.start();

      }
    }

    Aquí podemos ver el vídeo del funcionamiento