Hallo,
ich habe jetzt leJOS halbwegs am Laufen, hapern tut es ganz stark mit dem Verständnis von OOP und Java.
Wer hat Lust und Kenntnisse, mir auf die Sprünge zu helfen?
Problemstellung:
Ein Motor und sein Sensor bilden eine "Unit", die ich steuern möchte.
Im "Hauptprogramm" wird alles definiert, danach möchte ich mit der Methode "speed" die Geschwindigkeit steuern.
d.h. das Objekt "Unit1" der Klasse "UNIT_CS" soll dauerhaft existieren und mit dem Motor und einem Sensor fest verknüpft sein
Hauptprogramm:
---------------------
EV3LargeRegulatedMotor m11 = new EV3LargeRegulatedMotor(MotorPort.A);
EV3TouchSensor s11 = new EV3TouchSensor(SensorPort.S1);
Unit_CS Unit1= new Unit_CS(m11,s11);
Unit1.speed(100);
Unit1.speed(200);
Unit1.speed(0);
Unit_CS:
----------------------
** HIER FEHLT IRGENDWAS ENTSCHEIDENDES ....... mit den
** Parametern (RegulatedMotor m,SensorModes s)
** sodass "speed" auf m zugreifen kann ......
public void speed(int v) {
m.forward();
m.setSpeed(v);
}
Wer kann helfen?
Grüße
Werner
Lok24 hat geschrieben:
Hallo Daniel,
recht vielen Dank für die schnelle Hilfe.
daniel.vergien hat geschrieben:
Lok24 hat geschrieben:
Hallo,
es wird besser, aber noch nicht gut
Eine Unit besteht im Modell immer aus einem konkreten Motor und einem konkreten Sensor.
Deswegen werden die in einem Array "Unit[]" definiert.
(Man könnte die Objekte auch im Konstruktor von Unit erzeugen, dann müsste man aber Art und Port als string übergeben, also quasi
U[4] = new Unit("L", "A"). Vertagt auf später.
In der Klasse "Unit" werden jedoch die 'Parents' (RegulatedMotor, SensorModes ) genutzt.
Ist das noch halbwegs sauber programmiert, oder geht das nur zufällig?
Die Methode "move" bekommt die Geschwindigkeit übergeben, der Motor dreht, bis der Sensor auslöst.
Überraschenderweise: das geht auch
Jetzt sollen die aber gleichzeitig laufen!
Also geändert in
"public Unit(RegulatedMotor m, SensorModes s ) extends thread"
Erfolg: kein Fehler, aber da läuft auch nix parallel.
Ich vermute die Idee mit den while-Schleifen ist da kontraproduktiv...
Wie macht man sowas "richtig"?
Grüße
Werner
--------------------------------------
public static void main(String[] args)
Unit[] U = new Unit[2];
EV3LargeRegulatedMotor m11 = new EV3
LargeRegulatedMotor(MotorPort.A);
EV3ColorSensor s12 = new EV3ColorSensor(SensorPort.S2);
U[1]= new Unit(m11,s12);
EV3MediumRegulatedMotor m12 = new EV3
MediumRegulatedMotor(MotorPort.B);
EV3TouchSensor s11 = new EV3TouchSensor(SensorPort.S1);
U[2]= new Unit(m12,s11);
U[2].move(100);
U[2].stop();
U[1].move(700);
U[1].stop();
---------------------------------------
public class Unit {
private RegulatedMotor m;
private SensorModes s;
private float[] sample;
public Unit(RegulatedMotor m, SensorModes s ) {
this.m = m;
this.s = s;
}
public void move(int v) {
if (s.getClass().getName().indexOf("Color") > 0){
SampleProvider sp = s.getMode("ColorID");
sample = new float[sp.sampleSize()];
}
if (s.getClass().getName().indexOf( "Touch") > 0){
SampleProvider sp = s.getMode("Touch");
sample = new float[sp.sampleSize()];
}
m.backward();
m.setSpeed(v);
while (true) {
s.fetchSample(sample, 0);
System.out.println(sample[0]);
Delay.msDelay(100);
if (sample[0] == 3) break;
if (sample[0] == 1) break;
}
//m.setSpeed(0);
//m.waitComplete();
//Sound.beep();
//Delay.msDelay(1000);
}
public void stop() {
m.stop();
m.flt();
}
}
Hallo Werner,
einen Thread started man in Java gewöhnlich über zwei verschiedene Wege:
1. Mit Runable
Du lässt deine Klasse das Interface "Runable" implementieren, also "public Unit(RegulatedMotor m, SensorModes s ) implements Runable"
Der Code der im Thread laufen soll kommt dann in die Methode "public void run()". Gestartet wird das ganze dann mit "Thread t = new Thread(new Unit(...)); t.start;
2. Direkt mit Thread
"public Unit(RegulatedMotor m, SensorModes s ) extends Thread" (mit großem T). Der Code der laufen soll kommt auch in "pulbic void run()". Gestarted wirt das dann mit "Unit u = new Unit(...); u.start;".
Der erste Weg hat den Vorteil, das eine Klasse mehrere Interfaces implantieren kann, aber nur von einer Klasse erben kann. Wenn deine Klassenhierachie etwas komplexer wird ist das oft ein entscheidender Vorteil.
Bis denn
Daniel
Lok24
20.12.2016, 10:13
Als Antwort auf den Beitrag von daniel.vergien
Editiert von
Lok24
20.12.2016, 10:23
Hallo Daniel,
daniel.vergien hat geschrieben:
Lok24 hat geschrieben:
Halo Daniel,
daniel.vergien hat geschrieben:
Hallo Werner,
funktioniert es den jetzt?
Sonst hab ich noch ein Paar Anmerkungen zu deinem Code:
* String Vergleiche mit "==" sind gefährlich. Es ist nicht garantiert das zwei String Objekte mit gleichen Inhalt das gleiche Objekt sind. Besser: status.equals("ON"
* Einrückung: da Du scheinbar eclipse nutzt: Strg+Shift+F oder in den "Preferences" nach "Save Actions" suchen und es dort gleich einstellen.
* Methoden, und Variablen fangen min einem kleinen Buchstaben an (EndThread() -> endThread()) und "CamleCase" ist die Konvention (getstatus() -> getStatus())
* Jeden if/else/for Block Klammern, das hilft gegen fehler, wenn man dann doch mal ein zweites Statement hinzufügt
Die letzten drei Punkte haben natürlich keinen Einfluss auf das Programm, aber da man Quellcode öfters liest als schreibt, ist es hilfreich sich an diese Konventionen zu halten. Der erste Punkt kann schwer zu findende Fehler produzieren.
Wenn Du es mit der Code-Qualität noch weiter treiben möchtest:
* enum type Direction mit LEFT und RIGHT definierten, sowie für Status mit ON, OFF. Das garantiert das man nicht aus versehen status = "LEFT" schreibt.
Lok24 hat geschrieben:
Hallo Daniel,
daniel.vergien hat geschrieben:
Lok24 hat geschrieben:
Hallo Daniel,
so, es geht weiter, ich packe jetzt das Thread-Erzeugen und die Sensoren-Prüfung in den Konstruktor von UNIT, das wird ja noch schöner.
Ich habe mich jetzt für KONSTANTEN entschieden, das schreibt und liest sich gut.
public static final String LEFT = "LEFT";
public static final String RIGHT = "RIGHT";
public static final String ON = "ON";
public static final String OFF = "OFF";
U[1].moveUnit(0, 300, LEFT);
U[2].moveUnit(5, 600, RIGHT);
while (U[1].getStatus() == OFF | U[2].getStatus() == OFF) {
}
Konkret baue ich nichts, sondern experimentiere ein wenig für ein konkretes Projekt, das aber ähnliche Aufgaben hat wie viele andere:
Ein Objekt soll bewegt werden, (ein) Sensor(en) soll(en) prüfen wo es ist, und das für mehrere Objekte parallel.
Das sind klassische Roboteranforderungen, die man immer wieder brauchen kann.
Und in labVIEW ist das Wiederzusammenführen von Threads nicht eben trivial, mehrdimensionale Arrays gibt es nicht.
Und auch die Parametrisierung ist nicht übersichtlich, hier mal das Setzen der Parameter und Arrays für meine 12V-Anlage.