Was machen wir mit den Farben?

Nachdem wir den Cube ohne Probleme kontrollieren können, muss der Roboter anfangen die Farben des Cubes zu scannen. Entweder fragen Sie sich gerade wie man denn die Farben in Java in einem Würfel abspeichert oder sie haben nie darüber nachgedacht und es ist Ihnen egal. Naja ich erkläre es Ihnen trotzdem.

Ein Rubics Cube besteht aus 6 Seiten mit je 9 Farben. Um immer den Überblick zu behalten  haben wir uns für folgende Speichermethode entschieden:

Wie sie sehen (oder vielleicht auch nicht), haben wir ein Würfelnetz gebaut was die Farben in einer Liste der Länge 54 speichert. Ich hab das zwar so schön als Bild visualisiert, aber was der Roboter sieht ist sowas ähnlich wie folgendes:

Jetzt ist die Frage nur wie wir dem Roboter die Farben übergeben.

Zum Glück haben wir einen Colorsensor bekommen, der Farben scannt und uns einen RGB-Wert zurück gibt (RGB steht für Rot-Grün-Blau). Um diesen zu kontrollieren habe ich folgende Methode geschrieben (nur ein Auszug aus einer viel komplizierteren Klasse):

float[] sample = new float[3];
sensor.getRGBMode().fetchSample(sample, 0);
c = new Color();
float r = sample[0] * 100;
float g = sample[1] * 100;
float b = sample[2] * 100;

Wie auch beim Drucksensor werden hier in sample die Werte rot, grün und blau gespeichert. Diese hab ich dann mit 100 multipliziert, einfach nur um schönere Zahlen zu kriegen.

Noch sind die Werte keine Farben, denn es sind nur drei Werte die uns nichts bringen. Um das zu ändern haben Andrey und ich eine Klasse programmiert, die aus reinen RGB-Werten eine Color zurück geben. Hier ein kleiner Auszug:

if (range(r, 17.4f) && range(g, 18.3f) && range(b, 37.8f)) {
c.setColor("GREEN");
}
if (range(r, 16.8f) && range(g, 12.8f) && range(b, 13.3f)) {
c.setColor("YELLOW");
}

Hier wird gefragt ob die RGB-Werte zwischen von uns festgelegten Werten liegen und wenn das der Fall ist wird den RGB-Werten eine Color zugewiesen. Was range(float, float) macht ist ganz einfach:

public boolean range(float zahl, float eins) {
if (zahl > (eins - 2f) && zahl < (eins + 2f)) {
return true;
} else {
return false;
}
}

Es wird geguckt ob die zahl 2 über oder drunter dem Wert von eins liegt. Wenn das der Fall ist, wird true ausgegeben (return true) und wenn nicht return false. (Das kennen Sie ja schon von dem Drucksensor ;)).

Wenn die range(float, float) jetzt zu allen drei RGB-Werten passt, dann wird den RGB-Werten eine color zugewiesen (c.setColor("YELLOW").

Aber was genau ist c.setColor("FARBE").
Um die Farben einfach zu managen habe ich eine weitere Klasse programmiert, die genau das für uns übernehmen soll:

public void setColor(String s) {
if (s.equalsIgnoreCase("weiss") || s.equalsIgnoreCase("weiß") || s.equalsIgnoreCase("white")) {
color = 0;
} else if (s.equalsIgnoreCase("yellow") || s.equalsIgnoreCase("gelb")) {
color = 5;
...
}
}

Wenn wir nun als s (String ist nur eine Zeichenkette) zum Beispiel YELLOW übergeben, wird geprüft ob das Wort, dass gleiche ist wie „yellow“ bzw. „gelb“. Dann wird color gleich 5 gesetzt. Für die Reihenfolge von den Farben in Ziffern haben wir uns für folgende entschieden:

WHITE = 0
ORANGE = 1
GREEN = 2
RED = 3
BLUE = 4
YELLOW = 5
UNDEFINED = 6

Zu dem Zeitpunkt hatte ich noch wenig Ahnung von Enums, was die Sache aber deutlich einfacher gemacht hätte (Für jeden den es interessiert: HIER klicken).

Jetzt hatten wir noch ein großes Problem zu lösen: Die Lichtwerte mit denen wir zutun haben (im Klassenraum, zuhause, usw.) haben wir immer wieder geändert (logisch es ist ja nicht immer gleich hell/dunkel), also was machen wir nun?
Ich, als schlauer Fuchs, dachte mir man könnte ab dem Anfang jedes Lösens eine Taste bestätigen, die dann die RGB-Werte jeder Farbe speichert und später mit der gescannten Farbe vergleicht.
Folgende Methode hat mir das ermöglicht:

public void scanColor() {
if (color < 6) {
float[] sample = new float[3];
sensor.getRGBMode().fetchSample(sample, 0);
float r = sample[0] * 100;
float g = sample[1] * 100;
float b = sample[2] * 100;
LCD.drawString("INSERT: " + Color.getName(color), 1, 6);
if (Button.ENTER.isDown()) {
cV[0 + color * 3] = r;
cV[1 + color * 3] = g;
cV[2 + color * 3] = b;
color++;
Delay.msDelay(2000);
}
}
LCD.clear();
}

Im Endeffekt, werden die Werte der sechs Farben in einer Liste (cV) gespeichert und später durch die oben genannten Werte (17.4, 18.3, usw.) ersetzt. Dies ermöglicht es noch genauer zu sein.