torsdag den 8. marts 2012

Lab 6


Date: 8. march 2012 & 13.march 2012
Duration of activity: 6 hours
Group members participating: Thomas, Stefan and Jeppe

Goal
  • Build three variations of the Braitenberg robots.1) One that is attracted to sound.2) One that is afraid of silence (it goes backward when it is quiet).
    3) A robot that is afraid of light (turns away when it senses light).
Plan

Vehicle 1 Assignment
Start with vehicle 1. As sensor use a soundsensor to implement a vehicle that moves faster forward the louder the environment sound is.
Use two motors to drive the vehicle and apply the same power to the two motors. The main issue is how to map sensor values to motor power. If raw sensor values are used, the mapping should be from the range 0, 1023 to the motor power range, i.e. 0, 100.
Also try to map to motor powers between -100,100 and interpret negative motor powers as moving the motors backwards. How would you describe the resulting behaviours?

Vi startede med at lave en robot, i følge arbejdstegningerne 9797 side 8-22. På robotten placerede vi desuden en lyd-sensor, som pegede frem foran robotten. Vores robot fik uploadet følgende program til sig:

public static void main(String [] args)throws Exception {
  //exitlistener
  Button.ESCAPE.addButtonListener(new ButtonListener() {
    public void buttonPressed(Button b) {
      System.exit(0);
    }
    public void buttonReleased(Button b) {}
  });
  int first_reading = SensorPort.S1.readRawValue();
  int min = first_reading;
  int max = first_reading;
  while (true) {
    int crr_sound = SensorPort.S1.readRawValue();
    crr_sound = 1023 - crr_sound;
    if (crr_sound < min)
      min = crr_sound;
    if (crr_sound > max)
      max = crr_sound;
    int power = (int) ((crr_sound / 1023F) * 100);
    LCD.clear();
    LCD.drawString("Crr:" + crr_sound,0,0);
    LCD.drawString("Max:" + max,0,1);
    LCD.drawString("Min:" + min,0,2);
    LCD.drawString("Power: " + power, 0, 3);
    LCD.refresh();
    MotorPort.A.controlMotor(power,1);
    MotorPort.B.controlMotor(power,1);
    Thread.sleep(250);
  }
}

Programmet tager raw value fra lydsensoren og mapper dissetil power værdier mellem 0 og 100. Vi observerede, at alle værdier i rawintervallet mellem 0 og 1023, så ud til at blive brugt – ved at kigge på max og min på displayet af robotten i løbet af vores forsøg. Raw værdierne var dog høje når der var næsten ingen lyd og små når der var meget støj. Dette var lige netop modsat af, hvordan vi ønskede at give motorerne power. Så derfor mappede vi raw value til power ved at tage 1023 (max raw værdien) og trække vores rawmåling fra denne. Dette gav høje værdier når støjen var stor og små når der var stille, som ønsket. For at få de mappede raw values i intervallet 0 til 100 dividerede vi disse med 1023 og gangede med 100.

Robotten bevægede sig ikke med mindre, der var ”meget” støj i nærheden af den. Vi skulle klappe højt eller snakke med høj stemme 5cm fra mikrofonen for at den bevægede sig. Vi kunne observere, at hvis vi ikke snakkede foran robotten, men bare lod baggrundsstøjen blive målt, at power værdien lå mellem 2-3. Hvis vi snakkede sammen 30cm fra robottens mikrofon lå power værdien i intervallet 20-29. Dette er som tidligere nævnt til forelæsning ikke nok til at overvinde den statiske friktion, der er mellem hjulene og underlaget.

Power mellem -100 og 100:
Med samme robot som i forrige sektion ændrede vi robottens program således at robotten bakkede, når der var stille og kørte fremad, når den opfangede lyder under 511 raw value. Dette gav anledning til følgende kode:

public static void main(String [] args)throws Exception {
  //exit listener
  Button.ESCAPE.addButtonListener(new ButtonListener() {
    public void buttonPressed(Button b) {
      System.exit(0);
    }
    public void buttonReleased(Button b) {}
  });
  SoundSensor s_sensor = newSoundSensor(SensorPort.S1);
  int first_reading = SensorPort.S1.readRawValue();
  int min = first_reading;
  int max = first_reading;
  while (true) {
    int crr_sound = SensorPort.S1.readRawValue();
    //split in middle of interval,high sounds gives positive crr_sound, low sounds
      gives negative crr_sound
    crr_sound = 511 - crr_sound;
    if (crr_sound < min)
      min = crr_sound;
    if (crr_sound > max)
      max = crr_sound;
    int power = (int) ((crr_sound / 511F) * 100);
    if (power > 0) {
      MotorPort.A.controlMotor(power,1);
      MotorPort.B.controlMotor(power,1);
    } else {
      power = power*(-1);
      MotorPort.A.controlMotor(power,2);
      MotorPort.B.controlMotor(power,2);
    }
    LCD.clear();
    LCD.drawString("Crr:" + crr_sound,0,0);
    LCD.drawString("Max:" + max,0,1);
    LCD.drawString("Min:" + min,0,2);
    LCD.drawString("Power: " + power, 0, 3);
    LCD.refresh();
    Thread.sleep(250);
}

Ved udførsel af programmet, bakkede robotten hele tiden, når den ikke målte andet end baggrundsstøj. Når vi snakkede højt 5cm foran mikrofonen kørte robotten frem (60-70 power) i kort tid og bakkede derefter hurtigt igen (80-90 power).


Vehicle 2a & 2b Assignment


In the two other vehicles use e.g. light sensors. Again make sure to define the mappings between sensor range and motor power. Try with both exibitory and inhibitory connections and describe the resulting behaviours.

Først tilsluttede vi en lys-sensor, for at finde et interval. For at finde den lavest mulige værdi holdt holdt vi en finger helt hen til sensoren, for at blokere så meget lys som muligt for den. For at finde den højest mulige værdi, lyste vi med en optisk mus ind i sensoren. Dette gav os et interval på 222-895.

To lyssensorer blev så påmonteret fronten af bilen med 10 cm mellemrum, således at begge pegede ligefrem.

Bilen blev kodet således, at hver motor får en power med en værdi på 50, hvortil der bliver lagt følgende udregning:
(Læsning - 222)/(895-222) * 50 + 50.

I model 2a blev power for venstre motor udregnet for læsningen på venstre sensor og tilsvarende for højre motor og højre sensor, mens det omvendte var tilfældet for model 2b.

Beskrivelse af bilernes opførsel med exibitory:
Disse forsøg blev foretaget i køkkennet i lego-lab, hvor vi med lukket dør og slukket lys, kunne undgå unødige lyskilder. Hefter blev der på midten af gulvet sat en lyskilde.

Bil 2a, der skulle kører væk fra lys, blev startet og sat til at køre frem mod en lyskilden. Fra start kørte bilen umiddelbart ligeud med meget lav hastighed, men efterhånden som den kom nærmere lyskilden, begyndte den at dreje til siden mens den generelle hastighed steg, hvorved den kørte forbi lyskilden.

Det så ud til, at lys-sensoren er meget "nærsynet", og den skulle inden for få centimeter af lyskilden, før der kommer nogle tydeligt observerbare udsving i power til motorerne.

Bil 2b, der skulle køre mod lys, blev fra start sat på en måden så den ved at køre direkte frem, ville køre lige forbi lyskilden. Her kunne vi igen se, at når den kom inden for få centimeter af lyskilden, begyndte den at styre hen mod denne. Dog med så relativt svagt udsving, at den stadig kørte forbi lyskilden.

Beskrivelse af bilerne opførsel med inhibitory:
Her var udregningen for power: 100 - (Læsning - 222)/(895-222) * 50.

Bil 2a og 2b, her kørte bilen med fuld hastighed så længe den ikke befandt sig i nærheden af lyskilden. Så snart den kom inden for kort afstand af denne begyndte den igen kraftigt at svinge væk fra/svinge ind mod lys-kilden.

Observationer på bilerne med inhibitory forbindelser, var betydeligt mere interessante, idet de ikke sneglede sig afsted, så længe der ikke var en lyskilde.

Kode:

public class LightCar2Inhib {
  //Vehicle 2b inhibitory
  public static void main(String [] args) throws Exception {
    //exit listener
    Button.ESCAPE.addButtonListener(new ButtonListener() {
    public void buttonPressed(Button b) { System.exit(0);}
    public voidbuttonReleased(Button b) { }
  });
  LightSensor l_sensor = newLightSensor(SensorPort.S1);
  LightSensor r_sensor = newLightSensor(SensorPort.S2);
  int first_reading = SensorPort.S1.readRawValue();
  //Max: 895
  //Min: 222
  while (true) {
    float crr_left = (float)SensorPort.S2.readRawValue();
    float crr_right = (float) SensorPort.S1.readRawValue();
    crr_left = 1023 - crr_left;
    crr_right = 1023 - crr_right;
    int powerleft = 100 - (int)((crr_left -222F)/(895-222) * 50);
    int powerright = 100 - (int) ((crr_right - 222F)/(895-222) * 50);
    MotorPort.A.controlMotor(powerleft,1);
    MotorPort.B.controlMotor(powerright,1);
    Thread.sleep(250);
  }
}


public class LightCarInhib {
  //Vehicle 2a inhibitory
  public static void main(String [] args) throws Exception {
    //exit listener
    Button.ESCAPE.addButtonListener(new ButtonListener() {
    public void buttonPressed(Button b) { System.exit(0);}
    public void buttonReleased(Button b) { }
  });
  LightSensor l_sensor = newLightSensor(SensorPort.S1);
  LightSensor r_sensor = newLightSensor(SensorPort.S2);
  int first_reading = SensorPort.S1.readRawValue();
  //Max: 895
  //Min: 222
  while (true) {
    float crr_left = (float)SensorPort.S2.readRawValue();
    float crr_right = (float) SensorPort.S1.readRawValue();
    crr_left = 1023 - crr_left;
    crr_right = 1023 - crr_right;
    int powerleft = 100 - (int)((crr_left -222F)/(895-222) * 50);
    int powerright = 100 - (int) ((crr_right - 222F)/(895-222) * 50);
    MotorPort.A.controlMotor(powerright,1);
    MotorPort.B.controlMotor(powerleft,1);
    Thread.sleep(250);
  }
}

public class LightSensorCar{
  //Vehicle 2a exibitory
  public static void main(String [] args) throws Exception {
    //exit listener
    Button.ESCAPE.addButtonListener(new ButtonListener() {
      public void buttonPressed(Button b) { System.exit(0);}
      public voidbuttonReleased(Button b) { }
    });
    LightSensor l_sensor = newLightSensor(SensorPort.S1);
    LightSensor r_sensor = newLightSensor(SensorPort.S2);
    int first_reading = SensorPort.S1.readRawValue();
    //Max: 895
    //Min: 222
    while (true) {
      float crr_left = (float)SensorPort.S2.readRawValue();
      float crr_right = (float) SensorPort.S1.readRawValue();
      crr_left = 1023 - crr_left;
      crr_right = 1023 - crr_right;
      int powerleft = (int) ((crr_left - 222F)/(895-222) * 50) + 50;
      int powerright = (int) ((crr_right - 222F)/(895-222) * 50) + 50;
      MotorPort.A.controlMotor(powerright,1);
      MotorPort.B.controlMotor(powerleft,1);
      Thread.sleep(250);
    }
}


public class LightSensorCar2 {
  //Vehicle 2b exibitory
  public static void main(String [] args) throws Exception {
    //exit listener
    Button.ESCAPE.addButtonListener(new ButtonListener() {
      public void buttonPressed(Button b) { System.exit(0);}
      public voidbuttonReleased(Button b) { }
    });
    LightSensor l_sensor = newLightSensor(SensorPort.S1);
    LightSensor r_sensor = newLightSensor(SensorPort.S2);
    int first_reading = SensorPort.S1.readRawValue();
    //Max: 895
    //Min: 222
    while (true) {
      float crr_left = (float)SensorPort.S2.readRawValue();
      float crr_right = (float) SensorPort.S1.readRawValue();
      crr_left = 1023 - crr_left;
      crr_right = 1023 - crr_right;
      int powerleft = (int) ((crr_left - 222F)/(895-222) * 50) + 50;
      int powerright = (int) ((crr_right - 222F)/(895-222) * 50) + 50;
      MotorPort.A.controlMotor(powerleft,1);
      MotorPort.B.controlMotor(powerright,1);
      Thread.sleep(250);
    }
}

Min Max Light Values
I opsamler nu de sidste N sensor målinger for at have en indikation af max og min værdierne i det miljø som robotten arbejder i.
Vi har en liste af størrelse N, som løbende bliver opdateret.
Koden er vist herunder:

public class LightCar2Inhib {
  // Vehicle 2b inhibitory
  static float maxvalue = 895;
  static int noReadings = 80;
  static float minvalue = 222;
  static int pointer = 0;
  static int[] readings = new int[noReadings];
  static int readingssize = 0;

  public static void updateMaxMin() {
    if (readingssize < 1) return;
    maxvalue = 0;
    minvalue = 2000;
    for(int i = 0; i< readingssize;i++){
      if (maxvalue < readings[i])
        maxvalue = readings[i];
      if (minvalue > readings[i])
        minvalue = readings[i];
    }
  }

  public static void putNewReading(int valueright, int valueleft) {
    int removedValue = readings[pointer % noReadings];
    readings[pointer % noReadings] = valueright;
    pointer++;
    int removedValue2 = readings[pointer % noReadings];
    readings[pointer % noReadings] = valueleft;
    pointer++;
    if (removedValue == maxvalue
     || removedValue == minvalue
     || removedValue2 == maxvalue
     || removedValue2 == minvalue) { updateMaxMin(); }
  }

  public static void main(String[] args) throws Exception {
    // exit listener
    Button.ESCAPE.addButtonListener(new ButtonListener() {
      public void buttonPressed(Button b) {
        System.exit(0);
      }
      public void buttonReleased(Button b) {}
    });
    LightSensor l_sensor = new LightSensor(SensorPort.S1);
    LightSensor r_sensor = new LightSensor(SensorPort.S2);
    int first_reading = SensorPort.S1.readRawValue();
    while (true) {
      float crr_left = (float) SensorPort.S2.readRawValue();
      float crr_right = (float) SensorPort.S1.readRawValue();
      crr_left = 1023 - crr_left;
      crr_right = 1023 - crr_right;
      putNewReading((int)crr_left, (int)crr_right);
      int powerleft = 100-(int)((crr_left – minvalue)/(maxvalue-minvalue)*50);
      int powerright = 100-(int)((crr_right-minvalue)/(maxvalue-minvalue)*50);
      MotorPort.A.controlMotor(powerleft, 1);
      MotorPort.B.controlMotor(powerright, 1);
      Thread.sleep(250);
     }     
}


Party Finder

Party Finder robotten er baseret på samme program som 2a og 2b robotterne.
Da max. og min. værdierne bliver målt ud fra kørsel af robotten er det
ikke væsentligt om det er en lyd sensor eller lys sensor som sidder på
robotten, så koden er den samme ud over vi initialisere SoundSensor-objekter i stedet for LightSensor.

Robotten havde svært ved at skelne lyden mellem de to sensorer, eller sagt på en anden måde de to lyd-sensorer opfangede samme lydstyrke på næsten alle tidspunkter. Det bevirkede, at den ikke drejede kraftig henimod/væk fra sit mål.

Ingen kommentarer:

Send en kommentar