Zum Inhalt
c't

c't Projekte - c't-Bot und c't-Sim - Mailinglisten

c't-Bot und c't-Sim


[Voriger (Datum)] [Nächster (Datum)] [Voriger (Thread)] [Nächster (Thread)]
[Nach Datum][Nach Thread]

Re: AW: [ct-bot] MAP-Verhalten nur fuer Sim ? -> Patch fuer Verhalten

Absender: Timo Sandmann
Datum: Mi, 27.08.2008 18:52:12
In-reply-to: <48C139945BA47F4DB4DE05DF62CD57AA03C4FD852D@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
References: <000001c906ec$5d802ee0$0200a8c0@mexpnew> <3552FBF3-5B11-49C8-BE17-283FDF25DC18@xxxxxxxxxxxxxxx> <48C139945BA47F4DB4DE05DF62CD57AA03C4FD852D@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>


Hallo Frank,

Am 27.08.2008 um 08:09 schrieb Menzel, Frank IT-OO4:
Hallo Timo,
es gibt für die linke und rechte Spur jeweils ein Beobachter- Verhalten, welches diese Spur im Auge behält. Darin gibt es schon einen Timer, um erst nach Ablauf einer bestimmten Zeit auf die Map zuzugreifen, da es beim echten ja sonst zur Mapüberlastung kommen würde.

ja das ist mir auch nicht so ganz klar geworden: Wenn nur alle 700 ms auf die Map zugegriffen wird, ist es aber ja trotzdem ein reines Lotteriespiel, ob die Map gerade frei ist oder nicht. Dafür gibt es eigentlich die Funktion map_locked(). Außerdem bringt es ja nichts, seltener in der Map nachzuschauen, wenn man dafür dann einen größeren Bereich seit dem letzten Check prüfen muss (dauert dann entsprechend länger). Am Sinnvollsten erscheint mir, nach X cm gefahrener Strecke die letzten X cm nebendran zu prüfen. Entscheidend ist eigentlich nur, ob das Überwachen der Nebenspuren zeitlich noch passt oder nicht, wie oft man die Abfrage dann macht (solange derselbe Bereich nicht mehrfach überprüft wird), sollte eigentlich egal sein.

Ist die Map schon erforscht und es wird ein Hindernis auf der Nebenbahn laut Map (nach Ablauf der Zeitspanne seit letztem Check) erkannt, dann wird die bis zu dem Hindernis freie Strecke auf dem Stack vermerkt. Es wird dann wieder nach dem nächsten gültigen Startpunkt nach dem Hindernis gesucht und so geht es weiter. An einem Hindernis voraus angekommen entscheidet er sich für eine Richtung, vorzugsweise rechts, und fährt diesen rechts vom bot berechneten Startpunkt der Nebenbahn an. Wäre links auch eine freie Alternative gewesen, wird die linke Strecke (Start- und Endpunkt) auf den Stack gespeichert. Geht es irgendwann einmal nicht mehr für den Bot weiter, also rechts oder links von ihm Hindernis oder schon befahren, wird eine Strecke aus dem Stack geholt (dieser enthält ja nur unbefahrene Strecken) und angefahren. Beim Anfahren einer vom Stack geholten Strecke liegt diese ja durchaus relativ weit weg vom bot und der Weg dorthin kann auch von einem Hindernis verstellt sein. Zum Anfahren müßte eigentlich ein Pfadplanungsverhalten her, welches es aber noch nicht gibt. Der bot kann somit diese Strecke nur direkt anfahren, d.h. einen der beiden Streckenpunkte, vorzugsweise den nahesten. Ist dieser nicht erreichbar aber der Weg zum anderen Punkt frei, wird dieser angefahren und versucht, von dort aus die Strecke zu befahren. Ist diese auch nicht anfahrbar, wird die Strecke verworfen und die nächste vom Stack geholt. Ohen den Pfadplaner kann es somit auch zu unbefahrenen Stellen kommen. Nach dem Stackholen werden auch lange Strecken geradeaus gefahren, um den neuen Weg zu erreichen. Und hier bin ich aber auf das Map- Update voraus (der Hindernisse) angewiesen. Das Anfahren erfolgt hier zweistufig, einmal bis 30cm vorher. Dann wird der Punkt auf Mapwert geprüft und bei Hinderniswahrscheinlichkeit möglicherweise der andere Punkt angefahren. Also einfach Abschalten des Map-Updates bei Geradeausfahrt geht nicht, für die Freistrahlen schon (werden nicht gebraucht).

Ja du kannst zwar mit set_scan_otf_distance(0) das Distanzsensorupdate ausschalten, bis voraus ein Hindernis erkannt wird und dann wieder einschalten, aber das ist natürlich ein bisschen umständlich. Sollten wir das Distanzsensorupdate vielleicht feiner steuerbar machen? Also "ganz an" oder "ganz aus" oder "nur Hindernisse eintragen"? Das könnte sinnvoll sein, weil gerade das Update der Freistrahlen sehr lange dauert. Vielleicht funktioniert das Verhalten aber auch mit Distanzsensoren immer an, müsste man mal ausprobieren, wie viel Zeit das Überwachen der Nebenspuren wirklich braucht und ob das in die "Lücken" des Map- Updates passt.

Mit dem Bereitstellen einer allgemeinen "Auslese-Funktionalität" habe ich nicht so recht verstanden.

Das Problem bei der Map auf einer SD-Karte / MMC ist, dass ein (Schreib-)Zugriff (512 Byte) unterschiedlich lange dauert, je nachdem, ob der gewünschte Block noch im selben Cache-Block des MMC-Controllers wie der letzte benutzte Block ist oder nicht (im ersten Fall dauert es 1 ms und im Zweiten können es auch 50 ms werden, je nach Karte usw.). Daher kann man keine genaue Aussage treffen, wie lange ein Map-Update dauert und somit auch nicht exakt planen, ob es in Echtzeit während der Fahrt geht oder nicht. Darum läuft das Schreiben auf die Karte jetzt im Hintergrund, also letztlich immer dann, wenn der Bot alles für einen Zyklus bereits erledigt hat, aber seine Zykluszeit von 10 ms noch gar nicht aufgebraucht hat. Da ein Schreibzugriff deutlich länger als 10 ms dauern kann, muss man ihn folglich unterbrechen, um einen neuen Durchlauf der Bot-Main-Schleife ausführen zu können. Genau das passiert seit dem Map-Umbau auch. Der Nachteil an der ganze Sache ist, dass man natürlich während ein Schreibzugriff pausiert ist, nicht lesend auf die MMC zugreifen kann. Da unbekannt ist, wie lange ein Schreibzugriff dauert (s.o.), kann man nicht voraussagen, wann man lesend auf die MMC (und somit auf die Map) zugreifen kann. Die Funktion map_locked() gibt Auskunft darüber, ob die Karte gerade gesperrt ist, oder man auf sie zugreifen kann. Greift man (über eine der Funktionen aus map.h) auf eine gesperrte Karte zu, wird der Zugriff solange verzögert, bis die Karte wieder frei ist. Allerdings werden damit auch alle anderen Bot-Aktivitäten (Sensorupdates, Notfallverhalten usw.) blockiert, es wird alles angehalten und das Map-Update zu Ende geführt. Nicht besonders elegant, aber auf Grund der beschränkten Ressourcen des ATmegas ein Kompromiss. Der Gedanke dabei ist, dass man die Karte eben nur dann ausliest, wenn entweder map_locked() == 0 oder wenn der Bot stillsteht, denn dann schadet es nicht, falls keine Sensorupdates und Notfallverhalten ausgeführt werden. Soviel erstmal zum allgemeinen Ablauf bei der Map (ich weiß es fehlt noch eine anständige Dokumentation...)

Was ich mit einer allgemeinen Funktionalität zum Auslesen der Map meinte: Dein neues Verhalten könnte jetzt entweder mit map_locked() usw. seine Zugriffe selbst koordinieren, oder wir machen genau wie für das Map-Update ein Gegenstück zum Auslesen der Map. Also dass man sagen kann, ich möchte gern die und die Auskunft von der Map (irgendeine der Funktionen, die es in map.h gibt), die eigentliche Abfrage wird dann auch im Hintergrund ausgeführt und wenn das Ergebnis zur Verfügung steht, kann es vom Verhalten, das es braucht, "abgeholt" werden. Für ein Verhalten, das die Map benutzen will, lohnt sich das vielleicht nicht, aber wenn es mehrere Verhalten gibt, die ähnliches brauchen, macht es vielleicht Sinn, das Ganze zentral vom Map-Code aus bereitzustellen?

Beim echten bot sollte es eigentlich auch funktionieren, habe mit diesem aber momentan ein paar Problemchen und kann nicht testen...

Oh sorry, da im Betreff steht "nur für Sim", habe ich es auf dem echten Bot gar nicht erst ausprobiert, werde ich mal nachholen!

Was mir beim Testen im Sim aufgefallen ist: Wenn der Bot bis zur Wand rechts (oder links) vorgedrungen ist (die aber noch nicht als Hindernis in der Map steht), crasht er irgendwann seitlich in die Wand und hängt dort fest. Das ist eigentlich bei allen Welten im Sim so. Dadurch kommt es leider nie zu dem Fall, dass das Verhalten den Bot zur anderen Seite der schon abgefahrenen Fläche schickt, was aber ja eigentlich einer der interessantesten Fälle ist.

Grüße,
Timo