Koordinatensystem zur Roboterorientierung

zubuku

Mitglied
Hallo,
ich baue seit einiger Zeit mit Freunden im Rahmen einer Schul-AG an einem Roboter. Zur Orientierung verwenden wir einen schwenkbaren Infrarot-Entferungsmesser, der ca. 20 Messungen pro Sekunde schafft.
Die Messdaten werden von einem Arduino I/O-Board erfasst und dann an einen Laptop geschickt, das klappt auch schon soweit.

Jetzt wollen wir die gemessenen Punkte in ein Koordinatensystem eintragen, das hauptsächlich dazu dienen soll, zu prüfen ob ein Hindernis auf einer bestimmten Strecke liegt.
Da wir eher Einsteiger sind, was das Programmieren angeht, sind wir uns nicht sicher wie man so ein Koordinatensystem in Java am besten umsetzt.
Damit wir nicht zu viel Zeit und Arbeit an einem umständlichen Lösungsweg verschwenden, wollte ich hier nach der besten Lösungsrichtung fragen.

Mit welcher Klassenbibliothek können wir so ein Koordinatensystem am besten umsetzen?
Durch googlen bin ich auf folgendes gestoßen:
- Java2D
- ein zweidimensionales Array als Koordinatensystem
- awt.geom


Ich denke man hört heraus, dass ich ein blutiger Anfänger bin. Aber wir wollen das Programmieren beim Machen lernen, daher wäre es super, wenn ihr uns grob in die richtige Richtung schickt, damit wir uns nicht unnötig abstrampeln. :)
 
T

Tomate_Salat

Gast
Wollt ihr die Daten visualisieren oder geht es euch erstmal darum, diese zu halten?
Habt ihr ein Beispiel, wie die Daten aussehen, die ihr gesendet bekommt?
reicht euch ein 2D-Raum oder braucht es dafür 3D?
 

zubuku

Mitglied
Wir planen auch, dass die Daten später als Karte visualisiert werden können. Aber wichtiger ist die weiterverwendung zur Orientierung (=>Ist ein Hindernis auf der Strecke?).

Die Daten, die wir am Laptop haben sind ausgehend vom Roboter Winkel und Entfernung eines Messpunkts. 0° liegt dabei genau vor dem Roboter, negative Winkel links, positive rechts vom Roboter.
Wenn kein Hindernis in Sensorreichweite liegt, werden keine Daten an den Laptop geschickt.

Hier zwei Grafiken mit Beispieldaten (2.Bild):
qakqf2bc.jpg
sa6revic.jpg


ein 2D-Raum reicht völlig, da wir auch nur zweidimensional messen können
 
Zuletzt bearbeitet:
T

Tomate_Salat

Gast
Die Daten sollten sich gut in ein Koordinatensystem mit x/y-Werten umrechnen lassen. Ich würde hier zum halten der Daten wahrscheinlich ein [japi]Polygon[/japi] verwenden.

Sind die Winkel bekannt in denen gemessen wird? Dann kann man auch etwa anfang+ende eines Objektes bestimmen und diese Daten in das erwähnte Polygon-objekt schreiben. Dabei gilt: Pro Hindernis ein Polygon. Dieses kann später auch einfach gezeichnet werden.

Btw: sehr schön angeführtes Beispiel.
 

zubuku

Mitglied
Die Winkel sind leider nicht bekannt. Unser billig-Servo der für das Schwenken zuständig ist, ist sehr ungenau(+-4°).

Danke für den Hinweis auf [JAPI]Polygon[/JAPI], sieht sehr nützlich aus. Vor allem da man mit intersect-Methode direkt prüfen kann, ob sich das Polygon mit der rechteckigen Fläche schneidet, die der Roboter auf einer bestimmten Strecke durchfährt. Und googeln fällt auch leichter, wenn man erstmal nen Anfang hat. ;)

Ich hab mal ein wenig damit rumprobiert und intersect funktioniert leider nur für Polygone mit 3 oder mehr Punkten (ergibt ja auch Sinn, da sonst keine Fläche eingeschlossen wird).
Das bedeutet bei Hindernissen bei denen nur ein oder zwei Punkte erkannt werden (z.B. oben im 2. Bild, die Punkte 4 und 5), kann ich die Methode nicht benutzen.
Hab ein wenig gegoogelt, durch [JAPI]Line2D[/JAPI] könnte ich Linien speichern,mit [JAPI]Point[/JAPI] Punkte.
Das sollte funktionieren, aber gibt es auch eine Klasse in der ich Punkte, Linien und Vielecke unterbringen kann?
Vielleicht [JAPI]Generalpath[/JAPI]?


Momentan stell ich mir das so vor, dass er bei jedem neuen Punkt die Entfernung zu den bestehenden Hindernissen prüft. Ist die Entfernung kleiner als der Durchmesser des Roboters, kommt er nicht durch, also kann man den neuen Punkt zum bestehen Hindernis(Polygon) hinzufügen. Ist die Entfernung größer als der Durchmesser, hat der Roboter ein neues Hindernis gefunden, dass dann auch als neues Hinderniss abgespeichert wird.


Auf jeden Fall schonmal vielen Dank für deine Hilfe. :)
 
T

Tomate_Salat

Gast
Ich würde bei Polygonen bleiben. Selbst Punkte lassen sich mit entsprechenden Strokes gut abbilden. Ich hab dir mal ein kskb gebaut, wie ich es mir etwa vorstelle:

Java:
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class PathDemo extends JComponent 
{
	private static final long serialVersionUID = 1L;

	public static void main(String[] args) 
	{
		final JFrame frame=new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		final PathDemo demo=new PathDemo();
				
		demo.addPoly(new Polygon(new int[] {222}, new int[] {120}, 1));
		demo.addPoly(new Polygon(new int[] {22,5}, new int[] {100,20}, 2));
		demo.addPoly(new Polygon(new int[] {100,30,50}, new int[] {10,50,200}, 3));
		
		frame.add(demo);
		
		final JSlider slider=new JSlider();
		slider.setValue(demo.getStrokeSize());
		slider.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				demo.setStrokeSize(slider.getValue());
			}
		});
		slider.setMinimum(1);
		slider.setMaximum(20);
		
		frame.add(slider, BorderLayout.SOUTH);
		
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				frame.setSize(400, 300);
				frame.setLocationRelativeTo(null);
				frame.setVisible(true);
			}
		});
	}
	
	private List<Polygon> objs=new ArrayList<Polygon>();
	private int strokeSize=2;
	
	public void addPoly(Polygon p)
	{
		objs.add(p);
		repaint();
	}
	
	public void setStrokeSize(int size)
	{
		if(size<=0)
			return;
		strokeSize=size;
		repaint();
	}
	
	public int getStrokeSize()
	{
		return strokeSize;
	}
	
	@Override
	protected void paintComponent(Graphics g) 
	{				
		Graphics2D g2d=(Graphics2D)g;
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		
		BasicStroke stroke=new BasicStroke(strokeSize,BasicStroke.CAP_ROUND,BasicStroke.JOIN_BEVEL);		
		g2d.setStroke(stroke);		
		
		for(int i=0;i<objs.size();i++) {			
			g2d.setColor(i%2==0 ? Color.BLUE : Color.RED);			
			g2d.drawPolygon(objs.get(i));
		}
	}
}
 
N

New_Escaflowne

Gast
Das Problem, dass du mit der intersect Methode lässt sich ja relativ leicht lösen, indem du von Polygon erbst und die intersect-Methode entsprechend umschreibst und Verhalten für einen Punkt und eine Strecke hinzufügst.
Sobald du drei Punkte hast, kannst du ja mit super.intersect(...) auf die ursprüngliche Methode zugreifen.
 

zubuku

Mitglied
Vielen Dank für das Beispiel, wieder was dazu gelernt :)
Kann ich mit den Strokes auch direkt prüfen, ob sich die Fläche der "Kontur" mit einer bestimmten rechteckigen Fläche überschneidet? Hab mit dem Beispiel rum experimentiert, aber keine Möglichkeit gefunden.

Ansonsten sollte das auch gut mit New_Escaflownes Vorschlag funktionieren. Wenn ich das richtig verstanden habe bau ich mir eine eigene Klasse, die intersect so verändert, dass sie zwischen 1,2 und >=3 Punkten unterscheidet und dann auch für jeden der drei Fälle funktioniert.

Bei den Polygonen stört mich noch etwas, dass dabei mitunter ziemlich komische Formen herauskommen können, wenn der Roboter ein Hindernis von mehreren Seiten betrachtet und dann die einzelnen Punkte in der "falschen" Reihenfolge sind. Lässt sich das irgendwie sortieren?


Auf jeden fall vielen Dank für eure Hilfe, das ist jetzt auch meine letzte Frage, danach können wir dann loslegen :)
 

Ähnliche Java Themen


Oben