12  Tipps, Tricks und leJOS-Experiment

In diesem Kapitel werden Tipps und Tricks beschrieben, die den Programmierer in der Praxis mit leJOS und dem EV3 unterstützen. Neben praktischen Tastenkombinationen werden auch gängige Probleme bei der Verbindung des EV3 mit dem Computer behandelt.

12.1  Tipps und Tricks

12.1.1  Tastenkombinationen

Es kann aus verschiedenen Gründen vorkommen, dass ein laufendes Programm nicht beendet wird und der EV3 auf keine Benutzereingaben mehr reagiert. Oft handelt es sich dabei um einen einfachen Programmierfehler, wenn zum Beispiel die Abbruchbedingung einer Schleife nie erfüllt wird, oder der EV3 hat sich schlicht aufgehangen und reagiert nicht mehr. Die intuitive Lösung in einem solchen Fall wäre den Akku zu entfernen, wieder einzusetzen und damit den EV3 neu zu starten. Der EV3 ist aber meist in einen Roboter eingebaut, was das entfernen des Akkus schwierig machen kann. Ein kompletter Neustart des EV3 ist bei einem Programm, das auf Grund eines Programmierfehlers nicht beendet wird, aber auch gar nicht nötig.

12.1.2  Verbindung mit dem EV3

Beim Verbinden des Computers mit dem EV3 über USB, wie in Anhang A beschrieben, können Probleme auftreten. In seltenen Fällen kommt es vor, dass eine vorher problemlos funktionierende Verbindung plötzlich nicht mehr funktioniert. Bevor aufwändigere Maßnahmen ergriffen werden, ist es ratsam, zunächst das USB-Kabel aus- und wieder einzustecken sowie ggfs. den EV3 neu zu starten. Im Folgenden werden Maßnahmen beschrieben, die darüber hinaus die Verbindung mit dem EV3 verbessern können.

12.1.3  Compiler Compliance Level

In Versionen, älter als 0.9.0, benötigt leJOS das Compiler Compliance Level 1.7. In der Regel sollte diese Einstellung beim Anlegen eines leJOS-Projekts in Eclipse automatisch erfolgen. Das Compliance Level kann für ein Projekt durch Rechtsklick auf das Projekt und Auswählen von Properties im darauffolgenden Fenster unter »Java Compiler« verändert werden.

12.2  leJOS-Experiment

An dieser Stelle wird ein weiteres Beispiel für eine praktische Anwendung des LEGO EV3-Systems mit leJOS vorgestellt: der »Roberta-EV3CubeSolver«. Dabei handelt es sich um einen Roboter, der in der Lage ist sogenannte »Rubik’s Cubes« (auch »Zauberwürfel« genannt) zu lösen. Die Konstruktion ist in Abbildung 12.1 dargestellt1. Im Folgenden wird kurz auf den Aufbau und die Funktionsweise eingegangen.

pict
Die Bauanleitung und eine ausführliche Dokumentation können im Roberta-Portal unter www.roberta-home.de/javaband-ev3 heruntergeladen werden.

pict

Abbildung 12.1.: Der Roberta-EV3CubeSolver ohne Verkabelung und EV3-Brick

12.2.1  Roberta-EV3CubeSolver

Der »Roberta-EV3CubeSolver« kann komplett aus einem LEGO MINDSTORMS Education-Set aufgebaut werden und verwendet zum Lösen des Würfels die drei enthaltenen Motoren. Die beiden großen Servomotoren sind für die Bewegung des sogenannten »Tischs« (auf dem der Würfel ruht; siehe Abbildung 12.3) und der sogenannten »Gabel« (mit der die ihr zugewandten Seite des Würfels gedreht wird; siehe Abbildung 12.2) zuständig. Der Servomotor medium ist für die Bewegung der »Gabel« in Richtung Würfel und wieder zurück zuständig.

pict

Abbildung 12.2.: Gabel

pict

Abbildung 12.3.: Tisch

Darüber hinaus wird der Farbsensor verwendet um die Farben der verschiedenen Elemente des Würfels zu detektieren. Bevor der Lösungsalgorithmus angewendet werden kann muss der Würfel komplett »gescannt« werden. Aufgrund des Aufbaus ist dies aber immer nur für die Oberseite des Würfels möglich. Deswegen muss der Würfel dabei nach einem bestimmten Muster verdreht werden, sodass sich jedes Element einmal oben befunden hat.

pict

Abbildung 12.4.: Abgescannte Oberseite des Rubik’s Cube

Ist der Scanvorgang abgeschlossen befindet sich eine interne Repräsentation des gescannten physikalischen Würfels in Form eines mehrdimensionalen Arrays im Speicher des Cubesolvers. Mit Hilfe von zwei Indizes werden dabei die Farbwerte der einzelnen Elemente abgespeichert. Der erste Index beschreibt die Seite des Würfels, auf dem sich das Element befindet, der zweite ist für die Adressierung des Elements zuständig. Auf einer Seite werden dabei die Elemente von oben links im Uhrzeigersinn durchnummeriert. Das mittlere Element einer Seite ist fest und braucht nicht nummeriert werden. Eine mögliche Konfiguration des Arrays, als Matrix dargestellt, könnte wie folgt aussehen:

0 1 2 3 4 5 6 7
0
1
2
3
4
5

Tabelle 12.1.: Eine mögliche Konfiguration des Rubik’s Cube

Die Zeilen entsprechen dabei den Seiten und die Spalten dem jeweiligen Element. Mit diesem Abbild kann dann die Lösung berechnet werden, die zu guter letzt auf dem physikalischen Würfel ausgeführt wird. Dabei verwendet der Roboter einen Algorithmus nach Schichten, der so auch von einem Menschen angewendet werder könnte. Nach dem Beenden des Vorgangs befindet sich der Würfel gelöst im »Roberta-EV3CubeSolver« und kann zur erstaunten Betrachtung entnommen werden.

Exemplarisch ist in Programm(ausschnitt) 12.1 die main-Methode des »Roberta-EV3CubeSolver« zu sehen. Die Codekommentare zeigen die Aufteilung des Hauptprogramms in die Abschnitte »Scannen«, »Berechnung der Lösung« und »Ausführen der Lösung«.


Programm 12.1: main-Methode des Roberta-EV3CubeSolver
 
1    public static void main (String[] args) { 
2        int scanTime, searchTime, applyTime; 
3 
4        MotorController motors = new MotorController(); 
5        CubeScanner scanner = new CubeScanner(motors); 
6        RubiksCube cube = new RubiksCube(); 
7        CubeAlgorithm solver = new CubeAlgorithm(); 
8        Stopwatch timer = new Stopwatch(); 
9        motors.init(); 
10 
11        LCD.drawString("Start Scanning?",0,0); 
12        Button.ENTER.waitForPress(); 
13 
14        //Scanning starts here 
15        timer.reset(); 
16        scanner.scanCube(cube); 
17        while (cube.completeIntegrity() == false) { 
18            LCD.clear(); 
19            LCD.drawString("Scan Failure", 0, 0); 
20            LCD.drawString("Rescan?", 0, 1); 
21            Button.ENTER.waitForPress(); 
22            timer.reset(); 
23            motors.rotate(); 
24            cube.resetNull(); 
25            scanner.scanCube(cube); 
26        } 
27        scanTime = timer.elapsed(); 
28 
29        cube.printEV3(); 
30        LCD.drawString("Start Search?", 0, 7); 
31        Button.ENTER.waitForPress(); 
32 
33        //Calculation of solution starts here 
34        cube.setRecording(true); 
35        timer.reset(); 
36        solver.firstLevelEdges(cube); 
37        cube.shortenSolution(); 
38        solver.firstLevelCorners(cube); 
39        cube.shortenSolution(); 
40        solver.secondLevelEdges(cube); 
41        cube.shortenSolution(); 
42        solver.orientLLEdges(cube); 
43        cube.shortenSolution(); 
44        solver.permuteLLCorners(cube); 
45        cube.shortenSolution(); 
46        solver.orientLLCorners(cube); 
47        cube.shortenSolution(); 
48        solver.permuteLLedges(cube); 
49        cube.shortenSolution(); 
50        searchTime = timer.elapsed(); 
51 
52        LCD.clear(); 
53        LCD.drawString("Solution found", 0, 0); 
54        LCD.drawString(""+cube.solutionIndex, 0, 1); 
55        LCD.drawString("Apply?", 0, 2); 
56        Button.ENTER.waitForPress(); 
57 
58        //Solution is applied to cube here 
59        timer.reset(); 
60        motors.maneuver(cube.solution, cube.solutionIndex); 
61        applyTime = timer.elapsed(); 
62 
63        //Times are displayed 
64        LCD.clear(); 
65        LCD.drawString("Scan: "+ scanTime/1000.0F, 0, 0); 
66        LCD.drawString("Search: "+ searchTime/1000.0F, 0, 1); 
67        LCD.drawString("Apply: "+ applyTime/1000.0F, 0, 2); 
68 
69        Button.ENTER.waitForPress(); 
70    }

1 Sie beruht auf dem Modell eines NXT-Cubesolvers von »Copper Dragon«, welches unter www.youtube.com/watch?v=1ty5MxgaGak angesehen werden kann