tirsdag den 11. januar 2011

NXT Programming, lesson 18

Dato: 10-1-2011
Varighed: 6 timer
Deltagere: JC, Allan



Formål:


Arbejde videre med ColorNavigator, hente den nye bane og lime den på pladen, og lave en adfærd, der kan se at den er i målzonen og kan aflevere brikken i den korrekte zone.




Plan:


-Kode videre på ColorNavigator.
-Lave en nye adfærd der hedder Finishline.
-Hente den nye bane og lime den på pladen.
-Lave kalibreringsmetoder, der kan bruges til at kalibrere forskellen mellem de to sensore og værdierne for de to farver.


ColorNavigator:


Den nye kode til ColorNavigator:



package BrickSorter;


import Robot.CameraSensor;
import Robot.LightSensorNavigator;
import Robot.Movement;
import lejos.nxt.LCD;
import lejos.nxt.Sound;
import lejos.robotics.subsumption.Behavior;


public class ColorNavigator implements Behavior{


private LightSensorNavigator lsn;
private boolean _suppressed = false;
private int actionTime = 20;
private int diffLevel = 6;
private CameraSensor cs;
private int reverseTime = 3000;
private int reverseSpeed = 30;
private int anglingTime = 1000;



public ColorNavigator(LightSensorNavigator lsn, CameraSensor cs) {
this.lsn = lsn;
this.cs = cs;
}


@Override
public void action() {
//Is the color red or green
Movement.stop();
int rightValue = lsn.getRight();
int leftValue = lsn.getLeft();
int rightColor = lsn.getRightColor();
int leftColor = lsn.getLeftColor();
if(rightColor == 1 || leftColor == 1){
Sound.beep();
}
if(rightColor == 2 || leftColor == 2){
Sound.twoBeeps();
}
LCD.drawString("Colors: " + leftColor + rightColor, 0, 6);

if(leftColor == 2){
if(cs.getBrickColor() != 2){
reverse(-15, 0);
return;
}
if(rightColor == 1){
if(cs.getBrickColor() == 2){
reverse(0, -15);
return;
}
if(cs.getBrickColor() == 1){
reverse(-15, 0);
return;
}
}
else {
while(rightColor != leftColor){
Movement.drive(1, 10);
Sound.pause(actionTime);
rightColor = lsn.getRightColor();
}
}

} else if(leftColor == 1){
if(cs.getBrickColor() != 1){
reverse(-15,0);
return;
}
while(rightColor != leftColor){
Movement.drive(1, 10);
Sound.pause(actionTime);
rightColor = lsn.getRightColor();
}
} else if(rightColor == 2){
if(cs.getBrickColor() != 2){
reverse(-15,0);
return;
}
while(rightColor != leftColor){
Movement.drive(10, 1);
Sound.pause(actionTime);
leftColor = lsn.getLeftColor();
}
} else if(rightColor == 1){
if(cs.getBrickColor() != 1){
reverse(0,-15);
return;
}
while(rightColor != leftColor){
Movement.drive(10, 1);
Sound.pause(actionTime);
leftColor = lsn.getLeftColor();
}
}
}

private void reverse(int left, int right){
Movement.drive(left, right);
Sound.pause(anglingTime);
Movement.drive(-reverseSpeed, -reverseSpeed);
Sound.pause(reverseTime);
lsn.resetBuffer();
}


@Override
public void suppress() {
_suppressed = true;// standard practice for suppress methods
}


@Override
public boolean takeControl() {
int rightDiff = lsn.getRightDiff();
int leftDiff = lsn.getLeftDiff();

return rightDiff > diffLevel || leftDiff > diffLevel;
}
}

Vi har lavet store ændringer i ColorNavigator, da den gamle udgave ikke tog højde for farven af brikken. 

I takeControl() er ændret til at bruge en metode i LightSensorNavigator, der hedder getRightDiff() og getLeftDiff(). Disse metoder kigger på cachen der er knyttet til hver af sensorene og finder differencen mellem den højeste og den laveste værdi. På denne måde kan den se om den er flyttet fra sort til rød eller grøn. Hvis dette er tilfældet skal den udføre action().

action() tager nu højde for hvilken farve sensorene har set og dette gøres via getRightColor() eller getLeftColor(). Denne metode kigger efter den højeste værdi i cachen og prøver at tolke dette som en farve. Ud fra hvilken farve de to sensorer ser, foretager robotten en manøvre. Enten drejer den lidt mod højre og bakker, eller lidt mod venstre og bakker, alt efter om den er ved rød og vil til grøn eller er ved grøn og vil til rød. Hvis den er ve den korrekte farve, så holder den stille med den side hvor sensoren har den korrekte farve og kører langsomt frem med den anden side, indtil den ser samme farve. Så skulle robotten gerne være rettet op i forhold til stregerne og være klar til at bruge GreyNavigator til at køre fremad på den røde stribe. En ting der mangler er at den skal kunne rette op på overgangen fra rød til sort.

Finishline:

Koden til Finishline:

package BrickSorter;

import Robot.CameraSensor;
import Robot.Claw;
import Robot.LightSensorNavigator;
import Robot.Movement;
import lejos.nxt.Sound;
import lejos.robotics.subsumption.Behavior;

public class Finishline implements Behavior{
private LightSensorNavigator lsn;
private boolean _suppressed = false;
private CameraSensor cs;
public Finishline(LightSensorNavigator lsn, CameraSensor cs){
this.lsn = lsn;
this.cs = cs;
}

@Override
public void action() {
Claw.open();
Movement.stop();
Sound.systemSound(true, 3);
System.exit(0);
}

@Override
public void suppress() {
_suppressed = true;// standard practice for suppress methods
}

@Override
public boolean takeControl() {
if(lsn.getRedColorCounter() > 30 && cs.getBrickColor() == 1) return true;
if(lsn.getGreenColorCounter() > 30 && cs.getBrickColor() == 2) return true;
return false;
}
}

takeControl() tjekker variablen redColorCounter eller greenColorCounter, som er to integers der tælles op hver gang begge sensore ser grøn eller rød samtidig. Hvis de ser noget forskelligt f.eks. ser sort eller ser rød, nulstilles greenColorCounter og omvendt. Dette sikrer os at robotten er i selve målzonen.

action() er ikke færdig, men den slipper brikken og spiller en lille lyd. Her skal vi har indsat kode der får robtten til at køre tilbage på selve banen igen.


Banen:

Huset kunne ikke levere udprintet i dag og det må vente til i morgen. Dette presser os lidt tidsmæssigt, men vi må se om vi kan arbejde videre på andre dele af projektet, indtil vi har banen i vore hænder. 

Kalibrering:

Før hvert forsøg kalibrer vi forskellen mellem de to lyssensorer, da vi tidligere er kommet frem til at de ikke giver den samme værdi, på det samme underlag. Forskellen ligger et sted mellem 4 og 6 når man bruger de normaliseret værdier fra sensorene. Denne forskel kan afhænge både af batteriets spænding  og af lyset omkring dem [Dean4].

Vi lavede en metode der læste på begge lyssensore mens robotten bevægede sig fremad.


private void calibrate() {
for(int i = 0; i < 10; i++){
Movement.drive(30, 30);
lsn.getLeft();
lsn.getRight();
Sound.pause(40);
}
Movement.stop();
int diff = lsn.getRightAverage() - lsn.getLeftAverage();
lsn.setDiff(diff);
LCD.drawString("Diff: " + diff, 0, 3);
}

Metoden sætter robotten i gang med at køre frem ad mens den læser ti gange på hver sensor. Derefter stopper robotten og vi henter gennemsnittet af de to sensorers målinger og finder differencen. Denne difference bliver sat ind i vores LightSensorNavigator-klasse, og den bliver lagt til den højres output.

Den anden kalibrering var at måle værdien for grøn og rød. Igen kan batteriet og lyset have en påvirkning, så dette skal også gøres før hvert forsøg.


private void calibrateRedGreen() {
int red = lsn.getRight();
int green = lsn.getLeft();
lsn.setRed(red);
lsn.setGreen(green);
lsn.createColorThredsholds();
LCD.drawString("Red: " + red, 0, 4);
LCD.drawString("Green: " + green, 0, 5);
}

Vi læser den højre til at være rød og den venstre til at være grøn. Dette gøres let på banen, nede ved vores målzoner. Da denne kalibrering sker efter den første kalibrering, er der allerede taget højde for at de to lyssensore ikke giver den samme værdi ved samme underlag.


Adfærdshierarki:




FinishLine har placeret sig imellem DetectWall og ColorNavigator.


Resultat:


Vi har nu fire adfærdsmønstre, der skal finpudses på den nye bane, men vi vil ikke kode mere på dem, da forholdene ændrer sig med den nye bane og ændring kan både gøre det bedre og værre.

Ingen kommentarer:

Send en kommentar