Jemower findet nicht nach Hause

jemihi

New member
Hallo,

nu ist endlich meine Prototypenplattform fahrbereit mit einer recht aktuellen Revision aus dem SVN (R221) und ich habe zum ersten Mal auch die Funktion "Perimeter" eingebaut. Das normale zufällige Umherfahren bis an das Perimeterkabel funktioniert nach Optimierung von Roll- und Reversefahrzeiten nun auch sehr ansehnlich. Ich habe mir zum Testen ein (glaub) 15m Kabel einmal im Kreis mitten in den Rasen gelegt.

Dann hat mich der Größenwahn gepackt, und ich habe auf "Home" in der pfodApp geklickt. Er findet das Kabel, überfährt es, fährt in einem ziemlich heftigen Schlenker wieder auf die richtige Seite des Perimeter und danach wird der Schlenker wild, er überfährt das Perimeterkabel immens und dreht dann irgendwann auf der Stelle. Der Fehler dabei ist eigentlich nur, dass er beim zweiten Mal Überfahren in Richtung Außen zwar in die richtige Richtung dreht, nur leider 1 viel zu spät und dann 2. nicht auch fährt. So findet er das bei weitem überfahrene Kabel natürlich nicht mehr wieder. Ich habe keine Ahnung mehr, wie ich es mit den App-Parametern in Griff kriegen soll.

Im Video ist das Problem (reproduzierbar) zu sehen.

[video width=425 height=344 type=youtube]hQJ3ddiKpps[/video]

0:14 erstes Überfahren des Perimeters nach außen
0:26 zweites Überfahren des Perimeters nach außen
0:30 Reaktion auf Überfahren

Ist der I-Anteil zu hoch? Wenn ich ihn reduziere oder erhöhe wird es aber nicht besser, nur anders :) Das Ergebnis bleibt immer geich ... (er steht etwa 0,3-1m außerhalb des Perimeters und dreht auf der Stelle).

Vielleicht kann mir wer helfen ?

Gruß,
Jem
 
@Jem: ich glaub da müssen wir nachbessern :) - Der Code befindet sich in mower.cpp (Zeile 377):

// PID controller: track perimeter
void Robot::motorControlPerimeter() {...}


Das Drehen setzt ein wenn der Roboter länger als 5 Sekunden (=5000 Millisekunden) keinen "Perimeter-Wechsel" (in/out) gesehen hat. Die Idee ist dass der Roboter evtl. steckengeblieben ist und durch die Drehbewegung wieder weiter kommt. Er dreht dabei solange bis wieder ein Perimeter-Wechsel stattfindet...

-Wir sollten die Zeit ggf. hochsetzen
-Evtl. könnten wir auch noch die Grundgeschwindigkeit (motorSpeedMaxPwm/2) hochsetzen

Evtl. kannst Du das ja mal ausprobieren, dann übernehmen wir ggf. tolerantere Werte...
 
Wie ist denn die Regelung gedacht? Wenn er das Perimeter überfährt, wird das jeweils gegengleiche Rad schneller und das andere langsamer?

Ich sehe als starkes Problem, dass er bei einer Zufahrt in einem rechten Winkel auf das Perimeter trifft, so derb überfährt und dann, wenn eigentlich schon auf dem richtigen Weg ist, weil er danach das Perimeter wiedergefunden hat, plötzlich anfängt, sich immer soweit zu drehen, dass er wieder 90° auf das Perimeter zufährt. Dann beginnt das Spiel von vorne, oder er fährt sogar viel zu weit (wie im Video zu sehen).

Manchmal dreht er wenn er wieder im Perimeter ist auch zu weit und fährt einmal durch die ganze Fläche auf die andere Seite. Das sah dann aus wie Ping Pong ...

Ich denke mich nochmal in die Steuerung ein und versuche zu optimieren :)

Gruß,
Jem

Edit: Ich denke, du meintest robot.cpp :)

Edit 2: In dem Zuge, den Code zu verstehen, nur die Frage, ob beim State_Roll diese Zeile richtig ist:
stateEndTime = millis() + rand() % motorRollTimeMax/2 + motorRollTimeMax/2;
Müsste es nicht rand() * motorRollTimeMax/2 heißen?
Und hast du das seed von rand() irgendwo initialisiert?
 
Ablauf:

--STATE_PERI_FIND--
Suchen des Schleife-Außen Signals. Wenn gefunden, einfädeln. Grund: Der Roboter liegt gerade deutlich zu weit über der Schleife (außen). Damit die Regelung "Zeit" bekommt, sollte der Roboter besser nach innen zeigen. Daher das Einfädeln.

--Einfädeln" (void Robot::checkPerimeterFind(){...})--
Der Roboter dreht solange nach rechts, bis er ein "innen" sieht. Dann geht er in "STATE_PERI_TRACK"

--STATE_PERI_TRACK--
Grundgeschwindigkeit beider Räder ist motorSpeedMaxPwm/2. Es wird der Fehler berechnet (positiver Fehler falls innen, negativer Fehler falls außen). Der Fehler wird dann mit der Grundgeschwindigkeit verrechnet:

linker Motor : motorSpeedMaxPwm/2 - Fehler
rechter Motor : motorSpeedMaxPwm/2 + Fehler

Dadurch pendelt der Roboter immer um die Schleife. Die Stärke, Trägheit etc. kann mit den PID Parametern eingestellt werden.

Falls der Roboter innerhalb von 5 Sek. keinen Schleifen-Wechsel sieht, geht er in den "Freistrampeln"-Modus:

--"Freistrampeln" (millis() > perimeterLastTransitionTime + 5000)--
Roboter ist "außen":
linker Motor: motorSpeedMaxPwm/1.5
rechter Motor: -motorSpeedMaxPwm/1.5

Roboter ist "innen":
linker Motor: -motorSpeedMaxPwm/1.5
rechter Motor: motorSpeedMaxPwm/1.5

Damit dreht er also auf der Stelle (links vor, rechts zurück bzw. umgekehrt) in die richtige Richtung.

Findet er jedoch innerhalb der nächsten 5 Sek. immer noch keinen Schleifen-Wechsel, geht er wieder in den "STATE_PERI_FIND" Zustand und sucht erneut die Schleife.


NACHTRAG: "rand() % ZahlMax" ist schon richtig - rand() liefert "große" Zufallszahl und die Modulo-Operation (Rest) sorgt für die Einhaltung der Grenzen.
 
Ah okay, ich schaue mal, ob ich dieses Verhalten beim Mower sehe.

Bei mir hat er soweit ich das gesehen habe, nicht nach einem "Freistrampeln" außerhalb der Schleife anschließend angehalten, sondern ewig weitergestrampelt (auch kein Perifind gemacht, aber das dürfte von der Logik ja nur innerhalb der Schleife folgen).

Zum rand() ... ich dachte es würde eine Zufallszahl zwischen 0 und 1 ausgeben ...

Gruß und danke soweit,
Jem
 
Oben