PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ASURO mit Java steuern



robo.fr
23.02.2008, 06:49
Hallo Alle,

den ASURO will ich mit einem kleine Java-Programm steuern. Um über die Schnittstelle Daten zu übertragen, werde ich RXTX einsetzen.
Hat schon mal jemand versucht, ein Java-Programm zu schreiben?

Gruß,
robo

Nachtrag:
hier ein Bild vom Zwischenstand

http://www.roboterclub-freiburg.de/asuro/software/java_asuro_control/asuro_control.jpg

damaltor
23.02.2008, 13:43
es gib eine eigene virtual machine die auf dem atmega8 läuft. damit könntest du auch java programme auf dem asuro laufen lassen.

meintest du das?

robo.fr
23.02.2008, 14:57
Nein, auf dem Atmega8 soll ein C-Programm laufen. Das Steuerprogramm auf dem PC mit Java.

rossir
23.02.2008, 21:06
Ich mache das mit JAVA!
Ungefähr so:


import javax.comm.*;
...

serialPort=open("COM1");
serialPort.setSerialPortParams(2400, SerialPort.DATABITS_8,SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
outputStream = serialPort.getOutputStream();

...
outputStream.write(char);
...

mit


SerialPort open(String name) throws PortInUseException {
CommPortIdentifier portId;

Enumeration portList;

portList = CommPortIdentifier.getPortIdentifiers();

while (portList.hasMoreElements()) {
portId = (CommPortIdentifier) portList.nextElement();
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
if (portId.getName().equals(name)) {
return (SerialPort) portId.open(name, 2000);
}
}
}
return null;
}



Tut's

robo.fr
24.02.2008, 05:58
Hallo rosir,

Zugegebenermaßen habe ich erst vor 4 Tagen angefangen, mich mit Java zu beschäftigen. Die Grundlegende Kommunikation habe ich aber vor kurzem schon hingekriegt.


import javax.comm.*;

Wenn ich beim Durchstöbern des Internet nichts übersehen habe, unterstützen die Orginal comm Klassen von Sun Windows nicht.
Unter Window muss man RXTX verwenden und dann sieht das ganze so aus


import gnu.io.*;

Was ich mich Frage: Wenn man jemandem ein Java-Programm geben möchte, wie ist das mit der Installation?
Für die Kommunikation wird die JRE und RXTX gebraucht. Gibt es Installer, die alle Datein auf einem Computer an die richtigen Stellen schieben? Kann man ein Java-Programm über eine Verknüpfung auf dem Desktop starten?

Gruß,
robo

rossir
24.02.2008, 22:48
Also, wenn ich mich richtig erinnere und man JAVA von den SUN Seiten installiert funktioniert doch alles automatisch?! Selbst JAR Dateien werden mit javaw.exe verbunden. D.h. ein Doppelklick auf eine JAR Datei startet dann das darin enthaltene JAVA Programm.

Ok, bei RXTX wird man wohl die entsprechenden Libraries (jars) händig ins richtige Verzeichnis kopieren müssen (mit RXTX habe ich aber keine Erfahrung).

Oder, habe ich Deine Frage nicht richtig verstanden?

robo.fr
25.02.2008, 07:44
Hallo rosir,


Also, wenn ich mich richtig erinnere und man JAVA von den SUN Seiten installiert funktioniert doch alles automatisch?! Selbst JAR Dateien werden mit javaw.exe verbunden. D.h. ein Doppelklick auf eine JAR Datei startet dann das darin enthaltene JAVA Programm.

Leier weis ich das nicht. Ich hatte mir Java als großes Zip-File heruntergeladen und dann das Java-Verzeichnis 'händisch' angelegt. Dadurch sind die *.jar- Files leider nicht mit Java verbunden.
( BTW: wie macht man das eigentlich nachträglich? )


Ok, bei RXTX wird man wohl die entsprechenden Libraries (jars) händig ins richtige Verzeichnis kopieren müssen
Ja, das befürchte ich auch. Könnte es sein, dass es einfache, selbst zu konfigurierende Installer gibt?


(mit RXTX habe ich aber keine Erfahrung).

Geht es auch anders mit Windows? Ich dachte die Sun-Comm-Lib funktioniert nur mit Linus und Mac ( laut Internet ).

Gruß,
robo

Kommunikationsprogramm auf ASURO-Seite

Hier habe ich ein sehr einfaches Kommunikationsprogramm in C für die ASURO Seite geschrieben. Es versteht im Moment nur zwei Kommandos:

't' für Test
'l' um den linken Liniensesnor abzufragen

man kann aber sehr einfach weitere Kommandos an das Programm hinzufügen. Für das Programm wird die Asuro LibV261 von http://sourceforge.net/projects/asuro/ benötigt


#include "asuro.h"
/************************************************** *************************
*
* AsuroEasyCom
*
* Programm zur einfachen Kommunikation des PC mit dem ASURO
* über die Infrarot Schnittstelle
*
*
* Kommandos:
*
* t: Testkommando, Asuro sendet xASUROy zurück
* l: Abfrage des linken Liniensensors
*
************************************************** *************************
*/

// Status LED Farbe wechseln
void toggle_led()
{
static uint8_t k=0;

if(k)StatusLED(GREEN);
else StatusLED(YELLOW);
k=~k;
}
// Ein Zeichen von IR empfangen
uint8_t receive()
{
/* Warten auf ein Zeichen von der seriellen Schnittstelle */
UCSRB = 0x10; // enable receiver
while(!(UCSRA & 0x80)); // wait for received byte
toggle_led();
return UDR;
}
// Text senden
void SerPrint(unsigned char *data)
{
SerWrite(data,strlen(data));
}

int main(void)
{
uint8_t command;
int linie[2];

Init();
SerPrint("\n\r-- ASURO Ready --\n\r");
StatusLED(GREEN);

while(1)
{
/* Warten auf ein Kommando der seriellen Schnittstelle */
command = receive();

switch(command)
{

// Testcommando
case 't':
{
SerPrint("xASUROy");
}
break;

// Liniensensor links abfragen
case 'l':
{
LineData(linie);
SerPrint("x");
PrintInt(linie[0]);
SerPrint("y");
}
break;

// nicht erkannte Kommandos
default:
{
StatusLED(RED);
SerPrint("E"); /* Falls kein bekanntes Kommando, 'E' für Error senden */
}break;
}
}
return 0;
}
/************************************************** *************************
*
* (c) 2008 robo.fr (Nickname) , christoph(at)roboterclub-freiburg.de
*
************************************************** *************************
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation version 2 of the License, *
* If you extend the program please maintain the list of authors. *
* ( if there is no real name, the nick name has to be mentioned )
* If you want to use this software for commercial purposes and you *
* don't want to make it open source, please contact the authors for *
* licensing. *
************************************************** *************************/

m.a.r.v.i.n
25.02.2008, 10:34
Hallo robo,


Geht es auch anders mit Windows? Ich dachte die Sun-Comm-Lib funktioniert nur mit Linus und Mac ( laut Internet ).


So ist es. Beim c't-Bot (http://www.ct-bot.de) wurde deshalb auch die RXTX Lib verwendet. Zur Installation unter Windows wird lediglich die Datei
rxtxSerial.dll benötigt, die in das Verzeichnis JAVA_HOME\jre\bin kopiert werden muß.
Mit einen Installprogramm wie z.B. NSIS (http://sourceforge.net/projects/nsis/) eigentlich kein Problem.

robo.fr
25.02.2008, 18:23
Hallo m.a.r.v.i.n,

vielen Dank für die Auskunft, ich hätte nicht gedacht, dass es so einfach ist. Bei RXTX ist ja noch die Datei rxtxParallel.dll dabei, die man angeblich auch noch mitkopieren soll.

Gruß,
robo

Mittlerweile habe ich es schon geschafft, mein erstes Java-Programm zu schreiben, welches testen kann, ob der ASURO da ist. Es kann auch die Werte des Linken Liniensensors auslesen.

Hier also meine erste Java-Klasse ( bin ja Java-Anfänger )


/**
* Java Testprogramm zur Kommunikation mit dem ASURO Roboter
*
* Programm zur einfachen Kommunikation des PC mit dem ASURO
* über die Infrarot Schnittstelle
*
* Kommandos:
*
* t: Testkommando, Asuro sendet xASUROy zurück
* l: Abfrage des linken Liniensensors, Asuro sendet xZAHLy zurück
*
*
* @author robo.fr ( Nickname ) christoph(at)roboterclub-freiburg.de
*
* Feb.2008
*
*/
public class Test
{
private static boolean debug = true;

// Nachbau von Msleep aus der AsuroLibV261 für Java
// ( leider müssen Methoden in Java klein geschrieben werden )
public static void msleep(int millisekunden)
{
long stop,current;

java.util.Date zeit=new java.util.Date();
stop=zeit.getTime()+millisekunden;

current=0;
while(current<stop)
{
java.util.Date zeit2=new java.util.Date();
current=zeit2.getTime();
}
}

// sende das Testzeichen 't' zum ASURO und warte auf die
// korrekte Antwort: "xASUROy"
// falls der ASURO richtig antwortet, return true
public static boolean testCommand(Rs232 port)
{
port.read(); // Empfangsbuffer leermachen durch lesen
port.write((byte)'t'); // Testkommando senden
msleep(200);
String text=port.read();
if(debug) System.out.println(text);
if(text.contains("x") && text.contains("y"))
{
//if((text.indexOf("ASURO")-text.indexOf('x'))==1)
if(text.indexOf("xASUROy")!=-1)
{
if(debug) System.out.println("Test OK");
return true; // Test OK, der ASURO antwortet korrekt
}
}

if(debug) System.out.println("No ASURO");
return false;
}
// Wert des linken Liniensensors lesen
public static double read_line_left(Rs232 port)
{
port.read(); // Empfangsbuffer leermachen durch lesen
port.write((byte)'l'); // Liniensensor Lesekommando
msleep(500);
String text=port.read();
if(debug) System.out.println(text);
double x;
if(text.contains("x") && text.contains("y"))
{
String s=text.substring(text.indexOf("x")+1,text.indexOf("y"));

x=Double.parseDouble(s);

if(debug) System.out.println(x);
return x; // Test OK, der ASURO antwortet korrekt
}

if(debug) System.out.println("No Number");
x=Double.NaN; // return Not a Number
return x;
}

public static void main(String[] args)
{
int n;

Rs232 port1=new Rs232();
port1.ports_available();
port1.open("COM10") ;
port1.write("test");

testCommand(port1);
testCommand(port1);

for(n=0;n<50;n++)
{
read_line_left(port1);
}

port1.close() ;
System.out.println("beendet");

}
}
/************************************************** *************************
*
* (c) 2008 robo.fr (Nickname) , christoph(at)roboterclub-freiburg.de
*
************************************************** *************************
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation version 2 of the License, *
* If you extend the program please maintain the list of authors. *
* ( if there is no real name, the nick name has to be mentioned )
* If you want to use this software for commercial purposes and you *
* don't want to make it open source, please contact the authors for *
* licensing. *
************************************************** *************************/

Zur Entwicklung verwende ich Eclipse. Da gibt es ein Fenster, das heist Javadoc. Kann man damit automatisch eine Dokumentation erstellen? Wie muss ein einfacher Syntax aussehen?

Hier das ganze Projekt als Zip-File, falls es jemand ausprobieren will.
An die Java-Profis: Was könnte ich den alles besser machen?

trapperjohn
25.02.2008, 19:44
Allgemein solltest du dir die Objektorientierung mal etwas näher anschauen -- einfach alle Methoden static zu machen entspricht eigentlich nicht dem Gedanken der objektorientierten Programmierung ;-)

Als einfaches Beispiel könnte deine Klasse für die ASURO-Kommunikation folgendes Schema haben:




public class ASURO {

private Rs232 thePort = null;


public boolean testCommand() {
//...
}

//.... Hier alle möglichen Methoden zur
// Kommunikation mit dem ASURO

public ASURO(Rs232 port) {
thePort = port;
}
public ~ASURO() {}

public static void main() {
s232 port1=new Rs232();
port1.ports_available();
port1.open("COM10")
ASURO myAsuro = new ASURO(port1);
myAsuro.testCommand();
//usw.
}


}


JavaDoc kann aus den Quellcodekommentaren eine Dokumentation erstellen, bspw. in HTML (siehe SUNs Java API Dokumentation, die ist so erstellt). Damit Javadoc weiß, was/wie/wo dokumentiert wird, muss man sich bei der Erstellung der Kommentare an ein paar Konventionen halten.

Siehe bspw. hier:
http://www.tobias-seckinger.de/java/javadoc-einf-hrung.html

Eine gute Alternative zu Javadoc, die auch mit C++ usw. umgehen kann, ist Doxygen (+doxywizard):
http://www.stack.nl/~dimitri/doxygen/

robo.fr
26.02.2008, 08:05
Allgemein solltest du dir die Objektorientierung mal etwas näher anschauen -- einfach alle Methoden static zu machen entspricht eigentlich nicht dem Gedanken der objektorientierten Programmierung

Jaja, ich weis schon: mit langer Erfahrung in der nicht-objektorientierten Programmierung hat man etwas Probleme mit der Denkweise.

Aber um es zu lernen habe ich jetzt eine Zwischenklasse "AsuroKommandos" eingeführt. Damit wird das Main Programm ziemlich gut lesbar:

int n;

AsuroKommandos asuro=new AsuroKommandos();

asuro.schnittstelleOeffnen("COM10");

for(n=0;n<10;n++) asuro.verbindungOk() ; // Prüfen und zeigen, ob Verbindung
for(n=0;n<10;n++) asuro.liniensensorLinks(); // Liniensensor anzeigen

asuro.schnittstelleSchliessen();

Allerdings: Ich frage mich, warum ich überhaupt die AsuroKommandos als Objekt benötige. Die Kommanos gibt es ja nur einmal. Ich könnte 100 AsuroKommandos-Objekte erzeugen, aber ich kann nur eines gebrauchen.

Hier die zugehörige AsuroKommandos Klasse:


/**
* Kommandos zur Kommunikation mit einem ASURO
*
* Programm zur einfachen Kommunikation des PC mit dem ASURO
* über die Infrarot Schnittstelle
*
* Kommandos:
*
* t: Testkommando, Asuro sendet xASUROy zurück
* l: Abfrage des linken Liniensensors, Asuro sendet xZAHLy zurück
*
*
* @author robo.fr ( Nickname ) christoph(at)roboterclub-freiburg.de
*
* Feb.2008
*
*/

public class AsuroKommandos
{
private static boolean debug = true;
private Rs232 irSchnittstelle=new Rs232();

public void AsuroKommandos()
{
irSchnittstelle.ports_available();
}
public void schnittstelleOeffnen(String port)
{
irSchnittstelle.open(port) ;
}
public void schnittstelleSchliessen()
{
irSchnittstelle.close() ;
if(debug) System.out.println("beendet");
}
// Nachbau von Msleep aus der AsuroLibV261 für Java
// ( leider müssen Methoden in Java klein geschrieben werden )
public void msleep(int millisekunden)
{
long stop,current;

java.util.Date zeit=new java.util.Date();
stop=zeit.getTime()+millisekunden;

current=0;
while(current<stop)
{
java.util.Date zeit2=new java.util.Date();
current=zeit2.getTime();
}
}

/**
* public boolean verbindungOk()
*
* sende das Testzeichen 't' zum ASURO und warte auf die
* korrekte Antwort: "xASUROy"
* falls der ASURO richtig antwortet, return true
*
* @author robo.fr ( Nickname ) christoph(at)roboterclub-freiburg.de
*
* Feb.2008
*
*/

public boolean verbindungOk()
{
irSchnittstelle.read(); // Empfangsbuffer leermachen durch lesen
irSchnittstelle.write((byte)'t'); // Testkommando senden
msleep(200);
String text=irSchnittstelle.read();
if(debug) System.out.println(text);
if(text.contains("x") && text.contains("y"))
{
//if((text.indexOf("ASURO")-text.indexOf('x'))==1)
if(text.indexOf("xASUROy")!=-1)
{
if(debug) System.out.println("Test OK");
return true; // Test OK, der ASURO antwortet korrekt
}
}

if(debug) System.out.println("No ASURO");
return false;
}
/**
* public double liniensensorLinks(
*
* Wert des linken Liniensensors lesen
*
* @author robo.fr ( Nickname ) christoph(at)roboterclub-freiburg.de
*
* Feb.2008
*
*/
public double liniensensorLinks()
{
irSchnittstelle.read(); // Empfangsbuffer leermachen durch lesen
irSchnittstelle.write((byte)'l'); // Liniensensor Lesekommando
msleep(500);
String text=irSchnittstelle.read();
if(debug) System.out.println(text);
double x;
if(text.contains("x") && text.contains("y"))
{
String s=text.substring(text.indexOf("x")+1,text.indexOf("y"));

x=Double.parseDouble(s);

if(debug) System.out.println(x);
return x; // Test OK, der ASURO antwortet korrekt
}

if(debug) System.out.println("No Number");
x=Double.NaN; // return Not a Number
return x;
}
}

trapperjohn
26.02.2008, 11:45
Warum? Datenkapselung, Lesbarkeit, Wiederverwendbarkeit, ...

In deinem Mini-Programm kommt dir das vielleicht noch nicht besonders sinnvoll vor - aber wenn du die ASURO Kommunikation mal in einem größeren Umfeld benötigst, kannst du einfach deine Klasse (die dann evtl. X Methoden und eine Menge von Member-Variablen hat) nehmen und benutzen, völlig unabhängig vom Rest der Anwendung.

Abgesehen davon könntest du so 2 Asuros gleichzeitig an 2 Schnittstellen bedienen.

Was mir auf die Schnelle noch aufgefallen ist:

- der Konstruktor der Klasse darf keinen Rückgabewert (also auch kein "void") definieren

- im Kopf der for-Schleifen kann man direkt eine Zählvariable anlegen, also einfach

for (int i=0; i<10; i++) ... ;

- du musst mit dem Datentyp "byte" aufpassen. Der ist in Java immer "signed"! Darum wird in der Java API fast immer, wenn es um "richtige" Bytes geht, ein "int" verwendet.

robo.fr
28.02.2008, 17:03
Was mir auf die Schnelle noch aufgefallen ist:

- der Konstruktor der Klasse darf keinen Rückgabewert (also auch kein "void") definieren

Vielen Dank für den Hinweis. Der war sehr nützlich, in meiner neuen Klasse habe ich nämlich den selben Fehler gemacht und ich konnte ihn nicht finden, bis ich den Post gelesen habe.


Warum? Datenkapselung, Lesbarkeit, Wiederverwendbarkeit, ...
...
Abgesehen davon könntest du so 2 Asuros gleichzeitig an 2 Schnittstellen bedienen.

Ist schon klar. Mir scheint die Objektorientierung eher für Graphik-Anwendungen nützlich. Deshalb habe ich versucht, eine Klasse zu schreiben, welche die Messwerte der IR-Schnittstelle als Graph darstellt. Im ersten Schritt sind hier die Kommunikationsfunktionen noch nicht eingebunden und es werden einfach nur Zufallswerte dargestellt.

Leider flackert das Fenster immer, wenn ein neuer Punkt gezeichnet wird. Die Kurve wurde nur aktualisiert, wenn ich das Fenster mit "visible" ein-und ausschalte. Da müsste es eine andere Methode geben. Leider habe ich keine gefunden.



import java.awt.Graphics;
import java.awt.Point;
import javax.swing.*;
import java.lang.Math;
import ch.Timer;
/**
* Graph Klasse zur Darstellung von Kurvenverläufen
*
* @author robo.fr ( Nickname ) christoph(at)roboterclub-freiburg.de
*
* Feb.2008
*
*/
public class Graph extends JPanel // ein Graph ist ein Fensterobjekt
{
public String fenstername;
private Point fensterDimension; // Point ist hier kein Punkt, sondern Länge und Breite
private Point[] daten;
private final int datenLaenge;
private int datenIndex;

private Graph()
{
fenstername="Graph";
fensterDimension=new Point();
fensterDimension.x=320;
fensterDimension.y=240;
datenLaenge=64;
daten=new Point[datenLaenge]; // Punkte der Kurve
datenIndex=0;
}
/**
* Wert aus dem Datenarray graphisch darstellen
*
* @author robo.fr ( Nickname ) christoph(at)roboterclub-freiburg.de
*
* Feb.2008
*
*/

@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g); // original paintComponent aus JPanel aufrufen
if(datenIndex>0)
{
for(int n=0;n<(datenIndex-1);n++)
{
int k=fensterDimension.y/2;
g.drawLine(daten[n].x,k-daten[n].y,daten[n+1].x,k-daten[n+1].y);
}
}
}
/**
*
* Fügt dem Graph einen neuen Wert hinzu
* der interne Index wird automatisch erhöht
*
* @author robo.fr ( Nickname ) christoph(at)roboterclub-freiburg.de
*
* Feb.2008
*
*/
public void addWert(int wert)
{
Point a=new Point();
a.x=datenIndex;
a.y=wert;
if(datenIndex<(datenLaenge)) // noch Platz im Array vorhanden
{
daten[datenIndex]=a;
datenIndex++;
}
else // Array voll, Kurve verschieben
{
// Arraywerte nach unten verschieben
for(int n=0;n<(datenLaenge-2);n++)
{
daten[n]=daten[n+1];
}
daten[datenLaenge-1]=a;
}
}
/**
* Demo: langsam neue Datenpunkte zum Graph hinzufügen und darstellen
*/
public static void main(String[] args)
{
JFrame graph1=new JFrame("Graph");
graph1.setDefaultCloseOperation(JFrame.EXIT_ON_CLO SE);

Graph g=new Graph();

graph1.setSize(g.fensterDimension.x,g.fensterDimen sion.y);
graph1.add( g);

Timer t=new Timer();

for(int n=0;n<100;n++)
{
g.addWert((int)(Math.random()*100));

graph1.setVisible(true);
t.msleep(200);
graph1.setVisible(false);
}
System.out.println("Ende");
}
}

trapperjohn
28.02.2008, 20:23
Du musst repaint() aufrufen!

Und nein, die OO Programmierung ist nicht nur für GUI gut, sondern für alles - der Code wird einfach viel besser benutzbar und lesbarer usw. Es dauert einfach ein wenig, sich umzustellen um sic alles als Objekte und deren Beziehungen, Vererbungen etc. vorzustellen. UML hilft ;-)

robo.fr
29.02.2008, 21:03
Du musst repaint() aufrufen!
Vielen Dank, damit sieht das ganze schon viel besser aus =P~

Jetzt versuche ich gerade, eine graphische Benutzeroberfläche mit 3 Buttons für das ferngesteuerte Einschalten der LED's des ASURO zu programmieren.



import java.awt.Image;
import java.awt.FlowLayout;
import java.awt.BorderLayout;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class AsuroControl
{

public static void main( String[] args )
{

JFrame fenster = new JFrame("Java ASURO CONTROL");
fenster.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

//fenster.setLayout( new FlowLayout() );
fenster.setLayout( new BorderLayout(5,5) );

fenster.setSize(320,120);

JPanel schalterPanel=new JPanel();
schalterPanel.setLayout(new FlowLayout());
JPanel bilder=new JPanel();

Icon bild = new ImageIcon(AsuroControl.class.getResource( "/images/asuro.jpg" ) );


final JButton button1 = new JButton("BACK_LED_R");
final JButton button2 = new JButton( "BACK_LED_L" );
final JButton button3 = new JButton( "FRONT_LED" );
final JButton button4 = new JButton( bild );

schalterPanel.add( button1 );
schalterPanel.add( button2 );
schalterPanel.add( button3 );
bilder.add( button4);

fenster.add(schalterPanel,BorderLayout.PAGE_END);
fenster.add(bilder,BorderLayout.PAGE_START);
/*
AsuroKommandos asuro=new AsuroKommandos();
asuro.schnittstelleOeffnen("COM10");
asuro.verbindungOk() ; // prüfen und zeigen, ob Verbindung
asuro.schnittstelleSchliessen();
*/
fenster.pack();
fenster.setVisible( true );
}
}

Das ganze sieht dann wie das Bild aus. Jetzt stellt sich mir die Frage, wie ich die Tastedrücke mit der AsuroKommandos-Klasse verbinde.

trapperjohn
01.03.2008, 12:51
So bspw. :




//myAsuro ist das AsuroKommandos-Objekt
// - muss aber (bspw. als Member-Variable o.ä.) außerhalb
//der main()-Funktion bekannt sein.

button1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
myAsuro.xyz();

}
});


"Schöner" wird der Code übrigens, wenn man in main() nur bspw. das Anwendungsfenster erzeugt und das Fenster selbst weiß, wie es aussieht etc. Dazu lässt du AsuroControl von JFrame erben und die ganzen Initialisierungen des Fensters (erstellen der Buttons usw.) landen im Konstruktor der Klasse. In main() erstellst du nur noch ein Objekt von AsuroControl.

Wenn AsuroControl dann ein AsuroKommando-Objekt kennen muss, kannst du das der Klasse am besten direkt im Konstruktor mit übergeben.

robo.fr
01.03.2008, 18:25
Hallo trapperjohn,

leider habe ich Deinen Post jetzt ein wenig zu spät gelesen und mich inzwischenzeit ziemlich abgemüht, das Programm zum laufen zu kriegen ( sagt man eigentlich noch Programm zum laufen kriegen, oder eher Klasse zum laufen kriegen?).

Jetzt muss ich erst mal Deine Version genauer unter die Lupe nehmen.

Hier ist meine "Wurstelversion", die ich nicht besonders lesbar finde. Ich habe mich aber an das Buch "Java is auch ein Insel" gehalten. Da gab's eine ähnlich Konstruktion.



/**
* Einache Java Klasse mit graphischer Oberflaeche
* zur Steuerung eines ASURO-Roboters ueber die IR-Schnittstelle
*
* Funktionen: Leds ein und ausschalten
*
* @author robo.fr ( Nickname ) christoph(at)roboterclub-freiburg.de
*
* March.2008
*
*/
import java.awt.Image;
import java.awt.FlowLayout;
import java.awt.BorderLayout;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class AsuroControl extends JFrame implements WindowListener
{
private AsuroKommandos asuro=null;
private static boolean debug=true;

// Hier müssen alle Methoden zur Behandlung der Fenster-Events folgen
public void windowClosing( WindowEvent event )
{
asuro.schnittstelleSchliessen();
System.exit( 0 );
}
public void windowClosed( WindowEvent event ) { /*Empty*/ }
public void windowDeiconified( WindowEvent event ) { /*Empty*/ }
public void windowIconified( WindowEvent event ) { /*Empty*/ }
public void windowActivated( WindowEvent event ) { /*Empty*/ }
public void windowDeactivated( WindowEvent event ) { /*Empty*/ }
public void windowOpened( WindowEvent event ) { /*Empty*/ }

// das ganze Programm befindet sich im Konstruktor
AsuroControl()
{
setSize( 400, 400 );
addWindowListener( this );


asuro=new AsuroKommandos();
JPanel ledSchalterPanel=new JPanel();
JPanel bilder=new JPanel();

Action testAction = new AbstractAction( )
{
public void actionPerformed( ActionEvent e )
{
if(debug&asuro.verbindungOk()) System.out.println("passt");
}
};

Action FrontLedAction = new AbstractAction( "FrontLed" )
{
public void actionPerformed( ActionEvent e )
{
if(debug) System.out.println("FrontLed ein");
asuro.ledsOff(); // Led's aus
asuro.frontLed() ; // frontLed einschalten
}
};

Action BackLedLAction = new AbstractAction( "BackL" )
{
public void actionPerformed( ActionEvent e )
{
if(debug) System.out.println("linke BackLed ein");
asuro.ledsOff(); // Led's aus
asuro.backLedL() ; // backLedL einschalten
}
};

Action BackLedRAction = new AbstractAction( "BackR" )
{
public void actionPerformed( ActionEvent e )
{
if(debug) System.out.println("rechte BackLed ein");
asuro.ledsOff(); // Led's aus
asuro.backLedR() ; // backLedr einschalten
}
};

JButton buttonFrontLed = new JButton(FrontLedAction);
JButton buttonBackLedL = new JButton(BackLedLAction);
JButton buttonBackLedR = new JButton(BackLedRAction);

ledSchalterPanel.add(buttonBackLedL);
ledSchalterPanel.add(buttonFrontLed);
ledSchalterPanel.add(buttonBackLedR);

Icon bild = new ImageIcon(AsuroControl.class.getResource( "/images/asuro.jpg" ) );
JButton buttonAsuroBild = new JButton( bild );
buttonAsuroBild.addActionListener(testAction);
bilder.add( buttonAsuroBild);

this.setLayout( new BorderLayout(5,5) );

this.add(ledSchalterPanel,BorderLayout.PAGE_END);
this.add(bilder,BorderLayout.PAGE_START);

this.setTitle("Java ASURO control");
setVisible( true );

asuro.schnittstelleOeffnen("COM10");
}

public static void main( String[] args )
{
new AsuroControl();
}

}
/************************************************** *************************
*
* (c) 2008 robo.fr (Nickname) , christoph(at)roboterclub-freiburg.de
*
************************************************** *************************
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation version 2 of the License, *
* If you extend the program please maintain the list of authors. *
* ( if there is no real name, the nick name has to be mentioned )
* If you want to use this software for commercial purposes and you *
* don't want to make it open source, please contact the authors for *
* licensing. *
************************************************** *************************/


Morgen werde ich Deine Version mal genauer unter die Lupe nehmen und sehen, wie ich mein Konstrukt verbessern kann.

Gruß,
robo

trapperjohn
01.03.2008, 18:38
Das sieht ja schon ungefähr so aus, wie ich vorgeschlagen hatte. Nur die ganzen ActionListener würde ich noch so wie in meinem Beispiel als anonyme Klasse erstellen - also keine extra Variablen dafür sondern direkt im Aufruf von addActionListener() zusammenbauen.

M1.R
02.03.2008, 10:46
den ASURO will ich mit einem kleine Java-Programm steuern.
ne dumme Frage:
warum mit Java? Was kann Java, was C nicht kann?
Gruss
M.

trapperjohn
02.03.2008, 11:02
Plattformunabhängigkeit, Klassen und der Zugriff auf eine große Klassenbibliothek würde ich schon als großen Vorteil sehen ...

Mir fällt persönlich kein Grund ein, warum man heutzutage noch auf einem PC in Standard-C programmieren sollte, wenn C++, Java o.ä. zur Auswahl stehen. Aber das ist wieder eine typische Grundsatzdiskussion, die hier nix zu suchen hat ;-)

robo.fr
02.03.2008, 17:35
Für Java habe ich mich wegen der Plattformunabhängigkeit entschieden. Da es ja doch immer mehr Leute gibt, die einen Mac oder Linux nutzen, wollte ich sicherstellen, dass jeder das Programm benutzen kann.


Nur die ganzen ActionListener würde ich noch so wie in meinem Beispiel als anonyme Klasse erstellen - also keine extra Variablen dafür sondern direkt im Aufruf von addActionListener() zusammenbauen.

Das habe ich jetzt mal für einen der Knöpfe realisiert ( Lichtorgel ). Die anderen müsste ich auch noch umbauen, das werde ich auf später verschieben.

Mittlerweile hat sich der Code schon wieder etwas erweitert


/**
* Einfache Java Klasse mit graphischer Oberflaeche
* zur Steuerung eines ASURO-Roboters ueber die IR-Schnittstelle
*
* Funktionen: Leds ein und ausschalten
*
* @author robo.fr ( Nickname ) christoph(at)roboterclub-freiburg.de
*
* March.2008
*
*/

import java.awt.Image;
import java.awt.FlowLayout;
import java.awt.BorderLayout;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class AsuroControl extends JFrame implements WindowListener
{
private AsuroKommandos asuro=null;
private static boolean debug=true;
private JTextField batterieWert;

// Hier müssen alle Methoden zur Behandlung der Fenster-Events folgen
public void windowClosing( WindowEvent event )
{
asuro.schnittstelleSchliessen();
System.exit( 0 );
}
public void windowClosed( WindowEvent event ) { /*Empty*/ }
public void windowDeiconified( WindowEvent event ) { /*Empty*/ }
public void windowIconified( WindowEvent event ) { /*Empty*/ }
public void windowActivated( WindowEvent event ) { /*Empty*/ }
public void windowDeactivated( WindowEvent event ) { /*Empty*/ }
public void windowOpened( WindowEvent event ) { /*Empty*/ }

// das ganze Programm befindet sich im Konstruktor
AsuroControl()
{
setSize( 550, 400 );
addWindowListener( this );


asuro=new AsuroKommandos();
// Panel erstellen, die später im Fenster sichtbar werden
JPanel ledSchalterPanel=new JPanel();
JPanel motorSchalterPanel=new JPanel();
JPanel bilder=new JPanel();
JPanel textPanel=new JPanel();
JPanel multiFunktionsPanel=new JPanel();

// Zusammenstellung der Anzeigefelder
batterieWert=new JTextField();

double x=1.23; // Dummy Wert
batterieWert.setText("Batterie "+String.valueOf(x)+" V");
textPanel.add(batterieWert);

JButton lichtorgelButton=new JButton();
lichtorgelButton.setText("Lichtorgel");
multiFunktionsPanel.add(lichtorgelButton);

// Lichtorgel Demo: mit den LED's blinken
lichtorgelButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
for(int n=0;n<10;n++)
{
asuro.ledsOff(); // Led's aus
asuro.backLedL() ; // backLedL einschalten
asuro.backLedR() ;
asuro.frontLed();
}
asuro.ledsOff(); // Led's aus
}
});

// Action beim drücken des ASURO Bildes
Action testAction = new AbstractAction( )
{
public void actionPerformed( ActionEvent e )
{
if(debug&asuro.verbindungOk()) System.out.println("passt");
batterieWert.setText("Batterie "+asuro.batterie()+" V");
}
};
//****************** LED Actions ********************************
Action FrontLedAction = new AbstractAction( "vorne" )
{
public void actionPerformed( ActionEvent e )
{
if(debug) System.out.println("FrontLed ein");
asuro.ledsOff(); // Led's aus
asuro.frontLed() ; // frontLed einschalten
}
};

Action BackLedLAction = new AbstractAction( "links" )
{
public void actionPerformed( ActionEvent e )
{
if(debug) System.out.println("linke BackLed ein");
asuro.ledsOff(); // Led's aus
asuro.backLedL() ; // backLedL einschalten
}
};

Action BackLedRAction = new AbstractAction( "rechts" )
{
public void actionPerformed( ActionEvent e )
{
if(debug) System.out.println("rechte BackLed ein");
asuro.ledsOff(); // Led's aus
asuro.backLedR() ; // backLedr einschalten
}
};
//****************** Motor Actions ********************************
Action asuroVorAction = new AbstractAction( "vor" )
{
public void actionPerformed( ActionEvent e )
{
if(debug) System.out.println("Asuro vor");
asuro.gehVor();
}
};
Action asuroRueckAction = new AbstractAction( "rueck" )
{
public void actionPerformed( ActionEvent e )
{
if(debug) System.out.println("Asuro vor");
asuro.gehRueck();
}
};
Action asuroLinksAction = new AbstractAction( "links" )
{
public void actionPerformed( ActionEvent e )
{
if(debug) System.out.println("Asuro vor");
asuro.gehLinks();
}
};
Action asuroRechtsAction = new AbstractAction( "rechts" )
{
public void actionPerformed( ActionEvent e )
{
if(debug) System.out.println("Asuro vor");
asuro.gehRechts(); // Led's aus
}
};

// Zusammenstellung der LED-Schalter
JButton buttonFrontLed = new JButton(FrontLedAction);
JButton buttonBackLedL = new JButton(BackLedLAction);
JButton buttonBackLedR = new JButton(BackLedRAction);
JTextField ledBeschriftung=new JTextField();
ledBeschriftung.setText("Leds");

ledSchalterPanel.add(ledBeschriftung);
ledSchalterPanel.add(buttonBackLedL);
ledSchalterPanel.add(buttonFrontLed);
ledSchalterPanel.add(buttonBackLedR);

// Zusammenstellung der Motorschalter
JButton asuroVor = new JButton(asuroVorAction);
JButton asuroRueck = new JButton(asuroRueckAction);
JButton asuroLinks = new JButton(asuroLinksAction);
JButton asuroRechts = new JButton(asuroRechtsAction);
JTextField motorBeschriftung=new JTextField();
motorBeschriftung.setText("Motoren");

motorSchalterPanel.add(motorBeschriftung);
motorSchalterPanel.add(asuroVor);
motorSchalterPanel.add(asuroRueck);
motorSchalterPanel.add(asuroLinks);
motorSchalterPanel.add(asuroRechts);

// Laden und Einfügen des Asuro Bildes
Icon bild = new ImageIcon(AsuroControl.class.getResource( "/images/asuro.jpg" ) );
JButton buttonAsuroBild = new JButton( bild );
buttonAsuroBild.addActionListener(testAction);
bilder.add( buttonAsuroBild);

// Layout für das Gesamtfenster festlegen
this.setLayout( new BorderLayout(5,5) );

// Alle Panel zu Fenster hinzufügen
this.add(motorSchalterPanel,BorderLayout.PAGE_STAR T);
this.add(ledSchalterPanel,BorderLayout.PAGE_END);
this.add(bilder,BorderLayout.CENTER);
this.add(textPanel,BorderLayout.LINE_START);
this.add(multiFunktionsPanel,BorderLayout.LINE_END );

// Hauptfenster Titel setzen und sichtbar machen
this.setTitle("Java ASURO control");
setVisible( true );

asuro.schnittstelleOeffnen("COM10");
}

public static void main( String[] args )
{
new AsuroControl();
}

}
/************************************************** *************************
*
* (c) 2008 robo.fr (Nickname) , christoph(at)roboterclub-freiburg.de
*
************************************************** *************************
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation version 2 of the License, *
* If you extend the program please maintain the list of authors. *
* ( if there is no real name, the nick name has to be mentioned )
* If you want to use this software for commercial purposes and you *
* don't want to make it open source, please contact the authors for *
* licensing. *
************************************************** *************************/


und die Oberfläche sieht wie das Bild aus.
Wenn man auf den ASURO klickt, wird die Batteriespannung des ASURO ausgelesen und übertragen. Der Knopf "Lichtorgel" läst die LEDs Java gesteuert am Asuro blinken.
Beim Auslesen der Batteriespannung wäre es natürlich schöner, wenn das timergesteuert so alle 2 Sekunden passieren würde, da ist mir aber noch nicht ganz klar, wie das geht.

Es wäre schön, wenn sich ein Beta-Tester für das Programm finden würde, dann poste ich hier das ganze Projekt wieder.

Gruß,
robo

robo.fr
09.03.2008, 11:51
Leider sind die Threds etwas durcheinandergekommen, hier geht's weiter:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=38675

damaltor
09.03.2008, 16:07
guter hinweis, ich schliesse den thread hier.