| |
Java 6 - Eclipse 3.4
Download : JavaFish50.zip
Lösung für Java 6 - Eclipse 3.4 und den Robo TX Controller und
ftcomputing.roboTX.jar.
Klasse HanoiTower
import ftcomputing.roboTX.*;
public class HanoiTower {
HanoiRobot hr;
public static void main(String[] args) {
HanoiTower ht = new HanoiTower();
ht.action();
}
private void action() {
hr = new HanoiRobot();
System.out.println("HanoiTower wird gestartet");
hr.openController("COM4");
System.out.println("Fährt auf Grundstellung");
hr.grundstellung();
System.out.println("Bei der Arbeit");
hanoi(3, 2, 22, 38);
System.out.println("--- FINIS ---");
hr.closeController();
}
private void hanoi(int n, int pAnf, int pMit, int pEnd) {
if(n == 1) {
System.out.println("Scheibe " + n + " : von " + pAnf + " nach " + pEnd);
hr.ziehe(pAnf, pEnd);
}
else {
hanoi(n-1, pAnf, pEnd, pMit);
System.out.println("Scheibe " + n + " : von " + pAnf + " nach " + pEnd);
hr.ziehe(pAnf, pEnd);
hanoi(n-1, pMit, pAnf, pEnd);
}
}
Die Klasse HanoiTower umfaßt die Methode action() für die
"Rahmenhandlung und die Methode hanoi() für die Hanoi-Logik. Der Zugriff
auf den Hanoi-Robot erfolgt über die innere Klasse HanoiRobot, die hier auch
instanziert wird. static main() dient dem Start des Console-Programmes.
In Methode action() wird die Verbindung zum Robo TX Controller (openController,
USB über COM4) hergestellt und der Robot auf grundstellung() gefahren. Dann
folgt die - rekursive - Hanoi-Lösung und noch das closeController().
Zur Hanoi-Logik siehe das Scheibenschichten, hier nur der Vermerk der Robot
wird über die harmlose Methode ziehe() der Klasse HanoiRobot bewegt. Die
angegebenen Parameter beim Aufruf von hanoi(..) stehen für die Anzahl Scheiben
und die drei Scheiben-Positionen. Gezählt wird dabei ab Home in Impulsen.
Klasse HanoiRobot
Interne Klasse von HanoiTower, abgeleitet von FishFace.
private class HanoiRobot extends FishFaceTX {
private final int PowerFull = 512;
private final int PowerOff = 0;
private final Mot mSaule = Mot.M1;
private final Mot mArm = Mot.M2;
private final Unv iArmOben = Unv.I3;
private final Unv iArmUnten = Unv.I4;
private final Out mGreifer = Out.O5;
private int robPos;
public void grundstellung(){
setLamp(mGreifer, PowerOff);
armHeben();
robPos = 9999;
sauleNach(0);
}
public void ziehe(int von, int nach) {
sauleNach(von);
armSenken();
setLamp(mGreifer, PowerFull);
armHeben();
sauleNach(nach);
armSenken();
setLamp(mGreifer, PowerOff);
armHeben();
}
private void sauleNach(int zielPos){
if(robPos < zielPos) {
startRobMotor(mSaule, Dir.Right, PowerFull, zielPos-robPos);
robPos = zielPos + waitForMotor(mSaule);
}
else {
startRobMotor(mSaule, Dir.Left, PowerFull, robPos-zielPos);
robPos = zielPos - waitForMotor(mSaule);
}
}
private void armSenken() {
setMotor(mArm, Dir.Left);
waitForInput(iArmUnten, true);
setMotor(mArm, Dir.Off);
}
private void armHeben() {
setMotor(mArm, Dir.Right);
waitForInput(iArmOben, true);
setMotor(mArm, Dir.Off);
}}}
Zuerst symbolische Konstanten für die beteiligten Interface-Anschlüsse,
zusätzlich die Variable robPos mit der aktuellen Position der Robot-Säule.
Gezählt wird in Impulsen ab Home (Endtaster an I1).
Mit grundstellung() wird der Magnet abgeschaltet, der Arm angehoben und die
Säule auf Home gefahren. Mit robPos = 9999 wird sauleNach() eine -fiktive -
Position weit von Home vorgegaukelt.
ziehe(..) fährt den Robot von der aktuellen Position zur Hol-Position,
armSenken(), Scheibe packen, armHeben() ...
sauleNach() fährt eine Position ab Home an. Die Positionsangabe erfolgt in
Impulsen ab Home. Intern wird anhand der aktuellen Position die zu fahrende
Position bestimmt und angefahren setMotor(...) - waitForMotors(..).
Anschließend noch robPos auf den neuen Wert gesetzt. Dabei wird eine mögliche
Abweichung von der Vorgabe einbezogen.
Wenn man schon andere Programme gesehen hat, die FishFaceTX nutzen, ist
vielleicht ungewohnt, dass hier der Instanz-Bezeichner fehlt. Grund : Klasse hat
von FishFaceTX geerbt (extends) und behandelt dessen Methoden wie eigene.
Hier die Lösung für das Robo Interface
Stand : 21.04.2010
|