Ich bin gerade dabei einen Roboter zu bauen, der einer Linie folgt.
Hardware steht alles, jedoch will ich meinen Algorithmus optimieren.
Arbeite mit dem Groove-System und habe 2 Fototransistoren (Line Finder) im Einsatz.
Sensoren sind zur Zeit mit einem Abstand von 27mm zueinander in der Breite der Linie angeordnet. Dieser Abstand kann noch geändert werden. Linienbreite habe ich 25/30mm zur Auswahl. Meine Überlegung mit den 27mm war es, wenn beide Sensoren auf der Linie (bzw. nicht auf der Linie, je nach dem welche Linienbreite ich wähle) liegen, der Roboter geradeaus fährt.
Aber das Problem ist, dass ich keine Ausrichtung entlang der Kante habe, sodass er immer nur so lange geradeaus fährt bis einer der beiden Sensoren eine Änderung feststellt, wodurch es zum ZickZack kommt.
Mir fehlt also ein Ansatz wie ich einen Algorithmus entwickeln kann, der zeitweise gerade Strecken möglichst Ruckelfrei abfahren lässt.
Den Versuchsaufbau werde ich nächste Woche startklar haben, sodass ich verschiedene Linienbreiten und Sensorabstände ausprobieren kann, jedoch nur mit meinem sehr einfachen Code.
In dem Fall ist die Linienbreite 30mm, sodass beide Sensoren zu Beginn auf der Linie liegen und HIGH ausgeben.
Übertrieben dargestellte Bewegung des Roboters auf einer breiten Linie.
Die Zeit bis zur nächsten Korrektur ist immer gleich bei einer Geraden, diese Zeitmessung kann man dann einbauen, damit das Programm erkennt, dass es sich um eine Gerade handelt und mit einem "Unterprogramm" (wie auch immer) die Korrekturen minimiert, sodass es evtl nach wenigen Sekunden möglich ist, möglichst gerade zu fahren.
Bei den Kurven ist die Zeit zur nächsten Korrektur nicht gleich, so könnte man (wenn man ausschließlich Kreiskurven benutzt) einen mathematischen Zusammenhang zwischen der Zeit und dem Radius der Kurve formulieren, sodass wieder durch ein "Unterprogramm" die Korrekturen im Idealfall nicht mehr ZickZack sind, sondern hauptsächlich nur in Richtung der Kurve korrigiert wird.
Wenn ich natürlich eine Ausrichtung einbauen könnte sodass sich der Roboter parallel zur Linie positionieren kann, könnte man ein Geradeausfahren sehr einfach realisieren. Genauso wie das Kurvenfahren, nämlich über die Geschwindigkeit der Motoren und dem daraus resultierenden Wendekreis, welcher sich der Kurve anpasst.
Denke ich zu einfach/zu kompliziert und habt ihr Tipps wie ich das hinbekommen kann oder das Problem anders löse?
Ich würde mal so anfangen, dass ich die Korrekturen immer kleiner als die vorangegangene Korrektur machen würde, wenn sich das Vorzeichen ändert, bei gleichem Vorzeichen sollten sich die Korrekturen addieren (oder schrittweise erhöhen).
Als Beispiel:
Robbi startet.
Robbi erkennt das Verlassen des Pfades nach links, also Korrektur mit Intensität +10 (wenn positive Korrektur nach rechts bedeutet.)
Wird wieder ein Verlassen des Pfades erkannt wird eine Korrektur von Intensität 9 (+9 nach rechts, -9 nach links) ausgeführt. Bei einer Korrektur nach links (also 2 mal die gleiche Richtung) wird als neuer (nächster) Korrekturwert die Summe (also 19) zwischengespeichert, wenn die Korrektur in die andere Richtung geht, dann wird als neuer Startwert 8 (also nächste kleinere Intensität) zwischengespeichert.
Damit ergeben sich eine immer weiter gedehntere Zickzack Spur, solange es geradeaus geht und ein recht heftiger Haken, wenn eine Kurve gefahren werden muss.
Mit den Intensitäten und den Stufen dazwischen ist noch zu experimentieren....
hajos118:
Damit ergeben sich eine immer weiter gedehntere Zickzack Spur, solange es geradeaus geht und ein recht heftiger Haken, wenn eine Kurve gefahren werden muss.
Den recht heftigen Haken verstehe ich noch nicht ganz.
Also du meinst wenn die Richtung immer wechselt (bzw. das Vorzeichen), beim Geradeausfahren wird das Zickzack gedehnt, ok das verstehe ich aber was passiert dann genau wenn die Kurve anfängt?
Greift das Programm dann erst ein wenn der Roboter zweimal in die selbe Richtung korrigieren muss und dann wird der Zwischenspeicher benutzt, sodass "radikaler" abgefahren wird?
für mich sieht das so aus, wie wenn die Ausschläge deiner Lenkung viel zu heftig wären.
Ich würde sei bei dauerhafter Abweichung langsam steigern, also ein I-glied mit einbauen.
Also:
Abweichnung nach links: kleiner Lenkeinschlag rechts
immer noch Abweichung nach links: Lenkeinschlag recht vergrößern
int LW // lenkwinkel
int dLW // delta Lenkwinkel
....
if (Wegabtasten() == links){
LW += dLW;
} else {
LW -= dLW
}
....
die Größe von dLW und die Zeit, wie oft abgetastet wird muss aufeinander abgestimmt werden.
@Quiyama:
Zweimal in die selbe Richtung korrigieren heisst effektiv, dass der Kurvenradius enger werden muss. Möglicherweise kommt das nicht nur 2 mal, sondern öfter hintereinander vor - dann schaukelt sich das recht leicht hoch... und es kommt schließlich zu einer Gegensteuerung (Korrektur in die andere Richtung). Was passiert, wenn die (langegezogene) Kurve noch nicht beendet ist, müsste man mal genauer durchdenken - wird aber definitiv zu heftigen Richtungsänderungen führen.
Zahlenbeispiel:
Zwischenspeicher = 3 (relativ gut geradeaus), dann kommt eine enge Kurve:
Korrektur nach rechts (3+1) - nochmal Korrektur nach rechts ( 3 + (3+1)) - nochmal Korrektur nach rechts (3 + (3+1) + ((3 + (3+1))+ 1), dann Gegenkorrektur (-17 +1)!!!
Vorstellen kannst Du dir das Verhalten so, dass möglichst versucht wird an der Wand entlang zu fahren und gerade noch eine kleine Korrektur (im Unendlichen) auszuführen.
Ist nur ein Gedankenspiel... @Gunterherb:
ein I-Anteil (aufaddieren) dürfte zu instabielem Verhalten führen. (in meinem Beispiel ist dies bei der mehrfachen Korrektur in eine Richtung der Fall).
Leider haben wir in dem geschilderten Problem nur eine relative grobe Abtastung und keine analog-Werte für die Abweichung zur Verfügung. Dadurch wird ein Regelungsansatz durch die heftigen Störgrößen ziemlich ruppig.
Für richtigen Geradeauslauf müßte der Winkel bekannt sein, in dem sich das Fahrzeug/Robot relativ zur Linie bewegt. Läuft er nach links von der Linie weg, kann man ihn so lange nach rechts drehen lassen, bis die Linie wieder erkannt wird. Dann eine Drehung nach links, um die halbe Anzahl von Encoder-Schritten, und der Roboter müßte genau in Richtung der Linie stehen. Dabei sollte die Linie breiter sein als der Sensorabstand. Wer will, kann das mit Zirkel und Lineal nachprüfen.
Da der Winkel aber nicht bekannt ist muss man sich eben annähern - z.B. in dem man die Korrektur in die entgegengesetzte Richtung kleiner macht als die vorangehende.
Der Winkel relativ zur Linie kann doch bestimmt werden, wie beschrieben. Wenn die Linie abknickt, sind nacheinander mehrere Korrekturen notwendig, alle nach dem gleichen Schema.
Stimmt. Im Idealfall läuft er dann genau in Richtung der Linie. Bei einem Bogen jedoch genau tangential - dadurch kann eine Bogenfahrt nicht erreicht werden. Mit dem "Annäherungs - Korrekturverfahren" ist jedoch auch eine Bogenfahrt möglich.
Danke @hajos118 sehr gut erklärt. Leider haben sich ein paar Teile verspätet, sodass ich das Ganze erst ab Freitag testen kann. Bin echt gespannt!
guntherb:
Abweichnung nach links: kleiner Lenkeinschlag rechts
immer noch Abweichung nach links: Lenkeinschlag recht vergrößern
Ist hiermit nicht auch die Korrektur bei Kurvenfahrt gemeint?
Danke auch dir für die Antwort @DrDiettrich ich werde es im Hinterkopf behalten, wenn ich es denn verstehen würde :') Was ist genau mit 'nach rechts laufen lassen' und 'nach links drehen lassen' gemeint. Also der Roboter hat ja eine Geschwindigkeit, die man festlegen kann, das hat doch keine Auswirkung auf die Encoder-Schritte (was ist das eig?) und eine Drehung dann um die eigene Achse?, bzw ja eig um die Achse der Sensorposition wenn überhaupt. Mir erschließt sich da der Zusammenhang nicht.
Den linePosition Wert bekommt er von einem QTR-8A Sensor. Dieser hat 8 Infrarot LEDs, und wenn die Linie in der Mitte des Sensors ist, liefert dieser 3500.
Da kann man ja mit deinen 2 Leds auch ein wenig spielen und einen optimalen Wert rausfinden.
Mein Fahrzeug hatte 2 Motoren am Heck, und der Sensor war vorne. Gelenkt hat er durch abbremsen des entsprechenden Rads.
Abweichnung nach links: kleiner Lenkeinschlag rechts
immer noch Abweichung nach links: Lenkeinschlag recht vergrößern
Das wäre eher eine Art von PI Regler. Wobei der Nachteil hier (im Gegensatz zu linearen Reglern) ist, dass man nur Auf der Linie / Abweichung ja/nein kennt, statt einer gemessenen Regel-Abweichung. Oder ?
Ganz genau. Ich schrieb oben, dass die Variable linePosition vom QTR-8A geliefert wird. Dieser gibt bei mittiger Linie den Wert 3500 aus. Dem entsprechend kann man den Wert in einem Regler abarbeiten und entsprechend benutzen.
Gibt dazu eine library. Allerdings kannst du deine 2 Infrarot LEDs auch benutzen. Stellat dein Fahrzeug mittig auf die Linie und schaust wie sich der Wert verändert wenn du es bewegst.
Der Regler hat sich in einem Wettbewerb bewährt. Wir sind mit 8 Fahrzeugen angetreten und haben die ersten 8 Plätze abgeräumt.