## c't-Projekte - Mailinglisten

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

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

Absender: Frank Menzel
Datum: Mo, 25.08.2008 21:54:25
In-reply-to: <317B8D88-9F6F-4458-BCA7-DFEFBBA106C7@xxxxxxxxxxxxxxx>

    Hallo,
    zu dem u.a. Thema habe ich nun das Verhalten fertig, so dass ich es hier
    mal einreiche. Das Verhalten wird via Taste 8 gestartet und fährt nun
    eine Spur nach der anderen ab, wobei sich Alternativwege auf dem
    Pos-Stack gemerkt und diese dann später angefahren werden. Anhand der
    Map werden Hindernisse auf den Nebenspuren erkannt und Zwischenwege
    erzeugt, ebenso wird eine bereits befahrene Spur anhand der Map als
    solche erkannt und nicht mehr angefahren.
    Einfach mal laufen lassen...

    Gruß, Frank Menzel

    -----Ursprüngliche Nachricht-----
    Von: ct-bot-entwickler-bounces@xxxxxxxxxxxxxxxxx
    [mailto:ct-bot-entwickler-bounces@xxxxxxxxxxxxxxxxx] Im Auftrag von Timo
    Sandmann
    Gesendet: Donnerstag, 3. Juli 2008 14:28
    An: Entwicklung rund um den c't-bot
    Betreff: Re: [ct-bot] MAP-Verhalten nur fuer Sim ?

    Am 02.07.2008 um 12:21 schrieb Frank Menzel:
    > Hallo,
    > ich hatte da ein wunderschönes MAP-Verhalten im Sim entwickelt,
    > könnte man als Staubsaugerverhalten bezeichnen oder flächendeckendes
    > Fahren. Doch was leider im sim so schön funktioniert, klappt nicht
    > beim realen bot wegen der Langsamkeit. Kern sind hierbei
    > Unterverhalten, welche jeweils die Nachbarspur in der Map
    > beobachten. Alle Versuche, dies so beim realen Bot zu implementieren
    > sind fehlgeschlagen wegen der langsamen und den bot bremsenden
    > Mapzugriffe.
    > Ich hatte es bereits ad acta gelegt unter nicht machbar, doch wollte
    > ich nun einfach mal anfragen, ob das Verhalten -auch wenn es nur
    > simfähig ist- nicht vielleicht doch von Interesse ist. Dann könnte
    > ich es verpatchen und einreichen und nicht für immer in Ablage P
    > verschwinden lassen (wäre zu Schade bei all der investierten Zeit
    > und Mühe).
    >
    > gruss, Frank Menzel

    Hallo,

    das Verhalten ist auf jeden Fall aus verschiedenen Gründen sehr
    interessant:
    1.) Es gibt bisher eigentlich gar kein Erkundungsverhalten, auch nicht
    ohne Map.
    2.) Die Map-Zugriffe sind jetzt durch den Umbau auf PC und Bot nahezu
    identisch, bis auf das unterschiedliche Zeitverhalten natürlich. Daher
    lässt es sich vielleicht doch auf dem Bot einsetzen, wenn man ein paar
    Wartezeiten in Kauf nimmt.
    Wenn der Bot wegen des Map-Updates anhält, kann das zwei Gründe haben:
    Entweder ist der Cache voll oder es versucht selbst die Karte zu
    lesen, während sie noch beschrieben wird. Für den ersten Grund kann
    das Verhalten selbst nichts, ist das der Fall, müssen wir eventuell
    noch weiter am Map-Code optimieren oder die Cachegröße anpassen.
    Allerdings kann das Verhalten selbst bestimmen, ob der Bot in diesem
    Fall anhält oder Daten verwirft.
    3.) Vielleicht wird durch das Verhalten auch klar, dass der derzeitige
    Map-Ansatz noch zu inflexibel oder schwierig zu benutzen ist. Wenn
    durch das neue Verhalten ersichtlich wird, wo noch Verbesserungsbedarf
    besteht, lässt sich das vermutlich nachrüsten und das Verhalten
    funktioniert dann.
    4.) Es gibt immer noch die Möglichkeit anstatt des ATmega32 einen
    ATmega644 im Bot einzusetzen, der doppelt soviel RAM hat. Dort lassen
    sich die nötigen Map-Daten für das Verhalten vielleicht als Kopie
    vorhalten, die dann sehr schnell verwendet werden kann.

    Das kommt natürlich alles stark auf die Implementierung des Verhaltens
    an, darum ist es sehr von Interesse.
    Wann ich persönlich dazu komme, mir den Code anzuschauen, um das
    besser beurteilen zu können, kann ich jetzt aber leider nicht
    versprechen.

    Außerdem kannst du den Patch natürlich auch gerne unter
    http://www.heise.de/ct/projekte/machmit/ctbot/wiki/Patches
    veröffentlichen, vielleicht lesen dort mehr Leute als in der
    Mailingliste hier. Die Seite soll ja auch als Archiv dienen, was die
    Mailingliste nur schlecht leisten kann.

    Gruß Timo
    _______________________________________________
    ct-bot-entwickler Mailingliste
    ct-bot-entwickler@xxxxxxxxxxxxxxxxx
    http://www.heise.de/bin/newsletter/listinfo/ct-bot-entwickler

    Index: C:/botneu/ct-Bot/bot-logic/behaviour_area.c
    ===================================================================
    --- C:/botneu/ct-Bot/bot-logic/behaviour_area.c	(revision 0)
    +++ C:/botneu/ct-Bot/bot-logic/behaviour_area.c	(revision 0)
    @@ -0,0 +1,964 @@
    +
    +/*
    + * c't-Bot
    + *
    + * 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; either version 2 of the License, or (at your
    + * option) any later version.
    + * This program is distributed in the hope that it will be
    + * useful, but WITHOUT ANY WARRANTY; without even the implied
    + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
    + * PURPOSE. See the GNU General Public License for more details.
    + * You should have received a copy of the GNU General Public
    + * License along with this program; if not, write to the Free
    + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
    + * MA 02111-1307, USA.
    + *
    + */
    +
    +
    +/*! @file 	behaviour_area.c
    + * @brief 	Flaechendeckendes Fahren als Verhalten (Staubsauger)
    + *          Der Bot faehrt geradeaus bis zu einem Hindernis, dort dreht er sich zu einer Seite und faehrt auf der Nebenspur wieder zurueck. Der
    + *          andere moegliche Weg wird als Alternative auf den Stack gespeichert. Falls es irgendwo nicht weitergeht, so wird eine solche Strecke
    + *          vom Stack geholt und angefahren. Leider gibt es noch kein Map-Planungsverhalten, welches einen anderen Punkt unter Umgehung von
    + *          Hindernissen anfaehrt. In dieser Version wird etwas tricky gefahren und versucht, diese Strecke anzufahren. Im Falle
    + *          aber des nicht moeglichen Anfahrens wird eben diese Strecke verworfen. Ein Planungsverhalten, welches moeglichst auch
    + *          nur ueber befahrene Abschnitte plant, wuerde entscheidend helfen.
    + *
    + * @author 	Frank Menzel (Menzelfr@xxxxxxx)
    + * @date 	16.07.2008
    +*/
    +
    +#include "bot-logic/bot-logik.h"
    +
    +#ifdef BEHAVIOUR_AREA_AVAILABLE
    +
    +#include <math.h>
    +#include <stdlib.h>
    +
    +#include "map.h"
    +#include "timer.h"
    +#include "math_utils.h"
    +#include "pos_stack.h"
    +
    +/*! nur alle X-Millisekunden Mapzugriff der Observer-Verhalten */
    +#define	CORRECTION_DELAY	700
    +
    +/*! Mapwert zur Erkennung einer bereits befahrenen Spur */
    +#define MAP_TRACKVAL   30
    +
    +/*!  In diesem Abstand voraus [mm] ab Abstandssensoren wird auf Hindernis gecheckt */
    +#define DIST_AWARD_HAZ  OPTIMAL_DISTANCE
    +
    +/*! ca. 1 1/2 Botbreiten, Mindestabstand der Punkte fuer eine gueltige Bahn, welche es zu befahren gilt */
    +#define DIST_GUILTY_QUAD (150 * 150)
    +
    +/*! anzufahrender Punkt gilt als sehr nah zum Bot, wenn Abstand kleiner Botdurchmesser (Quadrat) */
    +#define DIST_GUILTY_LOW (BOT_DIAMETER * BOT_DIAMETER)
    +
    +/*! Defines zum festlegen, auf welcher Seite des Bots sich die Spur befindet */
    +#define TRACKLEFT  -1
    +#define TRACKRIGHT 1
    +
    +/*! Verhalten-Define zum Verlassen */
    +#define TRACK_END 99
    +
    +/*! zu erreichender Punkt laut Observer neben dem Bot auf Parallelbahn; Korrekturwert, um den der
    + *  Seitenabstand (Botdurchmesser) subtrahiert wird
    + */
    +#define SIDEDIST_MINUS  30
    +
    +
    +
    +/*! Statusvariable des area-Verhaltens */
    +static uint8 track_state = 0;
    +
    +/*! Notfallkennung fuer Abgrund; wird gesetzt in registrierter Notfallroutine */
    +static uint8 border_fired=False;
    +
    +/*! Statusvars fuer die Observer-Verhalten links und rechts */
    +static uint8 observe1_state=0;
    +static uint8 observe2_state=0;
    +
    +/*! Zeit-Merkvariable fuer die Observer-Verhalten fuer Mapzugriff erst nach Ablauf einer gewissen Zeit */
    +static uint32_t lastCorrectionTime = 0;
    +static uint32_t lastCorrectionTimeObserveLeft = 0;
    +static uint32_t lastCorrectionTimeObserveRight = 0;
    +
    +/*! Strukturtyp fuer die beobachteten Nachbar-Bahnen; fuer Links und Rechts bestehend aus 2 Punkten */
    +typedef struct {
    +	int16 point1x; /*!< Einzelne Punkte */
    +	int16 point1y;
    +	int16 point2x;
    +	int16 point2y;
    +} trackpoint_t;
    +
    +/*! Nachbarbahnen links und rechts */
    +static trackpoint_t observe_trackleft;
    +static trackpoint_t observe_trackright;
    +
    +/*! nachste anzufahrende Bahn */
    +static trackpoint_t nextline;
    +
    +
    +/* ==================================================================================
    + * ===== Start der allgemein fuer diese Verhalten notwendigen Routinen ==============
    + * ==================================================================================*/
    +
    +
    +
    +/*!
    + * Notfallhandler, ausgefuehrt bei Abgrunderkennung und muss registriert werden
    + */
    +void border_area_handler(void) {
    +	// Routine setzt hier einfach nur die Borderkennung, die vom area-Verhalten ausgewertet wird
    +	  border_fired=True;
    +}
    +
    +
    +/*!
    + * liefert den Wert eines Feldes als Durchschnittwert laut Map in bestimmtem Umkreis
    + * @param x	X-Weltkoordinate
    + * @param y	Y-Weltkoordinate
    + * @return	Durchschnittswert des Feldes (>0 heisst frei, <0 heisst belegt)
    + */
    +int8_t map_get_field(int16_t x, int16_t y) {
    +	return map_get_average(x, y, 50);  // Mapwert Durchschnitt
    +}
    +
    +
    +
    +/*!
    + * Speichert eine Line auf dem Stack, d.h. den Start- und Endpunkt der Linie
    + * @param x1	X-Koordinate des ersten Punktes der Linie
    + * @param y1	Y-Koordinate des ersten Punktes der Linie
    + * @param x2	X-Koordinate des zweiten Punktes der Linie
    + * @param y2	Y-Koordinate des zweiten Punktes der Linie
    + */
    +void push_stack_pos_line(int16_t x1, int16_t y1, int16_t x2, int16_t y2) {
    +
    +	if ((x1==0 && y1==0) || (x2==0 && y2==0))
    +	  return;	// ungueltige Werte werden nicht uebernommen
    +
    +	// Push der Einzelpunkte
    +	pos_stack_push(x1,y1);
    +	pos_stack_push(x2,y2);
    +}
    +
    +/*!
    + * Holt eine Line vom Stack, d.h. die beiden Punkte der Linie werden zurueckgegeben
    + * @param *x1	X-Koordinate des ersten Punktes der Linie
    + * @param *y1	Y-Koordinate des ersten Punktes der Linie
    + * @param *x2	X-Koordinate des zweiten Punktes der Linie
    + * @param *y2	Y-Koordinate des zweiten Punktes der Linie
    + * @return True wenn erfolgreich, False falls Stack leer ist
    + */
    +uint8_t pop_stack_pos_line(int16_t *x1, int16_t *y1, int16_t *x2, int16_t *y2) {
    +	int16 x_i; int16 y_i;
    +	if (!pos_stack_pop(&x_i, &y_i))
    +	  return False;
    +	*x1=x_i;*y1=y_i;
    +
    +	if (!pos_stack_pop(&x_i, &y_i))
    +      return False;
    +    *x2=x_i;*y2=y_i;
    +    return True;
    +}
    +
    +
    +/*!
    + * Hilfsroutine, um 2 Punkte in die Merkvariable zu speichern
    + * @param *lastpointx X-Merkvariable
    + * @param *lastpointy Y-Merkvariable
    + * @param mapx zu merkender X-Wert
    + * @param mapy zu merkender Y-Wert
    + */
    +void set_point_to_lastpoint(int16 *lastpointx, int16 *lastpointy, int16 mapx, int16 mapy) {
    +	          	*lastpointx = mapx;
    +	          	*lastpointy = mapy;
    +	          };
    +
    +/*!
    + * Liefert True, wenn der Abstand zwischen den beiden Punkten gueltig ist, d.h. erreicht oder ueberschritten wurde
    + * @param xs World-Koordinate des zu untersuchenden Punktes
    + * @param ys World-Koordinate des zu untersuchenden Punktes
    + * @param xd World-Koordinate des Zielpunktes
    + * @param yd World-Koordinate des Zielpunktes
    + * @return True bei Erreichen des Abstandes zwischen den beiden Punkten sonst False
    + */
    + uint8 dist_guilty(int16 xs, int16 ys, int16 xd, int16 yd){
    +	// falls ein Punktepaar noch 0 hat, so ist dies ungueltig
    +	if ((xs==0 && ys==0) || (xd==0 && yd==0))
    +	  return False;
    +
    +	/* Abstandsermittlung nach dem guten alten Pythagoras ohne Ziehen der Wurzel */
    +	return (get_dist(xs,ys,xd,yd) > DIST_GUILTY_QUAD );
    +}
    +
    +
    +/*!
    + * Liefert True, wenn der Abstand zwischen den beiden Punkten sehr klein ist
    + * @param xs World-Koordinate des zu untersuchenden Punktes
    + * @param ys World-Koordinate des zu untersuchenden Punktes
    + * @param xd World-Koordinate des Zielpunktes
    + * @param yd World-Koordinate des Zielpunktes
    + * @return True bei geringem Abstand zwischen den beiden Punkten sonst False
    + */
    +uint8 pointdist_low(int16 xs, int16 ys, int16 xd, int16 yd){
    +
    +	/* Abstandsermittlung nach dem guten alten Pythagoras ohne Ziehen der Wurzel */
    +	return (get_dist(xs,ys,xd,yd) < DIST_GUILTY_LOW );
    +}
    +
    +
    +
    +
    +/*!
    + * Berechnung des Seitenpunktes der Nebenbahn mit Rueckgabe des Punktes und des Map-Durchschnittswertes
    + * @param sidedist seitlicher Abstand vom Botmittelpunkt
    + * @param dist Punkt im Abstand voraus
    + * @param side Trackleft (-1) oder Trackright (+1) fuer links oder rechts vom bot gesehen
    + * @param *point_x berechnete X-Map-Weltkoordinate
    + * @param *point_y berechnete Y-Map-Weltkoordinate
    + * @return Mapwert an dem ermittelten Punkt in Blickrichtung zum Abstand dist
    + */
    +int8 getpoint_side_dist(uint16 sidedist, int16 dist, int8 side, int16 *point_x, int16 *point_y) {
    +        // Berechnung je nach zu blickender Seite des Bots
    +		(side==TRACKLEFT)? calc_point_in_distance(heading, DISTSENSOR_POS_FW + dist, sidedist, point_x, point_y):
    +		                   calc_point_in_distance(heading, DISTSENSOR_POS_FW + dist, -sidedist,point_x, point_y);
    +
    +        // Rueckgabe des Mapwertes
    +        return map_get_average(*point_x,*point_y, 20);  // Mapwert Durchschnitt ueber 2 cm
    +}
    +
    +
    +
    +/* ==========================================================================================
    + * ===== Obserververhalten und der dafuer notwendigen Routinen; es gibt 2 Observer-Verhalten,
    + * ===== wobei eines die Bahn links und das andere die Bahn rechts vom Bot beobachtet
    + * =========================================================================================*/
    +
    +
    +
    +/*! Verhaltensroutine fuer beide Observer zur Ermittlung des Startpunktes der Nebenspur
    + * Je nach zu checkender Botseite wird der Punkt in der Nachbarspur auf Anfahrbarkeit gecheckt
    + * und hier der Startpunkt der nebenbahn ermittelt
    + * @param checkside  zu checkende Seite (TRACKLEFT TRACKRIGHT)
    + * @param *observe Zeiger auf die Koordinaten der Bahn, hier Startpunkt zurueckgegeben
    + * @param *lastCorrectTime Zeiger auf Timervariable; erst nach Ablauf einer Zeitspanne erfolgt Mapzugriff
    + * @return True falls Startpunkt anfahrbar ist und zurueckgegeben wurde sonst False
    + */
    +uint8 observe_get_startpoint(int8 checkside, trackpoint_t *observe, uint32_t *lastCorrectTime) {
    + int16 mapx;
    + int16 mapy;
    + int8 mapval;
    +
    + 	     // nur alle x ms Mapzugriff des Observers
    +	      if (!timer_ms_passed(lastCorrectTime, CORRECTION_DELAY))
    +		    return False;
    +
    +
    +	     // hier seitenabhaengig auf die Spur nebenan sehen auf Hoehe Mittelpunkt und Mapwert checken
    +		 mapval=getpoint_side_dist(BOT_DIAMETER-SIDEDIST_MINUS,-DISTSENSOR_POS_FW, checkside, &mapx, &mapy);
    +
    +	     // falls Punkt bereits als befahren gekennzeichnet ist oder Hinderniswert hat gehts weiter mit Startpunktsuche
    +	     if (mapval>=MAP_TRACKVAL || mapval<0)
    +	       return False;
    +
    +			 // hier ist also der Trackpunkt frei, dann merken und zur Endpunktsuche im Observer
    +		 // zuweisen der Initwerte in die richtigen Puntvars
    +	     set_point_to_lastpoint(&observe->point1x,&observe->point1y,mapx,mapy);
    +	     set_point_to_lastpoint(&observe->point2x,&observe->point2y,0,0);
    +
    +	return True;
    +}
    +
    +
    +
    +
    +
    +
    +/*!  Kennung, dass die Observer-Verhalten beendet werden sollen; bei True soll Verhalten sofort beendet werden mit
    + *   vorherigem Gueltigkeitscheck des Endpunktes
    + */
    +static uint8 endrequest=False;
    +
    +
    +/*! Statusvariable der Obserververhalten */
    +#define observe_search_startpoint     0
    +#define observe_search_endpoint       1
    +
    +
    +
    +/*!
    + * Verhaltensroutine fuer beide Observer zur Endepunktermittlung; liefert True wenn der Endepunkt gueltig ist und damit ermittelt werden konnte
    + * bei einem Teilhindernis auf der Nebenbahn wird eine gueltige befahrbare Strecke automatisch auf den Stack gelegt zum spaeteren Anfahren
    + * @param checkside  Seite der zu beobachtenden Nebenbahn (TRACKLEFT TRACKRIGHT)
    + * @param *behavstate neuer Zustand des Obserververhalten
    + * @param *observer Zeiger auf Punkte der Nebenbahn, gueltiger Endepunkt wird hier vermerkt
    + * @param *lastpointx letzter gueltiger X-Wert der Nebenbahn, verwendeter Wert bei Erkennung Hindernis
    + * @param *lastpointy letzter gueltiger Y-Wert der Nebenbahn, verwendeter Wert bei Erkennung Hindernis
    + * @param *lastCorrectTime Merkvariable der abgelaufenen Zeit; erst nach Ablauf gewisser Zeit erfolgt Mapzugriff
    + * @return True falls Endpunkt auf der Seite ermittelt werden konnte sonst False
    + */
    +uint8 observe_get_endpoint(int8 checkside, uint8 *behavstate, trackpoint_t *observe,int16 *lastpointx, int16 *lastpointy,
    +                           uint32_t *lastCorrectTime) {
    + int16 mapx;
    + int16 mapy;
    + int8 mapval=0;
    +
    + 	// wenn Zeit noch nicht um dann sofort beenden ohne weitere Checks
    + 	if (!endrequest && !timer_ms_passed(lastCorrectTime, CORRECTION_DELAY))
    +	  return False;
    +
    +	// hier seitenabhaengig auf die jeweilige Spur sehen und Mapwert holen
    +    mapval=getpoint_side_dist(BOT_DIAMETER-SIDEDIST_MINUS, 0, checkside, &mapx, &mapy);
    +
    +	  //Endepunktsuche nicht weiter verfolgen falls noch kein Startpunkt vorliegt
    +	  if ((observe->point1x==0 && observe->point1y==0) ) {
    +	  	*behavstate=(endrequest)?TRACK_END:0; // weiter mit Startpunktsuche oder Ende
    +	  	return False;
    +	  }
    +
    +
    +	    if (mapval<0 )  {  //Punkt auf Nebenbahn hat Hinderniswahrscheinlichkeit
    +
    +	       if (*lastpointx==0 && *lastpointy==0) {
    +	       	 // noch kein gueltiger Zwischenendpunkt ermittelt; Ende falls Endeanforderung kam sonst weiter mit Endepunktsuche
    +              if (endrequest)
    +        	       *behavstate=TRACK_END;
    +
    +             return False;
    +	       }
    +
    +	         // bei Hindernis auf aktuellem Punkt wird der letzte gemerkte Nicht-Hindernispunkt auf den Stack gespeichert, der
    +	         // vorher auf Gueltigkeit gecheckt wird, d.h. muss bestimmten Mindestabstand zum Startpunkt haben und kein Hindernis sein
    +              if (dist_guilty(observe->point1x,observe->point1y,mapx,mapy) && map_get_field(*lastpointx,*lastpointy)>=0 && !endrequest) {
    +                set_point_to_lastpoint(&observe->point2x,&observe->point2y,*lastpointx,*lastpointy);
    +
    +                //zuletzt gueltigen Endpunkt auf Stack sichern
    +                push_stack_pos_line(observe->point1x,observe->point1y,*lastpointx,*lastpointy);
    +
    +
    +                 set_point_to_lastpoint(lastpointx,lastpointy,0,0);
    +                  set_point_to_lastpoint(&observe->point1x,&observe->point1y,0,0);
    +                *behavstate=(endrequest)?TRACK_END:0;  // weiter mit Startpunktsuche
    +                return True;
    +                }
    +
    +
    + 	         if (endrequest) // Verhaltensende nach Anforderung
    +        	       *behavstate=TRACK_END;
    +
    + 	         return False;  //Verhalten erst mal beendet
    +
    +
    +	     }
    +	    else {  //Punkt auf Nebenbahn hat keine Hinderniswahrscheinlichkeit
    +
    +	            // Abstand zum Startpunkt muss gueltig sein
    +	            if (!(dist_guilty(observe->point1x,observe->point1y,mapx,mapy))) {
    +                    if (endrequest)
    +        	         *behavstate=TRACK_END;
    +
    +         	       return False;
    +	             }
    +
    +	          // gueltigen Zwischenpunkt merken
    +	          set_point_to_lastpoint(lastpointx,lastpointy,mapx,mapy);
    +
    +
    +	         // falls sich bei diesem gueltigen Endpunkt herausstellt, dass der vorhin ermittelte Startpunkt nun Hinderniswert besitzt, so wird der Endpunkt zum Startpunkt
    +	         // und weiter mit Endpunktsuche
    +	         if (map_get_field(observe->point1x,observe->point1y)<0) {
    +	             set_point_to_lastpoint(&observe->point1x,&observe->point1y,*lastpointx,*lastpointy);	// Startpunkt ueberschreiben
    +	             if (endrequest)
    +        	         *behavstate=TRACK_END;
    +                 set_point_to_lastpoint(lastpointx,lastpointy,0,0);
    +                 set_point_to_lastpoint(&observe->point2x,&observe->point2y,0,0);
    +                 return True;
    +	          }
    +
    +
    +	          // freien befahrbaren Punkt merken; bei Endeanforderung ist dies der aktuelle Endpunkt
    +	          if (!endrequest) // weiter nur falls kein Ende kommen soll
    +        	       return False;
    +
    +	      // gueltigen Endepunkt merken
    +           set_point_to_lastpoint(&observe->point2x,&observe->point2y,*lastpointx,*lastpointy);
    +	 }
    +
    +
    +         *behavstate=(endrequest)?TRACK_END:0;
    +
    +	     return True; // Streckenpunkt ist hier gueltig
    +
    +}
    +
    +/*! Merkvariable des letzten gueltigen Endpunktes fuer Obserververhalten linke Spur */
    + static int16 lastpointleft_x=0;
    + static int16 lastpointleft_y=0;
    +
    +/*!
    + * Observer links; jeweils ein selbstaendiges Verhalten, welches die Nachbarbahn beobachtet und eine befahrbare Strecke bis zu einem Hindernis
    + * auf den Stack legt fuer spaeteres Anfahren; ebenfalls wird eine Alternativroute auf dem Stack gemerkt
    + * Verhalten wurde so geschrieben, dass es zwar 2 Verhalten sind, der Code jedoch identisch ist und daher in Subroutinen ausgelagert ist
    + * @param data Verhaltensdatensatz
    + */
    +void bot_observe_left_behaviour(Behaviour_t *data) {
    +
    +// je zu beobachtende Seite gibt es einen codeidentischen Observer; hier die Seite festgelegt
    +static int8 CHECK_SIDE=TRACKLEFT;
    +
    +  	switch (observe1_state) {
    +	case observe_search_startpoint:
    +	     // Eingang fuer Startpunktsuche
    +	     if (!observe_get_startpoint(CHECK_SIDE, &observe_trackleft, &lastCorrectionTimeObserveLeft))
    +	     	break;
    +
    +		 observe1_state = observe_search_endpoint;
    +		break;
    +
    +	case observe_search_endpoint:
    +         // Anfangspunkt wurde bestimmt und ist hier auf der Suche nach dem Endpunkt; ein Endpunkt wird als Ende der Strecke
    +         // vom bereits vorhandenen Startpunkt erkannt, wenn der Botbereich neben dem Bot nicht mehr befahren werden kann; es
    +         // wird dann der zuletzt gemerkte befahrbare Punkt als Endpunkt genommen
    +          // nur alle x ms Mapvergleich
    +
    +	      if (!observe_get_endpoint(CHECK_SIDE,&observe1_state,&observe_trackleft,&lastpointleft_x,&lastpointleft_y,&lastCorrectionTimeObserveLeft))
    +	    	break;
    +
    +		break;
    +	default:
    +	    if (observe_trackleft.point2x==0 && observe_trackleft.point2y==0)
    +	      set_point_to_lastpoint(&observe_trackleft.point1x,&observe_trackleft.point1y,0,0);
    +		return_from_behaviour(data);
    +		break;
    +	}
    +}
    +
    +/*!
    + * Rufe das Observer-Verhalten Links auf
    + * @param caller	Der obligatorische Verhaltensdatensatz des Aufrufers
    + */
    +void bot_observe_left(Behaviour_t * caller) {
    +	if (!behaviour_is_activated(bot_observe_left_behaviour)) {
    +	  switch_to_behaviour(caller,bot_observe_left_behaviour,OVERRIDE);
    +	  observe1_state = 0;
    +	  endrequest=False;
    +	  set_point_to_lastpoint(&observe_trackleft.point1x,&observe_trackleft.point1y,0,0);
    +	  set_point_to_lastpoint(&observe_trackleft.point2x,&observe_trackleft.point2y,0,0);
    +	  set_point_to_lastpoint(&lastpointleft_x,&lastpointleft_y,0,0);
    +	  lastCorrectionTimeObserveLeft=9999;
    +	}
    +}
    +
    +/*! Merkvariable des letzten gueltigen Endpunktes fuer Obserververhalten rechte Spur */
    + static int16 lastpointright_x=0;
    + static int16 lastpointright_y=0;
    +
    +/*!
    + * Observer rechts; jeweils ein selbstaendiges Verhalten, welches die Nachbarbahn beobachtet und eine befahrbare Strecke bis zu einem Hindernis
    + * auf den Stack legt fuer spaeteres Anfahren; ebenfalls wird eine Alternativroute auf dem Stack gemerkt
    + * Verhalten wurde so geschrieben, dass es zwar 2 Verhalten sind, der Code jedoch identisch ist und daher in Subroutinen ausgelagert ist
    + * @param data Verhaltensdatensatz
    + */
    +void bot_observe_right_behaviour(Behaviour_t *data) {
    +
    +// je zu beobachtende Seite gibt es einen codeidentischen Observer; hier die Seite festgelegt
    +static int8 CHECK_SIDE=TRACKRIGHT;
    +
    +	switch (observe2_state) {
    +	case observe_search_startpoint:
    +	       // Eingang fuer Startpunktsuche
    +	       if (!observe_get_startpoint(CHECK_SIDE,&observe_trackright, &lastCorrectionTimeObserveRight))
    +	     	break;
    +
    +		   observe2_state = observe_search_endpoint;
    +
    +		break;
    +
    +	case observe_search_endpoint:
    +         // Anfangspunkt wurde bestimmt und ist hier auf der Suche nach dem Endpunkt; ein Endpunkt wird als Ende der Strecke
    +         // vom bereits vorhandenen Startpunkt erkannt, wenn der Botbereich neben dem Bot nicht mehr befahren werden kann; es
    +         // wird dann der zuletzt gemerkte befahrbare Punkt als Endpunkt genommen
    +         // nur alle x ms Mapvergleich
    +
    +	       if (!observe_get_endpoint(CHECK_SIDE,&observe2_state,&observe_trackright,&lastpointright_x,&lastpointright_y,&lastCorrectionTimeObserveRight ))
    +	         break ;
    +
    +		break;
    +	default:
    +	    if (observe_trackright.point2x==0 && observe_trackright.point2y==0)
    +	      set_point_to_lastpoint(&observe_trackright.point1x,&observe_trackright.point1y,0,0);
    +		return_from_behaviour(data);
    +		break;
    +	}
    +}
    +
    +/*!
    + * Rufe das Rechts-Observer-Verhalten auf
    + * @param caller	Der obligatorische Verhaltensdatensatz des Aufrufers
    + */
    +void bot_observe_right(Behaviour_t * caller) {
    +	if (!behaviour_is_activated(bot_observe_right_behaviour)) {
    +	  switch_to_behaviour(caller,bot_observe_right_behaviour,OVERRIDE);
    +	  observe2_state = 0;
    +      set_point_to_lastpoint(&observe_trackright.point1x,&observe_trackright.point1y,0,0);
    +	  set_point_to_lastpoint(&observe_trackright.point2x,&observe_trackright.point2y,0,0);
    +	   set_point_to_lastpoint(&lastpointright_x,&lastpointright_y,0,0);
    +	   lastCorrectionTimeObserveRight=9999;
    +	}
    +
    +}
    +
    +void bot_start_observe_left_right(Behaviour_t * caller) {
    +	endrequest=False;
    +	bot_observe_right(0);
    +	bot_observe_left(0);
    +}
    +
    +/*!
    + * Stopanforderung der beiden Observer-Verhalten links und rechts
    + * @param caller	Der obligatorische Verhaltensdatensatz des Aufrufers
    + */
    +void bot_stop_observe(Behaviour_t * caller) {
    +	// Verhalten soll beendet werden
    +	endrequest=True;
    +
    +
    +}
    +
    +
    +/* ==================================================================================
    + * ===== Ende der Obserververhalten und der dafuer notwendigen Routinen =============
    + * ==================================================================================*/
    +
    +
    +
    +/* ==================================================================================
    + * ===== Hier alles fuer das flaechendeckende Fahrverhalten  ========================
    + * ==================================================================================*/
    +
    +/* Check-Bedingung zum Triggern des cancel-Verhaltens
    + * @return True bei Abgrund sonst False
    + */
    +uint8 check_border_fired(void) {
    +	return border_fired;
    +}
    +
    +/* Check-Routine zum Erkennen eines Hindernisses nach den Abgrund- als auch Abstandssensoren
    + * @return True wenn Hindernis voraus sonst False
    + */
    +uint8 check_haz_in_map(void) {
    +
    +	if (border_fired)
    +	 return True;
    +
    +	   if (sensDistL <= DIST_AWARD_HAZ || sensDistR <=DIST_AWARD_HAZ )
    +	    	return True;
    +
    +	return False;
    +}
    +
    +
    +
    +/*!
    + * Hilfsroutine, welche den Fahrtrack nextline mit den Koordinaten belegt; die Koordinaten
    + * koennen hierbei vertauscht werden oder in point1x/y die zum Bot nahesten Werte gespeichert
    + * @param x1 X-Koordinate des Punktes 1
    + * @param y1 Y-Koordinate des Punktes 1
    + * @param x2 X-Koordinate des Punktes 2
    + * @param y2 Y-Koordinate des Punktes 2
    + * @param change_points Punkte1 und 2 in nextline werden bei True vertauscht sonst belegt mit den Koordinaten
    + */
    +void set_nextline(int16 x1, int16 y1, int16 x2, int16 y2,uint8 change_points) {
    +
    +
    +       if (change_points) {
    +       	int16 xtemp=nextline.point1x;
    +        int16 ytemp=nextline.point1y;
    +        nextline.point1x=nextline.point2x;
    +        nextline.point1y=nextline.point2y;
    +        nextline.point2x=xtemp;
    +        nextline.point2y=ytemp;
    +       }
    +       else {
    +       	    // der Punkt in der Naehe wird richtig nach nextline uebernommen; der naheste nach Punkt1
    +             if (get_dist(x1,y1,x_pos,y_pos)<
    +                 get_dist(x2,y2,x_pos,y_pos)
    +               ) {
    +
    +              set_point_to_lastpoint(&nextline.point1x,&nextline.point1y,x1,y1);
    +   		      set_point_to_lastpoint(&nextline.point2x,&nextline.point2y,x2,y2);
    +
    +            }
    +            else
    +            {
    +       	    // der Punkt in der Naehe wird richtig nach nextline uebernommen; der naheste nach Punkt1
    +              set_point_to_lastpoint(&nextline.point1x,&nextline.point1y,x2,y2);
    +   		      set_point_to_lastpoint(&nextline.point2x,&nextline.point2y,x1,y1);
    +            }
    +       }
    +
    +}
    +
    +
    +
    + /*!
    + * Routine zur Entscheidungsfindung, welche Richtung (links oder rechts) der bot nach Ankunft vor Hindernis nehmen soll; Routine
    + * wird seitenabhaengig aufgerufen und gibt nach Gueltigkeitspruefung des Punktes in der Map die Gueltigkeit zurueck
    + * koennen hierbei vertauscht werden oder in point1x/y die zum Bot nahesten Werte gespeichert
    + * @param observe_track zu pruefende Seitenbahn mit Start- und Endpunkt aus Ermittlung des Observers
    + * @param observe_track_to_push Koordinaten der anderen Seitenbahn, wird auf Stack gelegt als Alternativweg zum spaeteren Anfahren
    + * @param checkside zu pruefende Seite der Bahn (TRACKLEFT TRACKRIGHT)
    + * @param *side_to_go Rueckgabe der Seite, zu der der bot sich bewegen soll; 0 falls nicht gueltig
    + * @return True falls die zu pruefende Seite gueltig ist, bot kann sich zu dieser Seite hinbewegen, sonst false
    + */
    + uint8 check_side_for_decision(trackpoint_t observe_track,trackpoint_t observe_track_to_push,int8 checkside,int8_t *side_to_go) {
    + 	int16 mapx=0;
    +     int16 mapy=0;
    +     int8 mapval=0;
    +
    + 	*side_to_go = 0;
    +
    + 		// Strecke muss vom Observer als gueltig gesetzt worden sein, nur dann gehts weiter
    + 		if (observe_track.point1x==0 && observe_track.point1y==0)
    + 		 return False;
    +
    + 	    // Punkt laut Map holen
    +		mapval=getpoint_side_dist(BOT_DIAMETER-SIDEDIST_MINUS, 0, checkside, &mapx, &mapy);
    +
    +	    //Mapwert darf keine Hinderniswahrscheinlichkeit haben und noch nicht befahren worden sein
    +	    if (!(mapval<0 || mapval>=MAP_TRACKVAL)) {
    +
    +          //Observer-Track init.
    +          set_nextline(observe_track.point1x,observe_track.point1y,observe_track.point2x,observe_track.point2y,0);
    +
    +          //gueltige Seite zurueckgeben
    +          *side_to_go=checkside;
    +
    +          // Alternative auf Stack speichern; d.h. die vom anderen Observer ermittelte gueltige Strecke auf Stack merken
    +          push_stack_pos_line(observe_track_to_push.point1x,observe_track_to_push.point1y,observe_track_to_push.point2x,observe_track_to_push.point2y);
    +
    +          return True;  // Seite ist gueltig und raus
    +	     }
    + 	return False;  // Seite ungueltig
    + }
    +
    +
    + /*!
    + * Entscheidungsfindung, welche Richtung (links oder rechts) der bot nach Ankunft vor Hindernis nehmen soll; Routine
    + * checkt die Gueltigkeit zuerst der rechten Seite (damit bevorzugter Weg) und erst dann die linke Seite
    + * @param observe_trackleft  linke Seitenbahn mit Start- und Endpunkt aus Ermittlung des Observers
    + * @param observe_trackright rechte Seitenbahn mit Start- und Endpunkt aus Ermittlung des Observers
    + * @param *side_to_go Rueckgabe der Seite, zu der der bot sich bewegen soll; 0 falls nicht gueltig
    + * @return True falls eine gueltige Seite links oder rechts ermittelt werden konnte
    + */
    + uint8 decision_for_one_direction(trackpoint_t observe_trackleft,trackpoint_t observe_trackright,int8_t *side_to_go) {
    +
    +     *side_to_go = 0; // erst mal init. mit kein Weg gueltig
    +
    + 			// zuerst nextline auf 0, ist keiner nah so ist nextline 0
    +			set_point_to_lastpoint(&nextline.point1x,&nextline.point1y,0,0);
    +			set_point_to_lastpoint(&nextline.point2x,&nextline.point2y,0,0);
    +
    +			 // Rechts ist ja die zuerst bevorzugte Richtung, also nach rechts gucken; dazu muss eine
    +			 if (check_side_for_decision(observe_trackright,observe_trackleft,TRACKRIGHT,side_to_go))
    +			   return True;
    +
    +			 // bei rechts ungueltig wird nun die linke Seite ueberprueft
    +			 if (check_side_for_decision(observe_trackleft,observe_trackright,TRACKLEFT,side_to_go))
    +			   return True;
    +
    +			  return False;
    +
    + }
    +
    +
    +/* ==================================================================================
    + * ===== Nun das Area-Fahrverhalten selbst                             ==============
    + * ==================================================================================*/
    +
    +/*! Zustaende des Verhaltens */
    +#define check_trackside  0
    +#define go_on_track      1
    +#define after_forward    2
    +#define onwall_to_track  3
    +#define  delay_after_forward 4
    +#define turn_to_destination 5
    +#define  go_on_wall	 6
    +#define get_line_from_stack 7
    +#define turn_to_nearest 8
    +#define go_back 9
    +#define goto_first_dest 10
    +
    +
    +/*!
    + * Das Fahrverhalten selbst; Fahren bis zu einem Hindernis, drehen zu einer Seite und merken des anderen Weges auf den Stack; waehrend der
    + * Fahrt werden die Nebenspuren beobachtet und bei Hindernissen in der Nebenspur automatisch Teilstrecken auf den Stack gelegt
    + * @param *data der Verhaltensdatensatz
    + */
    +void bot_area_behaviour(Behaviour_t *data) {
    +
    +
    +  static int8 direct_choice=0;  // Entscheidungsrichtung
    +
    +  static uint8 go_long_distance=0;  //Kennung ob nach Stackholen weit gefahren wurde
    +
    +  static uint32_t lastCheckTime=0;
    +
    +    int16 x=0;
    +    int16 y=0;
    +
    +	switch (track_state) {
    +	  case check_trackside:  //Vorwaeertsfahren mit Start der Observer
    +
    +	     // anzufahrende naechste Strecke erst mal initialisieren
    +         set_point_to_lastpoint(&nextline.point1x,&nextline.point1y,0,0);
    +         set_point_to_lastpoint(&nextline.point2x,&nextline.point2y,0,0);
    +
    +	     //Naechste anzufahrende Bahn vom Stack holen wenn die Bahnen nebenan schon befahren wurden oder Hindernis voraus
    +         if (getpoint_side_dist(BOT_DIAMETER-SIDEDIST_MINUS, 0, TRACKLEFT, &x, &y) >= MAP_TRACKVAL  &&
    +             getpoint_side_dist(BOT_DIAMETER-SIDEDIST_MINUS, 0, TRACKRIGHT, &x, &y) >= MAP_TRACKVAL
    +         ) {
    +	        track_state=get_line_from_stack;
    +	        break;
    +         }
    +
    +         if (check_haz_in_map()) {  //Hindernis voraus erkannt
    +          	 track_state=get_line_from_stack;
    +	        break;
    +          }
    +
    +         //naechster Verhaltenszustand
    +	     track_state = delay_after_forward;
    +
    +	     //Observer starten zum Beobachten der Nebenspuren
    +         bot_start_observe_left_right(0);
    +
    +         //Verhalten zum Vorwaertsfahren bis Hindernis voraus
    +         bot_goto_obstacle(data,DIST_AWARD_HAZ,0);
    +
    +         bot_cancel_behaviour(data, bot_goto_pos_behaviour, check_haz_in_map); //damit auch Abgrund erkannt wird beim vorfahren
    +
    +	     break;
    +
    +    case delay_after_forward:
    +        // kommt hierher, wenn das Fahrverhalten (cancel-Verhalten) Hindernis oder Abgrund voraus erkannt hat; hier wird etwas gewartet
    +
    +        //bei Abgrund etwas rueckwaerts fahren
    +	    if (border_fired)
    +	  	  bot_drive_distance(data,0,-BOT_SPEED_NORMAL,OPTIMAL_DISTANCE/10);  // rueckwaerts bei Abgrund
    +
    +         lastCheckTime = TIMER_GET_TICKCOUNT_16; // Var auf Systemzeit setzen, damit etwas zeit vergehen kann im naechsten Zustand
    +         track_state=after_forward; //naechster Verhaltenszustand
    +         BLOCK_BEHAVIOUR(data, 500);  // etwas warten
    +
    +         break;
    +
    +
    +    case after_forward:
    +        // kommt hierher, wenn das Verhalten Vorwaertsfahren an Wand angekommen ist und etwas Zeit abgewartet wurde; Bot blickt noch geradeaus zum Hindernis
    +        // Entscheidung treffen, wohin sich bot nun bewegen soll
    +
    +        //Observer spaetestens hier anhalten, falls noch nicht geschehen, und gueltige Endpunkte in die Streckenvars vermerken
    +        if (!endrequest) {
    +            bot_stop_observe(0);
    +            break;
    +        }
    +          //Abgrundvar init.
    +          border_fired=False; //Abgrundvar init.
    +
    +          //etwas hier verbleiben, damit Observer sicher gestoppt sind
    +          if (!timer_ms_passed(&lastCheckTime, CORRECTION_DELAY+300))
    +		    break;
    +
    +          //naechster Verhaltenszustand
    +          track_state=turn_to_nearest;
    +
    +
    +         // Entscheidungslogik welche Richtung genommen wird; Alternative wird auf Stack gespeichert und der anzufahrende Weg in nextline
    +        if (decision_for_one_direction(observe_trackleft,observe_trackright,&direct_choice))
    +        	break;
    +
    +         // hier war keine Richtungsentscheidung moeglich, daher naechsten Weg from Stack holen
    +         track_state=get_line_from_stack;
    +
    +        break;
    +
    +
    +    case turn_to_nearest:
    +          // in nextline befindet sich nun der naechste Fahrweg mit Start- und Endpunkt; hier wird der bot nun zum naechsten Zielpunkt ausgerichtet; das Ausrichten
    +          // haette auch Entfallen koennen weil ja sowieso direkt mit goto_pos gefahren wird, aber so wird erst in die Richtung des Fahrens gesehen und es kann schon
    +          // die Map aktualisiert und Hindernis gecheckt werden vor Start des Fahrverhaltens selbst
    +
    +          //naechster Verhaltenszustand
    +          track_state=onwall_to_track;
    +
    +          //Drehen des Bots zum nahesten Punkt bei Gueltigkeit desselben
    +          if (nextline.point1x!=0 || nextline.point1y!=0)
    +            bot_turn(data, calc_angle_diff(nextline.point1x-x_pos, nextline.point1y-y_pos));
    +
    +        break;
    +
    +
    +   case onwall_to_track:
    +        //bot ist hier zum naechsten Zielpunkt ausgerichtet und faehrt nun dahin
    +        // 2stufig zu einem weiten Zielpunkt fahren, damit Map aktualisiert werden kann ; zuerst bis 30cm ranfahren und dann je nach Mapwert weiter
    +        // das Fahrverhalten greift hier nur fuer weite Distanzen (nach Stackholen)
    +
    +        //naechster Verhaltenszustand
    +        track_state = goto_first_dest;
    +
    +        //Mapwert des Zielpunktes ermitteln; hat dieser Hinderniswert, dann zuerst den anderen Punkt anfahren um sich diesem hier von der
    +        //anderen Seite zu naehern
    +        if (map_get_field(nextline.point1x,nextline.point1y)<0) {
    +            track_state = turn_to_destination;  //Zustand zum Anfahren des anderen Punktes
    +         	break;
    +
    +        }
    +
    +        //Abstand des bots zum ersten Zielpunkt bestimmen (hier mal mit Ziehen der Wurzel-spaeter vielleicht mal mit Quadratwert)
    +         int16_t dist_to_point = sqrt(get_dist(nextline.point1x,nextline.point1y,x_pos,y_pos));
    +
    +        go_long_distance=False; //Kennung fuer grossen Abstand zum Zielpunkt init.
    +
    +
    +        //fuer grossen Abstand zum Zielpunkt (nach Stackholen) wird hier gefahren bis Hindernis etwas voraus gesehen wird; dadurch kann die Map
    +        // aktualisiert werden und dann vor dem weiteren Ranfahren Entscheidungen getroffen werden
    +        if (dist_to_point>300) {
    +
    +            //es wird eine lange Distanz zurueckgelegt
    +            go_long_distance=True;
    +
    +        	 //track_state = TRACK_END;
    +        	bot_goto_dist(data,dist_to_point-300,1);  // bis 300mm vor Ziel
    +
    +         	//damit bot nicht auf seinem weiten Weg zum Zielpunkt in den Abgrund faellt
    +         	bot_cancel_behaviour(data, bot_goto_pos_behaviour, check_haz_in_map);
    +        }
    +        break;
    +
    +
    +
    + case goto_first_dest:
    +        //bot ist hier nicht mehr weit von dem Zielpunkt entfernt und kann nun naeher ranfahren; Mapwerte sollten hier voraus vorliegen
    +
    +        //naechster Verhaltenszustand
    +        track_state = turn_to_destination;
    +
    +        //falls weit gefahren wurde und Hindernis zum naechsten Zielpunkt erkannt wird aber der andere Streckenpunkt freie Fahrt bietet, dann einfach
    +        //Punkte tauschen und den anderen Punkt zuerst anfahren um sich diesem von der anderen Seite zu naehern
    +        if ( ((go_long_distance && check_haz_in_map()) || map_get_field(nextline.point1x,nextline.point1y)<0)&&map_way_free(x_pos,y_pos, nextline.point2x,nextline.point2y))
    +        	set_nextline(0,0,0,0,True);  //Werte egal da nextline nur getauscht
    +
    +        //Ersten Streckenpunkt nun anfahren
    +        bot_goto_pos(data,nextline.point1x,nextline.point1y,999);
    +
    +         lastCorrectionTime=0; //Ablaufzeit init.
    +
    +         //bei geringem Abstand nur Abgrund ueberwachen sonst ebenfalls auch Hindernisse mit Sensoren
    +         if (pointdist_low(nextline.point1x,nextline.point1y,x_pos,y_pos))	{
    +            bot_cancel_behaviour(data, bot_goto_pos_behaviour, check_border_fired); // kurzer Abstand nur Abgrundcheck
    +         }
    +         else
    +         	bot_cancel_behaviour(data, bot_goto_pos_behaviour, check_haz_in_map); // Abgrund und Abstandsensorcheck
    +
    +        break;
    +
    +
    +    case turn_to_destination:
    +        //bot ist hier beim ersten Zielpunkt angekommen oder Cancelverhalten hat das Fahren dorthin unterbrochen wegen Hindernis oder Abgrund
    +
    +        //nach Abgrund etwas rueckwaerts und weiter mit Stackholen
    +        if (border_fired) {
    +           bot_drive_distance(data,0,-BOT_SPEED_NORMAL,OPTIMAL_DISTANCE/10);
    +	  	   border_fired=False;
    +	  	   track_state=get_line_from_stack;
    +	  	   break;
    +	    }
    +
    +          //Ausrichten auf den Endpunkt der Fahrstrecke; ebenfalls wieder zum Aktualisieren der Map vor dem Anfahren selbst
    +          bot_turn(data, calc_angle_diff(nextline.point2x-x_pos, nextline.point2y-y_pos));
    +
    +          //naechster Verhaltenszustand, welches wiederum der Starteintritt des Verhaltens selbst ist und geht hiermit von vorn los
    +          track_state=check_trackside;
    +         break;
    +
    +
    +   case get_line_from_stack:
    +         //kommt hierher, wenn Bot weder nach linsk noch rechts fahren kann und deswegen wird hier eine gemerkte Fahrstrecke
    +         //vom Stack geholt und angefahren
    +
    +         // auf jeden Fall hier Stop der Obserververhalten
    +         bot_stop_observe(0);
    +
    +        // Weg vom Stack holen und Ende falls leer
    +        if (!pop_stack_pos_line(&nextline.point1x,&nextline.point1y,&nextline.point2x,&nextline.point2y)){
    +        	 track_state = TRACK_END;
    +        	 break;
    +        }
    +
    +         // der naheste Punkt zum Bot laut Luftdistance wird nextline.x1y1
    +	     set_nextline(nextline.point1x,nextline.point1y,nextline.point2x,nextline.point2y,0);
    +
    +        //Mapwerte des Start- und Endepunktes holen
    +        int8 mapval1=map_get_field(nextline.point1x,nextline.point1y);
    +        int8 mapval2=map_get_field(nextline.point2x,nextline.point2y);
    +
    +
    +        //pruefen, ob Wege zu den Punkten frei sind und Freikennungen speichern
    +        uint8 free1= map_way_free(x_pos,y_pos, nextline.point1x,nextline.point1y) ;
    +        uint8 free2= map_way_free(x_pos,y_pos, nextline.point2x,nextline.point2y);
    +
    +        //falls nur der weiter liegende Punkt freie Fahrt voraus bietet, dann Reihenfolge vertauschen
    +        //sind beide eigentlich nicht anfahrbar laut Map aber der weiter liegende hat hoehere Freiwahrscheinlichkeit,
    +        //dann ebenfalls tauschen
    +         if ((free2 && !free1)||(!free1 && !free2 && (mapval2>mapval1)))
    +        	set_nextline(0,0,0,0,True);  //Werte egal da nextline nur Werte vertauscht
    +
    +         //naechster Verhaltenszustand mit Ausrichten auf den naeheren Punkt laut nextline
    +         track_state=turn_to_nearest;
    +        break;
    +
    +	default:
    +        // am Ende des Verhaltens Observer stoppen
    +        bot_stop_observe(0);
    +        pos_stack_clear();  // Stack bereinigen
    +		return_from_behaviour(data);
    +		break;
    +	}
    +}
    +
    +/*!
    + * Startet das Verhalten bot_area_behaviour
    + * @param caller	Der obligatorische Verhaltensdatensatz des Aufrufers
    + */
    +void bot_area(Behaviour_t * caller) {
    +
    +	/* ein paar Initialisierungen sind notwendig */
    +	lastCorrectionTime = 0;
    +	switch_to_behaviour(caller,bot_area_behaviour,OVERRIDE);
    +	track_state = 0;
    +	border_fired=False;
    +	pos_stack_clear();
    +
    +	/* Kollisions-Verhalten ausschalten  */
    +	#ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
    +		deactivateBehaviour(bot_avoid_col_behaviour);
    +	#endif
    +
    +	/* Einschalten sicherheitshalber des on_the_fly Verhaltens */
    +	#ifdef BEHAVIOUR_SCAN_AVAILABLE
    +		activateBehaviour(bot_scan_onthefly_behaviour);
    +	#endif
    +
    +}
    +
    +
    +
    +#endif	// BEHAVIOUR_AREA_AVAILABLE
    Index: C:/botneu/ct-Bot/bot-logic/bot-logik.c
    ===================================================================
    --- C:/botneu/ct-Bot/bot-logic/bot-logik.c	(revision 1462)
    +++ C:/botneu/ct-Bot/bot-logic/bot-logik.c	(working copy)
    @@ -1,34 +1,34 @@
     /*
      * c't-Bot
    - *
    + *
      * 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; either version 2 of the License, or (at your
    - * option) any later version.
    - * This program is distributed in the hope that it will be
    + * option) any later version.
    + * This program is distributed in the hope that it will be
      * useful, but WITHOUT ANY WARRANTY; without even the implied
    - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
    + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
      * PURPOSE. See the GNU General Public License for more details.
    - * You should have received a copy of the GNU General Public
    - * License along with this program; if not, write to the Free
    + * You should have received a copy of the GNU General Public
    + * License along with this program; if not, write to the Free
      * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
      * MA 02111-1307, USA.
    - *
    + *
      */

    -/*!
    +/*!
      * @file 	bot-logik.c
      * @brief 	High-Level Routinen fuer die Steuerung des c't-Bots.
    - * Diese Datei sollte der Einstiegspunkt fuer eigene Experimente sein,
    + * Diese Datei sollte der Einstiegspunkt fuer eigene Experimente sein,
      * den Roboter zu steuern.
    - *
    - * bot_behave() arbeitet eine Liste von Verhalten ab.
    + *
    + * bot_behave() arbeitet eine Liste von Verhalten ab.
      * Jedes Verhalten kann entweder absolute Werte setzen, dann kommen niedrigerpriorisierte nicht mehr dran.
      * Alternativ dazu kann es Modifikatoren aufstellen, die bei niedriger priorisierten angewendet werden.
      * bot_behave_init() baut diese Liste auf.
      * Jede Verhaltensfunktion bekommt einen Verhaltensdatensatz uebergeben, in den Sie ihre Daten eintraegt
    - *
    + *
      * @author 	Benjamin Benz (bbe@xxxxxxxx)
      * @author 	Christoph Grimmer (c.grimmer@xxxxxxxxxx)
      * @date 	01.12.05
    @@ -77,7 +77,7 @@
     /*! hier liegen die Zeiger auf die auszufuehrenden Abgrund Notfall-Funktionen */
     static void (* emerg_functions[MAX_PROCS])(void) = {NULL};

    -/*!
    +/*!
      * Routine zum Registrieren einer Notfallfunktion, die beim Ausloesen eines Abgrundsensors
      * aufgerufen wird; hierdurch kann ein Verhalten vom Abgrund benachrichtigt werden und
      * entsprechend dem Verhalten reagieren
    @@ -91,9 +91,9 @@
     	return proc_nr;
     }

    -/*!
    - * Beim Ausloesen eines Abgrundes wird diese Routine am Ende des Notfall-Abgrundverhaltens angesprungen
    - * und ruft alle registrierten Prozeduren der Reihe nach auf
    +/*!
    + * Beim Ausloesen eines Abgrundes wird diese Routine am Ende des Notfall-Abgrundverhaltens angesprungen
    + * und ruft alle registrierten Prozeduren der Reihe nach auf
      */
     void start_registered_emergency_procs(void) {
     	uint8_t i=0;
    @@ -102,8 +102,8 @@
     	}
     }

    -/*!
    - * Das einfachste Grundverhalten
    +/*!
    + * Das einfachste Grundverhalten
      * @param *data der Verhaltensdatensatz
      */
     void bot_base_behaviour(Behaviour_t *data){
    @@ -137,13 +137,13 @@
     	// Hoechste Prioritate haben die Notfall Verhalten

     	// Verhalten zum Schutz des Bots, hohe Prioritaet, Aktiv
    -	#ifdef BEHAVIOUR_AVOID_BORDER_AVAILABLE
    +	#ifdef BEHAVIOUR_AVOID_BORDER_AVAILABLE
     		insert_behaviour_to_list(&behaviour, new_behaviour(250, bot_avoid_border_behaviour,ACTIVE));
     	#endif
    -	#ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
    +	#ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
     		insert_behaviour_to_list(&behaviour, new_behaviour(249, bot_avoid_col_behaviour,ACTIVE));
     	#endif
    -    #ifdef BEHAVIOUR_HANG_ON_AVAILABLE
    +    #ifdef BEHAVIOUR_HANG_ON_AVAILABLE
     		insert_behaviour_to_list(&behaviour, new_behaviour(245, bot_hang_on_behaviour,ACTIVE));
     		// Registrierung des Handlers zur Behandlung des Haengenbleibens zum Rueckwaertsfahren
      	    register_emergency_proc(&hang_on_handler);
    @@ -162,14 +162,14 @@
     	#ifdef BEHAVIOUR_DRIVE_STACK_AVAILABLE
     		insert_behaviour_to_list(&behaviour, new_behaviour(190, bot_put_stack_waypositions_behaviour, INACTIVE));
     	#endif
    -
    +
     	#ifdef BEHAVIOUR_CANCEL_BEHAVIOUR_AVAILABLE
     		// Verhalten, das andere Verhalten abbricht, sobald eine Bedingung erfuellt ist
     		insert_behaviour_to_list(&behaviour, new_behaviour(154, bot_cancel_behaviour_behaviour,INACTIVE));
     	#endif

     	// Alle Hilfsroutinen sind relativ wichtig, da sie auch von den Notverhalten her genutzt werden
    -	// Hilfsverhalten, die Befehle von Boten-Funktionen ausfuehren, erst inaktiv, werden von Boten aktiviert
    +	// Hilfsverhalten, die Befehle von Boten-Funktionen ausfuehren, erst inaktiv, werden von Boten aktiviert
     	#ifdef BEHAVIOUR_TURN_AVAILABLE
     		insert_behaviour_to_list(&behaviour, new_behaviour(150, bot_turn_behaviour,INACTIVE));
     	#endif
    @@ -193,12 +193,22 @@
     		insert_behaviour_to_list(&behaviour, new_behaviour(140, bot_measure_distance_behaviour, INACTIVE));
     		insert_behaviour_to_list(&behaviour, new_behaviour(139, bot_check_distance_behaviour, INACTIVE));
     	#endif
    -
    +
     	#ifdef BEHAVIOUR_SOLVE_MAZE_AVAILABLE
     		/* solve_maze belegt Prios 100, 90, 89 */
     		bot_solve_maze_init(100,90,INACTIVE);
     	#endif

    +	#ifdef BEHAVIOUR_AREA_AVAILABLE
    +		      // Registrierung des Handlers zur Behandlung des Abgrundes im Area-Verhalten
    +		 	  register_emergency_proc(&border_area_handler);
    +		 	  // Observer bekomemn hohe Prio um noch vor goto_pos zum Zuge zu kommen
    +		      insert_behaviour_to_list(&behaviour, new_behaviour(170, bot_observe_left_behaviour, INACTIVE));
    +		      insert_behaviour_to_list(&behaviour, new_behaviour(170, bot_observe_right_behaviour, INACTIVE));
    +
    +		      insert_behaviour_to_list(&behaviour, new_behaviour(72, bot_area_behaviour, INACTIVE));
    +    #endif
    +
     	#ifdef BEHAVIOUR_FOLLOW_LINE_AVAILABLE
     		// Verhalten um einer Linie zu folgen
     		insert_behaviour_to_list(&behaviour, new_behaviour(70, bot_follow_line_behaviour, INACTIVE));
    @@ -208,23 +218,23 @@
     		/* olympic belegt Prios 60, 55, 54 */
     		bot_olympic_init(60,55,INACTIVE);
     	#endif
    -
    +
     	#ifdef BEHAVIOUR_DRIVE_SQUARE_AVAILABLE
     		// Demo-Verhalten, etwas komplexer, inaktiv
     		insert_behaviour_to_list(&behaviour, new_behaviour(51, bot_drive_square_behaviour,INACTIVE));
     	#endif
    -
    +
         #ifdef BEHAVIOUR_FOLLOW_WALL_AVAILABLE
      	    // Explorer-Verhalten um einer Wand zu folgen
      	    insert_behaviour_to_list(&behaviour, new_behaviour(48, bot_follow_wall_behaviour, INACTIVE));
      	    // Registrierung zur Behandlung des Notfallverhaltens zum R ueckwaertsfahren
      	    register_emergency_proc(&border_follow_wall_handler);
     	#endif
    -
    +
     	#ifdef BEHAVIOUR_CLASSIFY_OBJECTS_AVAILABLE
      	    insert_behaviour_to_list(&behaviour, new_behaviour(45, bot_classify_objects_behaviour, INACTIVE));
     	#endif
    -
    +
     	#ifdef BEHAVIOUR_CATCH_PILLAR_AVAILABLE
      	    insert_behaviour_to_list(&behaviour, new_behaviour(44, bot_catch_pillar_behaviour,INACTIVE));
     		insert_behaviour_to_list(&behaviour, new_behaviour(43, bot_unload_pillar_behaviour,INACTIVE));
    @@ -237,23 +247,23 @@
     	#ifdef BEHAVIOUR_FOLLOW_OBJECT_AVAILABLE
     		insert_behaviour_to_list(&behaviour, new_behaviour(40, bot_follow_object_behaviour, INACTIVE));
     	#endif
    -
    +
     	#ifdef BEHAVIOUR_DRIVE_STACK_AVAILABLE
     		insert_behaviour_to_list(&behaviour, new_behaviour(33, bot_drive_stack_behaviour, INACTIVE));
    -	#endif
    -
    +	#endif
    +
     	#ifdef BEHAVIOUR_CALIBRATE_PID_AVAILABLE
    -		insert_behaviour_to_list(&behaviour, new_behaviour(30, bot_calibrate_pid_behaviour, INACTIVE));
    +		insert_behaviour_to_list(&behaviour, new_behaviour(30, bot_calibrate_pid_behaviour, INACTIVE));
     	#endif

     	#ifdef BEHAVIOUR_CALIBRATE_SHARPS_AVAILABLE
    -		insert_behaviour_to_list(&behaviour, new_behaviour(29, bot_calibrate_sharps_behaviour, INACTIVE));
    +		insert_behaviour_to_list(&behaviour, new_behaviour(29, bot_calibrate_sharps_behaviour, INACTIVE));
     	#endif

     	#ifdef BEHAVIOUR_TURN_TEST_AVAILABLE
     		insert_behaviour_to_list(&behaviour, new_behaviour(28, bot_turn_test_behaviour, INACTIVE));
     	#endif
    -
    +
     	// Grundverhalten, setzt aeltere FB-Befehle um, aktiv
     	insert_behaviour_to_list(&behaviour, new_behaviour(2, bot_base_behaviour, ACTIVE));

    @@ -280,8 +290,8 @@
      */
     void deactivateBehaviour(BehaviourFunc function) {
     	Behaviour_t *job;	// Zeiger auf ein Verhalten
    -
    -	// Einmal durch die Liste gehen, bis wir den gewuenschten Eintrag haben
    +
    +	// Einmal durch die Liste gehen, bis wir den gewuenschten Eintrag haben
     	for (job = behaviour; job; job = job->next) {
     		if (job->work == function) {
     			LOG_DEBUG("Verhalten %u wird deaktiviert", job->priority);
    @@ -300,7 +310,7 @@
     uint8_t behaviour_is_activated(BehaviourFunc function) {
     	Behaviour_t *job;	// Zeiger auf ein Verhalten

    -	// Einmal durch die Liste gehen, bis wir den gewuenschten Eintrag haben
    +	// Einmal durch die Liste gehen, bis wir den gewuenschten Eintrag haben
     	for (job = behaviour; job; job = job->next) {
     		if (job->work == function)
     			return job->active;
    @@ -317,9 +327,9 @@
      */
     static uint8_t isInCallHierarchy(Behaviour_t *job, BehaviourFunc function) {
     	uint8_t level = 0;
    -
    +
     	if (job == NULL) return 0;	// Liste ist leer
    -
    +
     	for (; job->caller; job=job->caller) {
     		level++;
     		if (job->caller->work == function) {
    @@ -327,23 +337,23 @@
     			return level;	// Direkter Aufrufer in Tiefe level gefunden
     		}
     	}
    -	return 0;	// function kommt in Caller-Liste von job nicht vor
    +	return 0;	// function kommt in Caller-Liste von job nicht vor
     }	// O(n), n:=|Caller-Liste|

     /*!
    - * Deaktiviert alle von diesem Verhalten aufgerufenen Verhalten.
    + * Deaktiviert alle von diesem Verhalten aufgerufenen Verhalten.
      * Das Verhalten selbst bleibt aktiv und bekommt ein SUBCANCEL in seine Datanestruktur eingetragen.
      * @param function	Die Funktion, die das Verhalten realisiert.
      */
     void deactivateCalledBehaviours(BehaviourFunc function) {
     	Behaviour_t *job;	// Zeiger auf ein Verhalten
    -
    +
     	LOG_DEBUG("Beginne mit dem Durchsuchen der Liste");
     	// Einmal durch die Liste gehen, und alle aktiven Funktionen pruefen, ob sie von dem uebergebenen Verhalten aktiviert wurden
     	uint8_t i=0;
     	Behaviour_t* beh_of_function = NULL;
     	for (job=behaviour; job; job=job->next) {	// n mal
    -		if (job->active == ACTIVE) {
    +		if (job->active == ACTIVE) {
     			i++;
     			uint8_t level = isInCallHierarchy(job, function);	// O(n)
     			LOG_DEBUG("Verhalten mit Prio = %u ist ACTIVE, Durchlauf %u", job->priority, i);
    @@ -355,8 +365,8 @@
     				Behaviour_t* tmp = job;
     				job = job->caller;	// zur naechsten Ebene
     				tmp->caller = NULL;	// Caller loeschen, damit Verhalten auch ohne OVERRIDE neu gestartet werden koennen
    -			}
    -		}
    +			}
    +		}
     		if (job->work == function) {
     			/* Verhalten von function fuer spaeter merken, wenn wir hier eh schon die ganze Liste absuchen */
     			beh_of_function = job;
    @@ -370,30 +380,30 @@
     	}
     }	// O(n^2)

    -/*!
    - * Ruft ein anderes Verhalten auf und merkt sich den Ruecksprung
    +/*!
    + * Ruft ein anderes Verhalten auf und merkt sich den Ruecksprung
      * return_from_behaviour() kehrt dann spaeter wieder zum aufrufenden Verhalten zurueck
      * @param from aufrufendes Verhalten
      * @param to aufgerufenes Verhalten
      * @param override Hier sind zwei Werte Moeglich:
    - * 		1. OVERRIDE : Das Zielverhalten to wird aktiviert, auch wenn es noch aktiv ist.
    - * 					  Das Verhalten, das es zuletzt aufgerufen hat wird dadurch automatisch
    + * 		1. OVERRIDE : Das Zielverhalten to wird aktiviert, auch wenn es noch aktiv ist.
    + * 					  Das Verhalten, das es zuletzt aufgerufen hat wird dadurch automatisch
      * 					  wieder aktiv und muss selbst sein eigenes Feld subResult auswerten, um zu pruefen, ob das
    - * 					  gewuenschte Ziel erreicht wurde, oder vorher ein Abbruch stattgefunden hat.
    + * 					  gewuenschte Ziel erreicht wurde, oder vorher ein Abbruch stattgefunden hat.
      * 		2. NOOVERRIDE : Das Zielverhalten wird nur aktiviert, wenn es gerade nichts zu tun hat.
      * 						In diesem Fall kann der Aufrufer aus seinem eigenen subResult auslesen,
      * 						ob seibem Wunsch Folge geleistet wurde.
    - */
    + */
     void switch_to_behaviour(Behaviour_t * from, void (*to)(Behaviour_t *), uint8 override ){
     	Behaviour_t *job;						// Zeiger auf ein Verhalten
    -
    -	// Einmal durch die Liste gehen, bis wir den gewuenschten Eintrag haben
    +
    +	// Einmal durch die Liste gehen, bis wir den gewuenschten Eintrag haben
     	for (job = behaviour; job; job = job->next) {
     		if (job->work == to) {
     			break;		// Abbruch der Schleife, job zeigt nun auf die Datenstruktur des Zielverhaltens
     		}
    -	}
    -
    +	}
    +
     	if (!job) {
     		/* Zielverhalten existiert gar nicht */
     		if (from) from->subResult=SUBFAIL;
    @@ -415,29 +425,29 @@
     		from->active=INACTIVE;
     		from->subResult=SUBRUNNING;
     	}
    -
    +
     	// neues Verhalten aktivieren
     	job->active=ACTIVE;
     	// Aufrufer sichern
     	job->caller =  from;
    -
    +
     	#ifdef DEBUG_BOT_LOGIC
     		if (from) {
     			LOG_DEBUG("Verhaltenscall: %d wurde von %d aufgerufen",job->priority,from->priority);
    -		} else {
    +		} else {
     			LOG_DEBUG("Verhaltenscall: %d wurde direkt aufgerufen",job->priority);
     		}
     	#endif
     }

    -/*!
    +/*!
      * @brief		Kehrt zum aufrufenden Verhalten zurueck und setzt den Status auf Erfolg oder Misserfolg
      * @param *data	laufendes Verhalten
      * @param state	Abschlussstatus des Verhaltens (SUBSUCCESS oder SUBFAIL)
    - */
    + */
     void exit_behaviour(Behaviour_t * data, uint8_t state) {
     	data->active=INACTIVE;	 				// Unterverhalten deaktivieren
    -	if (data->caller) {
    +	if (data->caller) {
     		data->caller->active = ACTIVE; 		// aufrufendes Verhalten aktivieren
     		data->caller->subResult = state;	// Status beim Aufrufer speichern
     	}
    @@ -449,25 +459,25 @@
      */
     void deactivateAllBehaviours(void){
     	Behaviour_t *job;						// Zeiger auf ein Verhalten
    -	// Einmal durch die Liste gehen und (fast) alle deaktivieren, Grundverhalten nicht
    +	// Einmal durch die Liste gehen und (fast) alle deaktivieren, Grundverhalten nicht
     	for (job = behaviour; job; job = job->next) {
     		if ((job->priority >= PRIO_VISIBLE_MIN) && (job->priority <= PRIO_VISIBLE_MAX)) {
    -            // Verhalten deaktivieren
    -			job->active = INACTIVE;
    +            // Verhalten deaktivieren
    +			job->active = INACTIVE;
     			job->caller = NULL;	// Caller loeschen, damit Verhalten auch ohne OVERRIDE neu gestartet werden koennen
     		}
    -	}
    +	}
     }

    -/*!
    - * @brief	Zentrale Verhaltens-Routine, wird regelmaessig aufgerufen.
    +/*!
    + * @brief	Zentrale Verhaltens-Routine, wird regelmaessig aufgerufen.
      */
    -void bot_behave(void){
    +void bot_behave(void){
     	Behaviour_t *job;						// Zeiger auf ein Verhalten
    -
    +
     	float faktorLeft = 1.0;					// Puffer fuer Modifkatoren
     	float faktorRight = 1.0;				// Puffer fuer Modifkatoren
    -
    +
     	#ifdef RC5_AVAILABLE
     		rc5_control();						// Abfrage der IR-Fernbedienung
     	#endif
    @@ -479,15 +489,15 @@
     			/* WunschVariablen initialisieren */
     			speedWishLeft = BOT_SPEED_IGNORE;
     			speedWishRight = BOT_SPEED_IGNORE;
    -
    +
     			faktorWishLeft = 1.0;
     			faktorWishRight = 1.0;
    -
    +
     			if (job->work)	// hat das Verhalten eine Work-Routine
     				job->work(job);	/* Verhalten ausfuehren */
     			else // wenn nicht: Verhalten deaktivieren, da es nicht sinnvoll arbeiten kann
    -				job->active=INACTIVE;
    -
    +				job->active=INACTIVE;
    +
     			/* Modifikatoren sammeln  */
     			faktorLeft  *= faktorWishLeft;
     			faktorRight *= faktorWishRight;
    @@ -497,11 +507,11 @@
     					speedWishLeft *= faktorLeft;
     				if (speedWishRight != BOT_SPEED_IGNORE)
     					speedWishRight *= faktorRight;
    -
    +
     				motor_set(speedWishLeft, speedWishRight);
     				break;						/* Wenn ein Verhalten Werte direkt setzen will, nicht weitermachen */
     			}
    -
    +
     		}
     		/* Dieser Punkt wird nur erreicht, wenn keine Regel im System die Motoren beeinflusen will */
     		if (job->next == NULL) {
    @@ -510,18 +520,18 @@
     	}
     }

    -/*!
    - * @brief			Erzeugt ein neues Verhalten
    +/*!
    + * @brief			Erzeugt ein neues Verhalten
      * @param priority 	Die Prioritaet
      * @param *work 	Den Namen der Funktion, die sich drum kuemmert
      * @param active	Boolean, ob das Verhalten aktiv oder inaktiv erstellt wird
      */
     Behaviour_t *new_behaviour(uint8 priority, void (*work) (struct _Behaviour_t *data), int8 active){
    -	Behaviour_t *newbehaviour = (Behaviour_t *) malloc(sizeof(Behaviour_t));
    -
    -	if (newbehaviour == NULL)
    +	Behaviour_t *newbehaviour = (Behaviour_t *) malloc(sizeof(Behaviour_t));
    +
    +	if (newbehaviour == NULL)
     		return NULL;
    -
    +
     	newbehaviour->priority = priority;
     	newbehaviour->active=active;
     	newbehaviour->next= NULL;
    @@ -539,11 +549,11 @@
     void insert_behaviour_to_list(Behaviour_t **list, Behaviour_t *behave){
     	Behaviour_t	*ptr	= *list;
     	Behaviour_t *temp	= NULL;
    -
    +
     	/* Kein Eintrag dabei? */
     	if (behave == NULL)
     		return;
    -
    +
     	/* Erster Eintrag in der Liste? */
     	if (ptr == NULL){
     		ptr = behave;
    @@ -557,13 +567,13 @@
     		} else {
     			/* Mit dem naechsten Eintrag vergleichen */
     			while(NULL != ptr->next) {
    -				if (ptr->next->priority < behave->priority)
    +				if (ptr->next->priority < behave->priority)
     					break;
    -
    +
     				/* Naechster Eintrag */
     				ptr = ptr->next;
     			}
    -
    +
     			temp = ptr->next;
     			ptr->next = behave;
     			behave->next = temp;
    @@ -575,7 +585,7 @@
     	/*!
     	 * @brief		Behandelt die Tasten fuer die Verhaltensanezeige, die das jeweilige Verhalten aktivieren oder deaktivieren.
     	 * @author 		Timo Sandmann (mail@xxxxxxxxxxxxxxx)
    - 	 * @date 		14.02.2007
    + 	 * @date 		14.02.2007
      	 * @param data	Zeiger auf ein Array mit Verhaltensdatensatzzeigern
     	 */
     	static void beh_disp_key_handler(Behaviour_t** data){
    @@ -584,12 +594,12 @@
     		switch (RC5_Code){
     			case RC5_CODE_1: callee = data[0]; break;
     			case RC5_CODE_2: callee = data[1]; break;
    -			case RC5_CODE_3: callee = data[2]; break;
    -			case RC5_CODE_4: callee = data[3]; break;
    -			case RC5_CODE_5: callee = data[4]; break;
    -			case RC5_CODE_6: callee = data[5]; break;
    -			case RC5_CODE_7: callee = data[6]; break;
    -			case RC5_CODE_8: callee = data[7]; break;
    +			case RC5_CODE_3: callee = data[2]; break;
    +			case RC5_CODE_4: callee = data[3]; break;
    +			case RC5_CODE_5: callee = data[4]; break;
    +			case RC5_CODE_6: callee = data[5]; break;
    +			case RC5_CODE_7: callee = data[6]; break;
    +			case RC5_CODE_8: callee = data[7]; break;
     		}
     		/* Verhaltensstatus toggeln */
     		if (callee != NULL){
    @@ -597,29 +607,29 @@
     			callee->active ^= 1;
     		}
     	}
    -
    +
     	/*!
     	 * @brief	Zeigt Informationen ueber Verhalten an, 'A' fuer Verhalten aktiv, 'I' fuer Verhalten inaktiv.
     	 * @author 	Timo Sandmann (mail@xxxxxxxxxxxxxxx)
    - 	 * @date 	12.02.2007
    - 	 * Es werden zwei Spalten mit jeweils 4 Verhalten angezeigt. Gibt es mehr Verhalten in der Liste, kommt man
    + 	 * @date 	12.02.2007
    + 	 * Es werden zwei Spalten mit jeweils 4 Verhalten angezeigt. Gibt es mehr Verhalten in der Liste, kommt man
      	 * mit der Taste DOWN auf eine weitere Seite (die aber kein extra Screen ist). Mit der Taste UP geht's bei Bedarf
      	 * wieder zurueck. Vor den Prioritaeten steht eine Nummer von 1 bis 8, drueckt man die entsprechende Zifferntaste
      	 * auf der Fernbedienung, so wird das Verhalten aktiv oder inaktiv geschaltet, komplementaer zum aktuellen Status.
    - 	 * Den Keyhandler dazu stellt beh_disp_key_handler() dar.
    + 	 * Den Keyhandler dazu stellt beh_disp_key_handler() dar.
     	 */
    -	void behaviour_display(void){
    +	void behaviour_display(void){
     		static uint8 behaviour_page = 0;	/*!< zuletzt angezeigte Verhaltensseite */
    -		if (RC5_Code == RC5_CODE_DOWN){
    +		if (RC5_Code == RC5_CODE_DOWN){
     			/* naechste Seite */
     			behaviour_page++;
     			display_clear();	// Screen-Nr. wechselt nicht => Screen selbst loeschen
    -			RC5_Code = 0;	// Taste behandelt
    -		} else if (RC5_Code == RC5_CODE_UP){
    +			RC5_Code = 0;	// Taste behandelt
    +		} else if (RC5_Code == RC5_CODE_UP){
     			/* vorherige Seite */
     			if (behaviour_page > 0) behaviour_page--;
     			display_clear();
    -			RC5_Code = 0;
    +			RC5_Code = 0;
     		}
     		Behaviour_t* behaviours[8] = {NULL};	/*!< speichert Zeiger auf die Verhalten fuer den Keyhandler zwischen */
     		uint8 i,j,k=0;
    @@ -639,7 +649,7 @@
     			}
     		}
     		char status[2] = "IA";	// I: inactive, A: active
    -		/* max. 4 Zeilen mit jeweils 2 Verhalten (= 8 Verhalten) anzeigbar */
    +		/* max. 4 Zeilen mit jeweils 2 Verhalten (= 8 Verhalten) anzeigbar */
     		for (i=1; i<=20; i+=11){	// Spalten
     			for (j=1; j<=4; j++){	// Zeilen
     				while (ptr != NULL && ptr->priority > PRIO_VISIBLE_MAX)
    @@ -647,16 +657,16 @@
     				if (ptr == NULL || ptr->priority < PRIO_VISIBLE_MIN){
     					if (i==1 && j==1 && behaviour_page > 0) behaviour_page--;	// keine unnoetige leere Seite anzeigen
     					if (RC5_Code !=0) beh_disp_key_handler(behaviours);	// Tasten auswerten
    -					return; // fertig, da ptr == NULL oder Prioritaet bereits zu klein
    +					return; // fertig, da ptr == NULL oder Prioritaet bereits zu klein
     				}
     				/* Ausgabe */
     				display_cursor(j, i);
     				display_printf("%u: %3d=%c ", k+1, ptr->priority, status[ptr->active]);
     				behaviours[k++] = ptr;	// speichern fuer Tastenhandler
     				ptr = ptr->next;
    -			}
    -		}
    +			}
    +		}
     		if (RC5_Code !=0) beh_disp_key_handler(behaviours);	// Tasten auswerten
    -	}
    +	}
     #endif	// DISPLAY_BEHAVIOUR_AVAILABLE
     #endif	// BEHAVIOUR_AVAILABLE
    Index: C:/botneu/ct-Bot/Changelog.txt
    ===================================================================
    --- C:/botneu/ct-Bot/Changelog.txt	(revision 1462)
    +++ C:/botneu/ct-Bot/Changelog.txt	(working copy)
    @@ -1,5 +1,7 @@
     CHANGELOG fuer c't-Bot
     ======================
    +2008-08-25 Frank Menzel [Menzelfr@xxxxxxx]: Verhalten behaviour_area zum flaechendeckenden Fahren nach der Map unter Verwendung des pos_stacks
    +
     2008-08-24 Timo Sandmann [mail@xxxxxxxxxxxxxxx]: Bugfix in mcu/minifat.c fuer aeltere avr-libc-Versionen, Makefile korrigiert, kleine Ergaenzung (1st_init.S) des PC-Codes fuer ARM-Architektur (arm-linux-eabi)

     2008-08-10 Timo Sandmann [mail@xxxxxxxxxxxxxxx]: Mini-FAT ueberprueft nun, ob eine Datei fragmentiert auf der MMC liegt (Workaround fuer #172). Ueberpruefung mit MINI_FAT_CHECK_FRAGMENTATION in mcu/mini-fat.c einstellbar.
    Index: C:/botneu/ct-Bot/ct-Bot.h
    ===================================================================
    --- C:/botneu/ct-Bot/ct-Bot.h	(revision 1462)
    +++ C:/botneu/ct-Bot/ct-Bot.h	(working copy)
    @@ -53,7 +53,7 @@
     #define MEASURE_MOUSE_AVAILABLE			/*!< Geschwindigkeiten werden aus den Maussensordaten berechnet */
     //#define MEASURE_COUPLED_AVAILABLE		/*!< Geschwindigkeiten werden aus Maus- und Encoderwerten ermittelt und gekoppelt */

    -//#define POS_STACK_AVAILABLE  /*!< Positionsstack vorhanden */
    +#define POS_STACK_AVAILABLE  /*!< Positionsstack vorhanden */

     //#define WELCOME_AVAILABLE	/*!< kleiner Willkommensgruss */

    @@ -70,9 +70,9 @@

     #define BEHAVIOUR_AVAILABLE /*!< Nur wenn dieser Parameter gesetzt ist, exisitiert das Verhaltenssystem */

    -//#define MAP_AVAILABLE /*!< Aktiviere die Kartographie */
    +#define MAP_AVAILABLE /*!< Aktiviere die Kartographie */

    -//#define SPEED_CONTROL_AVAILABLE /*!< Aktiviert die Motorregelung */
    +#define SPEED_CONTROL_AVAILABLE /*!< Aktiviert die Motorregelung */
     //#define ADJUST_PID_PARAMS		/*!< macht PID-Paramter zur Laufzeit per FB einstellbar */
     //#define SPEED_LOG_AVAILABLE 	/*!< Zeichnet Debug-Infos der Motorregelung auf MMC auf */

    @@ -80,7 +80,7 @@
     //#define CMPS03_AVAILABLE		/*!< Kompass CMPS03 vorhanden */
     //#define SP03_AVAILABLE		/*!< Sprachmodul SP03 vorhanden */

    -//#define MMC_AVAILABLE			/*!< haben wir eine MMC/SD-Karte zur Verfuegung */
    +#define MMC_AVAILABLE			/*!< haben wir eine MMC/SD-Karte zur Verfuegung */
     //#define SPI_AVAILABLE			/*!< verwendet den Hardware-SPI-Modus des Controllers, um mit der MMC zu kommunizieren - Hinweise in mcu/mmc.c beachten! */
     //#define MMC_VM_AVAILABLE		/*!< Virtual Memory Management mit MMC / SD-Card oder PC-Emulation */
     //#define OS_AVAILABLE			/*!< Aktiviert BotOS fuer Threads und Scheduling */
    Index: C:/botneu/ct-Bot/include/bot-logic/available_behaviours.h
    ===================================================================
    --- C:/botneu/ct-Bot/include/bot-logic/available_behaviours.h	(revision 1462)
    +++ C:/botneu/ct-Bot/include/bot-logic/available_behaviours.h	(working copy)
    @@ -5,7 +5,7 @@

     #ifdef BEHAVIOUR_AVAILABLE

    -/*!
    +/*!
      * @file 	available_behaviours.h
      * @brief 	globale Schalter fuer die einzelnen Verhalten
      */
    @@ -53,17 +53,25 @@

     #define BEHAVIOUR_DELAY_AVAILABLE /*!< Delay-Routinen als Verhalten */

    -/* Aufgrund einer ganzen reihe von Abhaengigkeiten sollte man beim Versuch Speicher
    - * zu sparen, zuerst mal bei den Hauptverhalten ausmisten, sonst kommen die
    +#define BEHAVIOUR_AREA_AVAILABLE /*!< flaechendeckendes Fahren mit Map */
    +
    +/* Aufgrund einer ganzen reihe von Abhaengigkeiten sollte man beim Versuch Speicher
    + * zu sparen, zuerst mal bei den Hauptverhalten ausmisten, sonst kommen die
      * Unterverhalten durch die Hintertuer wieder rein
      */
     #ifndef MAP_AVAILABLE
     	#undef BEHAVIOUR_SCAN_AVAILABLE
    +	#undef BEHAVIOUR_AREA_AVAILABLE
     #endif

    +#ifdef BEHAVIOUR_AREA_AVAILABLE
    +  #define BEHAVIOUR_GOTO_POS_AVAILABLE
    +  #define BEHAVIOUR_CANCEL_BEHAVIOUR_AVAILABLE
    +#endif
    +
     #ifdef BEHAVIOUR_GOTOXY_AVAILABLE
     	#define BEHAVIOUR_TURN_AVAILABLE
    -#endif
    +#endif

     #ifdef BEHAVIOUR_DRIVE_STACK_AVAILABLE
     	#define BEHAVIOUR_GOTO_POS_AVAILABLE
    @@ -71,7 +79,7 @@

     #ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
     	#define BEHAVIOUR_TURN_AVAILABLE
    -#endif
    +#endif

     #ifdef BEHAVIOUR_TURN_TEST_AVAILABLE
     	#define BEHAVIOUR_TURN_AVAILABLE
    @@ -87,26 +95,26 @@
     #ifdef BEHAVIOUR_FOLLOW_LINE_AVAILABLE
     	#define BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
     	#define BEHAVIOUR_TURN_AVAILABLE
    -#endif
    +#endif

     #ifdef BEHAVIOUR_OLYMPIC_AVAILABLE
     	#define BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
     	#define BEHAVIOUR_TURN_AVAILABLE
    -#endif
    +#endif

     #ifdef BEHAVIOUR_SIMPLE_AVAILABLE
     	#define BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
    -#endif
    +#endif

     #ifdef BEHAVIOUR_SOLVE_MAZE_AVAILABLE
     	#define BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
     	#define BEHAVIOUR_DELAY_AVAILABLE
    -#endif
    +#endif

     #ifdef BEHAVIOUR_DRIVE_SQUARE_AVAILABLE
     	#define BEHAVIOUR_TURN_AVAILABLE
     	#define BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
    -#endif
    +#endif

     #ifdef BEHAVIOUR_CLASSIFY_OBJECTS_AVAILABLE
     	#define BEHAVIOUR_CATCH_PILLAR_AVAILABLE
    @@ -208,5 +216,7 @@

     #include "bot-logic/behaviour_drive_stack.h"

    +#include "bot-logic/behaviour_area.h"
    +
     #endif	// BEHAVIOUR_AVAILABLE
     #endif	/*AVAILABLE_BEHAVIOURS_H_*/
    Index: C:/botneu/ct-Bot/include/bot-logic/behaviour_area.h
    ===================================================================
    --- C:/botneu/ct-Bot/include/bot-logic/behaviour_area.h	(revision 0)
    +++ C:/botneu/ct-Bot/include/bot-logic/behaviour_area.h	(revision 0)
    @@ -0,0 +1,79 @@
    +/*
    + * c't-Bot
    + *
    + * 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; either version 2 of the License, or (at your
    + * option) any later version.
    + * This program is distributed in the hope that it will be
    + * useful, but WITHOUT ANY WARRANTY; without even the implied
    + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
    + * PURPOSE. See the GNU General Public License for more details.
    + * You should have received a copy of the GNU General Public
    + * License along with this program; if not, write to the Free
    + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
    + * MA 02111-1307, USA.
    + *
    + */
    +
    +
    +/*! @file 	behaviour_area.c
    + * @brief 	Flaechendeckendes Fahren als Verhalten (Staubsauger)
    + *          Der Bot faehrt geradeaus bis zu einem Hindernis, dort dreht er sich zu einer Seite und faehrt auf der Nebenspur wieder zurueck. Der
    + *          andere moegliche Weg wird als Alternative auf den Stack gespeichert. Falls es irgendwo nicht weitergeht, so wird eine solche Strecke
    + *          vom Stack geholt und angefahren. Leider gibt es noch kein Map-Planungsverhalten, welches einen anderen Punkt unter Umgehung von
    + *          Hindernissen anfaehrt. In dieser Version wird etwas tricky gefahren und versucht, diese Strecke anzufahren. Im Falle
    + *          aber des nicht moeglichen Anfahrens wird eben diese Strecke verworfen. Ein Planungsverhalten, welches moeglichst auch
    + *          nur ueber befahrene Abschnitte plant, wuerde entscheidend helfen.
    + *
    + * @author 	Frank Menzel (Menzelfr@xxxxxxx)
    + * @date 	16.07.2008
    +*/
    +
    +
    +#ifndef BEHAVIOUR_AREA_H_
    +#define BEHAVIOUR_AREA_H_
    +
    +#include "ct-Bot.h"
    +#include "bot-logic/bot-logik.h"
    +
    +#ifdef BEHAVIOUR_AREA_AVAILABLE
    +
    +
    +/*!
    + * Observer links; jeweils ein selbstaendiges Verhalten, welches die Nachbarbahn beobachtet und eine befahrbare Strecke bis zu einem Hindernis
    + * auf den Stack legt fuer spaeteres Anfahren; ebenfalls wird eine Alternativroute auf dem Stack gemerkt
    + * Verhalten wurde so geschrieben, dass es zwar 2 Verhalten sind, der Code jedoch identisch ist und daher in Subroutinen ausgelagert ist
    + * @param data Verhaltensdatensatz
    + */
    +void bot_observe_left_behaviour(Behaviour_t *data);
    +
    +/*!
    + * Observer rechts; jeweils ein selbstaendiges Verhalten, welches die Nachbarbahn beobachtet und eine befahrbare Strecke bis zu einem Hindernis
    + * auf den Stack legt fuer spaeteres Anfahren; ebenfalls wird eine Alternativroute auf dem Stack gemerkt
    + * Verhalten wurde so geschrieben, dass es zwar 2 Verhalten sind, der Code jedoch identisch ist und daher in Subroutinen ausgelagert ist
    + * @param data Verhaltensdatensatz
    + */
    +void bot_observe_right_behaviour(Behaviour_t *data);
    +
    +/*!
    + * Das Fahrverhalten selbst; Fahren bis zu einem Hindernis, drehen zu einer Seite und merken des anderen Weges auf den Stack; waehrend der
    + * Fahrt werden die Nebenspuren beobachtet und bei Hindernissen in der Nebenspur automatisch Teilstrecken auf den Stack gelegt
    + * @param *data der Verhaltensdatensatz
    + */
    +void bot_area_behaviour(Behaviour_t *data);
    +
    +/*!
    + * Startet das Verhalten bot_area_behaviour
    + * @param caller	Der obligatorische Verhaltensdatensatz des Aufrufers
    + */
    +void bot_area(Behaviour_t * caller);
    +
    +/*!
    + * Notfallhandler, ausgefuehrt bei Abgrunderkennung und muss registriert werden
    + */
    +void border_area_handler(void);
    +
    +#endif /*AREA_AVAILABLE */
    +#endif /*BEHAVIOUR_AREA_H_*/
    Index: C:/botneu/ct-Bot/ui/rc5.c
    ===================================================================
    --- C:/botneu/ct-Bot/ui/rc5.c	(revision 1462)
    +++ C:/botneu/ct-Bot/ui/rc5.c	(working copy)
    @@ -1,23 +1,23 @@
     /*
      * c't-Bot
    - *
    + *
      * 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; either version 2 of the License, or (at your
    - * option) any later version.
    - * This program is distributed in the hope that it will be
    + * option) any later version.
    + * This program is distributed in the hope that it will be
      * useful, but WITHOUT ANY WARRANTY; without even the implied
    - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
    + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
      * PURPOSE. See the GNU General Public License for more details.
    - * You should have received a copy of the GNU General Public
    - * License along with this program; if not, write to the Free
    + * You should have received a copy of the GNU General Public
    + * License along with this program; if not, write to the Free
      * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
      * MA 02111-1307, USA.
    - *
    + *
      */

    -/*!
    +/*!
      * @file 	rc5.c
      * @brief 	RC5-Fernbedienung / Basic-Tasten-Handler
      * Um RC5-Codes fuer eine eigene Fernbedienung anzupassen, reicht es diese
    @@ -27,7 +27,7 @@
      * @author 	Timo Sandmann (mail@xxxxxxxxxxxxxxx)
      * @date 	12.02.2007
      */
    -
    +
     #include "bot-logic/bot-logik.h"
     #include "map.h"
     #include "ir-rc5.h"
    @@ -49,7 +49,7 @@
     /*!
      * @brief			Setzt das Display auf eine andere Ausgabe.
      * @param screen	Parameter mit dem zu setzenden Screen.
    - */
    + */
     static void rc5_screen_set(uint8 screen){
     	#ifdef DISPLAY_AVAILABLE
     		if (screen == DISPLAY_SCREEN_TOGGLE)
    @@ -64,9 +64,9 @@
     }

     /*!
    - * @brief	Stellt die Not-Aus-Funktion dar.
    + * @brief	Stellt die Not-Aus-Funktion dar.
      * Sie laesst den Bot anhalten und setzt alle Verhalten zurueck mit Sicherung der vorherigen Aktivitaeten.
    - */
    + */
     static void rc5_emergency_stop(void) {
     	#ifdef BEHAVIOUR_AVAILABLE
     		target_speed_l = 0;	// Geschwindigkeit nullsetzen
    @@ -74,12 +74,12 @@
     		deactivateAllBehaviours();  // alle Verhalten deaktivieren mit vorheriger Sicherung
     	#endif
     }
    -
    +
     /*!
      * @brief		Aendert die Geschwindigkeit um den angegebenen Wert.
      * @param left	linke, relative Geschwindigkeitsaenderung
    - * @param right	rechte, relative Geschwindigkeitsaenderung
    - */
    + * @param right	rechte, relative Geschwindigkeitsaenderung
    + */
     static void rc5_bot_change_speed(int16 left, int16 right) {
     	#ifdef BEHAVIOUR_AVAILABLE
     		int16 old;
    @@ -91,8 +91,8 @@
     			target_speed_l = BOT_SPEED_MIN;
     		else if (target_speed_l > -BOT_SPEED_MIN && target_speed_l < 0)
     			target_speed_l = -BOT_SPEED_MIN;
    -
    -		old = target_speed_r;
    +
    +		old = target_speed_r;
     		target_speed_r += right;
     		if ((target_speed_r <-BOT_SPEED_MAX) ||(target_speed_r > BOT_SPEED_MAX))
     			target_speed_r = old;
    @@ -136,12 +136,12 @@
     			case 1:	target_speed_l = BOT_SPEED_SLOW; target_speed_r = BOT_SPEED_SLOW; break;
     			case 3: target_speed_l = BOT_SPEED_NORMAL; target_speed_r = BOT_SPEED_NORMAL; break;
     		#endif	// BEHAVIOUR_AVAILABLE
    -
    +
     		#ifdef BEHAVIOUR_TURN_AVAILABLE
     			case 2: bot_turn(NULL, 90); break;
     			case 7: bot_turn(NULL, 180); break;
     			case 9: bot_turn(NULL, -180); break;
    -		#endif	// BEHAVIOUR_TURN_AVAILABLE
    +		#endif	// BEHAVIOUR_TURN_AVAILABLE

     		#if defined BEHAVIOUR_CATCH_PILLAR_AVAILABLE
     			case 4: bot_catch_pillar(NULL); break;
    @@ -154,7 +154,7 @@
     		#elif defined BEHAVIOUR_SOLVE_MAZE_AVAILABLE
     			case 5: bot_solve_maze(NULL); break;
     		#endif	// BEHAVIOUR_SOLVE_MAZE_AVAILABLE
    -
    +
     		#if defined BEHAVIOUR_CALIBRATE_PID_AVAILABLE
     			case 6: bot_calibrate_pid(NULL, BOT_SPEED_SLOW); break;
     		#elif defined BEHAVIOUR_CALIBRATE_SHARPS_AVAILABLE
    @@ -162,8 +162,10 @@
     		#elif defined BEHAVIOUR_TURN_AVAILABLE
     			case 6: bot_turn(NULL, -90); break;
     		#endif	// BEHAVIOUR_CALIBRATE_PID_AVAILABLE
    -
    -		#ifdef BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
    +
    +		#ifdef BEHAVIOUR_AREA_AVAILABLE
    +		    case 8: bot_area(NULL); break;
    +		#elif defined  BEHAVIOUR_DRIVE_DISTANCE_AVAILABLE
     			case 8: bot_drive_distance(NULL, 0, BOT_SPEED_NORMAL, 10); break;
     		#elif defined BEHAVIOUR_GOTO_POS_AVAILABLE
     			case 8: bot_goto_dist(NULL, 100, 0); break;
    @@ -177,24 +179,24 @@
      * @date 	12.02.2007
      * Hier gehoeren nur die absoluten Basics an Tastenzuordnungen rein, nicht Spezielles! Sonderwuensche
      * evtl. nach rc5_number(), ab besten aber eigenen Screenhandler anlegen und mit GUI/register_screen()
    - * einhaengen.
    + * einhaengen.
      * Prinzip hier: Uebersichtlichkeit! :)
      */
     void default_key_handler(void){
    -	switch (RC5_Code){
    +	switch (RC5_Code){
     		/* Not-Aus */
     		case RC5_CODE_PWR:		rc5_emergency_stop(); break;
    -
    +
     		/* Karte Drucken */
     		#ifdef MAP_AVAILABLE
     		case RC5_CODE_DOT:		map_print(); break;
     		#endif
    -
    +
     		/* Reset */
     		#ifdef RC5_CODE_CH_PC
     		case RC5_CODE_CH_PC:	bot_reset(); break;
    -		#endif
    -
    +		#endif
    +
     		/* Screenwechsel */
     		#ifdef RC5_CODE_GREEN
     		case RC5_CODE_GREEN:	rc5_screen_set(0); break;
    @@ -209,13 +211,13 @@
     		case RC5_CODE_BLUE:		rc5_screen_set(3); break;
     		#endif
     		case RC5_CODE_TV_VCR:	rc5_screen_set(DISPLAY_SCREEN_TOGGLE); break;
    -
    +
     		/* Geschwindigkeitsaenderung */
     		case RC5_CODE_UP:		rc5_bot_change_speed( 10,  10); break;
     		case RC5_CODE_DOWN:		rc5_bot_change_speed(-10, -10); break;
     		case RC5_CODE_LEFT:		rc5_bot_change_speed(-10,  10); break;
     		case RC5_CODE_RIGHT:	rc5_bot_change_speed( 10, -10); break;
    -
    +
     		/* Servoaktivitaet */
     		#ifdef BEHAVIOUR_SERVO_AVAILABLE
     		#ifdef RC5_CH_PLUS
    @@ -225,7 +227,7 @@
     		case RC5_CH_MINUS:		bot_servo(0, SERVO1, DOOR_OPEN);  break;
     		#endif
     		#endif	// BEHAVIOUR_SERVO_AVAILABLE
    -
    +
     		/* numerische Tasten */
     		case RC5_CODE_0:		rc5_number(0); break;
     		case RC5_CODE_1:		rc5_number(1); break;
    @@ -246,9 +248,9 @@
     void rc5_control(void){
     	static uint16 RC5_Last_Toggle = 1;	/*!< Toggle-Wert des zuletzt empfangenen RC5-Codes*/
     	uint16 rc5 = ir_read();				// empfangenes RC5-Kommando
    -
    +
     	if (rc5 != 0){
    -		/* Toggle kommt nicht im Simulator, immer gewechseltes Toggle-Bit sicherstellen */
    +		/* Toggle kommt nicht im Simulator, immer gewechseltes Toggle-Bit sicherstellen */
     		#ifdef PC
     		  RC5_Last_Toggle = !(rc5 & RC5_TOGGLE);
     		#endif
    Index: C:/botneu/ct-Bot/.settings/org.eclipse.cdt.core.prefs
    ===================================================================
    --- C:/botneu/ct-Bot/.settings/org.eclipse.cdt.core.prefs	(revision 0)
    +++ C:/botneu/ct-Bot/.settings/org.eclipse.cdt.core.prefs	(revision 0)
    @@ -0,0 +1,3 @@
    +#Mon Aug 25 21:27:23 CEST 2008
    +eclipse.preferences.version=1
    +indexerId=org.eclipse.cdt.core.fastIndexer

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

- Referenzen:
  - Re: [ct-bot] MAP-Verhalten nur fuer Sim ?
    - From: Timo Sandmann

- Voriger (Datum): Re: AW: [ct-bot] Fehler nach Define MMC_AVAILABLE..., Timo Sandmann
- Nächster (Datum): Re: AW: [ct-bot] MAP-Verhalten nur fuer Sim ? -> Patch fuer Verhalten, Timo Sandmann
- Voriger (Thread): Re: [ct-bot] MAP-Verhalten nur fuer Sim ?, Timo Sandmann
- Nächster (Thread): Re: AW: [ct-bot] MAP-Verhalten nur fuer Sim ? -> Patch fuer Verhalten, Timo Sandmann
- Indizes:
  - Datum
  - Thread