summaryrefslogtreecommitdiffstats
path: root/source/ct-Bot/bot-logic/behaviour_solve_maze.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/ct-Bot/bot-logic/behaviour_solve_maze.c')
-rw-r--r--source/ct-Bot/bot-logic/behaviour_solve_maze.c660
1 files changed, 660 insertions, 0 deletions
diff --git a/source/ct-Bot/bot-logic/behaviour_solve_maze.c b/source/ct-Bot/bot-logic/behaviour_solve_maze.c
new file mode 100644
index 0000000..5eb2fc4
--- /dev/null
+++ b/source/ct-Bot/bot-logic/behaviour_solve_maze.c
@@ -0,0 +1,660 @@
+/*
+ * 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_solve_maze.c
+ * @brief Wandfolger durchs Labyrinth
+ *
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 03.11.06
+*/
+
+#include "bot-logic/bot-logik.h"
+#include <math.h>
+#include <stdlib.h>
+#include "log.h"
+
+#ifdef BEHAVIOUR_SOLVE_MAZE_AVAILABLE
+
+/* Parameter fuer das check_wall_behaviour() */
+int8 wall_detected; /*!< enthaelt True oder False, je nach Ergebnis des Verhaltens */
+int8 check_direction; /*!< enthaelt CHECK_WALL_LEFT oder CHECK_WALL_RIGHT */
+int16 wall_distance; /*!< enthaelt gemessene Entfernung */
+
+/* Konstanten fuer check_wall_behaviour-Verhalten */
+#define CHECK_WALL_RIGHT 0
+#define CHECK_WALL_LEFT 1
+
+/* Parameter fuer das measure_angle_behaviour() */
+int8 measure_direction; /*!< enthaelt MEASURE_RIGHT oder MEASURE_LEFT */
+int16 measure_distance; /*!< enthaelt maximale Messentfernung, enthaelt nach der Messung die Entfernung */
+int16 measured_angle; /*!< enthaelt gedrehten Winkel oder 0, falls nichts entdeckt */
+#ifdef MEASURE_MOUSE_AVAILABLE
+ int16 start_heading; /*!< Blickwinkel des Bots zu Beginn der Messung */
+#else
+ int16 startEncL; /*!< enthaelt Encoderstand zu Beginn der Messung */
+ int16 startEncR; /*!< enthaelt Encoderstand zu Beginn der Messung */
+#endif
+/* Konstanten fuer measure_angle_behaviour-Verhalten */
+#define MEASURE_LEFT 1
+#define MEASURE_RIGHT -1
+
+
+/*!
+ * Das Verhalten dreht sich um 45 Grad in die angegebene Richtung (0=rechts, 1=links)
+ * und prueft, ob auf dem Sensor auf der Seite der angegebenen Richtung eine Wand
+ * im Abstand von 12cm zu sehen ist. Wenn dem so ist, wird die Variable wall_present
+ * auf True gesetzt, sonst False */
+void bot_check_wall_behaviour(Behaviour_t *data) {
+ /* Konstantenfuer check_wall_behaviour-Verhalten */
+ #define CORRECT_NEAR 0
+ #define CORRECT_NONE 1
+ #define CORRECT_FAR 2
+ /* Zustaende fuer check_wall_behaviour-Verhalten */
+ #define CHECK_WALL_TURN 0
+ #define CHECK_WALL_SENS 1
+ #define CHECK_WALL_TURN_BACK 2
+ #define CHECK_WALL_FINISHED 3
+ #define CHECK_WALL_CORRECT 4
+
+ static int8 checkState=CHECK_WALL_TURN;
+ /* wenn die Wand noch da ist aber aus dem Blickfeld rueckt, Entfernung und Winkel korrigieren */
+ static int8 correctDistance=CORRECT_NONE;
+ /* letzte, gueltige Distanz fuer Abweichungsberechnung */
+ static int16 lastDistance=0;
+ /* enthaelt anzahl der +/-5 identischen Messungen */
+ static int8 measureCount=0;
+ /* letzter Messwert */
+ static int16 lastSensor=0;
+
+ int16 sensor; /* fuer temporaer benutzte Senorwerte */
+
+ switch(checkState) {
+ case CHECK_WALL_TURN:
+ /* haben wir links oder rechts eine Wand? */
+ if (check_direction==CHECK_WALL_LEFT) {
+ checkState=CHECK_WALL_SENS;
+ bot_turn(data,45);
+ break;
+ } else {
+ checkState=CHECK_WALL_SENS;
+ bot_turn(data,-45);
+ break;
+ }
+
+ case CHECK_WALL_SENS:
+ if (check_direction==CHECK_WALL_LEFT) {
+ sensor=sensDistL;
+ } else {
+ sensor=sensDistR;
+ }
+ /* dafuer sorgen, dass wir nur verlaessliche Werte haben
+ * dazu muss der wert dreimal nacheinander max. um +/- 5
+ * unterschiedlich sein */
+ if (measureCount==0) {
+ lastSensor=sensor;
+ measureCount++;
+ break;
+ }
+ if (sensor>=lastSensor-5 && sensor<=lastSensor+5 && measureCount<4) {
+ /* Messwert ist ok */
+ measureCount++;
+ break;
+ } else if (measureCount<4) {
+ /* Messwert weicht zu doll ab -> von Neuem messen */
+ measureCount=0;
+ break;
+ }
+ /* ok, wir hatten drei Messungen mit nahezu identischen Werten */
+
+ /* keine wand in eingestellter Maximalentfernung? */
+ if (sensor>IGNORE_DISTANCE) {
+ correctDistance=CORRECT_NONE; /* dann auch keine Korrektur */
+ lastDistance=0; /* auch kein Vergleichswert */
+ wall_detected=False; /* keine Wand da */
+ } else if (sensor<OPTIMAL_DISTANCE-ADJUST_DISTANCE) {
+ /* bot hat den falschen Abstand zur Wand, zu nah dran */
+ wall_detected=True;
+ correctDistance=CORRECT_NEAR;
+ } else if (sensor>OPTIMAL_DISTANCE+ADJUST_DISTANCE) {
+ /* bot hat den falschen Abstand zur Wand, zu weit weg */
+ wall_detected=True;
+ correctDistance=CORRECT_FAR;
+ } else {
+ /* perfekter Abstand */
+ correctDistance=CORRECT_NONE;
+ wall_detected=True;
+ }
+ wall_distance=sensor;
+ /* Wenn Korrektur noetig, dann durchfuehren, sonst gleich zurueckdrehen */
+ if (correctDistance==CORRECT_NONE) checkState=CHECK_WALL_TURN_BACK;
+ else checkState=CHECK_WALL_CORRECT;
+ break;
+
+
+ case CHECK_WALL_TURN_BACK:
+ checkState=CHECK_WALL_FINISHED;
+ int16 turnAngle=45;
+
+ /* welcher Sensorwert wird gebraucht? */
+ if (check_direction==CHECK_WALL_LEFT) {
+ sensor=sensDistL;
+ } else {
+ sensor=sensDistR;
+ }
+ /* wenn vorhanden, aus letztem Abstand und aktuellem Abstand
+ * Korrekturwinkel berechnen, falls vorheriger Abstand da.
+ * wird durch Abstand>IGNORE_DISTANCE zurueckgesetzt */
+ if (lastDistance!=0) {
+ turnAngle=turnAngle+(lastDistance-wall_distance)/10;
+ }
+ if (sensor<IGNORE_DISTANCE) lastDistance=sensor;
+ if (check_direction==CHECK_WALL_LEFT) {
+ bot_turn(data,-turnAngle);
+ } else {
+ bot_turn(data,turnAngle);
+ }
+ break;
+
+ case CHECK_WALL_FINISHED:
+ /* ok, check beendet -> Verhalten verlassen */
+ checkState=CHECK_WALL_TURN;
+ return_from_behaviour(data);
+ break;
+
+ case CHECK_WALL_CORRECT:
+ /* Abhaengig von der Seite, auf der die Wand ist, Entfernung korrigieren */
+ if (check_direction==CHECK_WALL_LEFT) {
+ sensor=sensDistL;
+ } else {
+ sensor=sensDistR;
+ }
+ if (sensor-OPTIMAL_DISTANCE<0) {
+ speedWishLeft=-BOT_SPEED_SLOW;
+ speedWishRight=-BOT_SPEED_SLOW;
+ } else if (sensor-OPTIMAL_DISTANCE>0) {
+ speedWishLeft=BOT_SPEED_SLOW;
+ speedWishRight=BOT_SPEED_SLOW;
+ }
+ else {
+ checkState=CHECK_WALL_TURN_BACK;
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ }
+ break;
+
+
+ default:
+ checkState=CHECK_WALL_TURN;
+ return_from_behaviour(data);
+ break;
+ }
+}
+
+
+/*!
+ * Das Verhalten dreht sich um 45 Grad in die angegebene Richtung (0=rechts, 1=links)
+ * und prueft, ob auf dem Sensor auf der Seite der angegebenen Richtung eine Wand
+ * im Abstand von 12-22cm zu sehen ist. Wenn dem so ist, wird die Variable wall_present
+ * auf True gesetzt, sonst False */
+void bot_check_wall(Behaviour_t *caller,int8 direction) {
+ check_direction=direction;
+ wall_detected=False;
+ switch_to_behaviour(caller, bot_check_wall_behaviour,NOOVERRIDE);
+}
+
+#ifdef MEASURE_MOUSE_AVAILABLE
+ /*!
+ * Das Verhalten dreht den Bot in die angegebene Richtung bis ein Hindernis
+ * im Sichtbereich erscheint, das eine Entfernung bis max. zur angegebenen
+ * Distanz zum Bot hat.
+ */
+
+ void bot_measure_angle_behaviour(Behaviour_t *caller) {
+ /* Zustaende measure_angle_behaviour-Verhalten */
+ #define MEASURE_TURN 0
+ #define FOUND_OBSTACLE 1
+ #define MEASUREMENT_DONE 2
+
+ static int8 measureState=MEASURE_TURN;
+
+ /* enthaelt anzahl der +/-5 identischen Messungen */
+ static int8 measureCount=0;
+ /* letzter Messwert */
+ static int16 lastSensor=0;
+
+ /* bereits gedrehten Winkel */
+ int16 turned_angle=0;
+ if (measure_direction>0) {
+ if ((int16)heading_mou<start_heading) {
+ /* war ein ueberlauf */
+ turned_angle=360-start_heading+(int16)heading_mou;
+ } else {
+ /* sonst normale differenz berechnen */
+ turned_angle=(int16)heading_mou-start_heading;
+ }
+ } else {
+ if ((int16)heading_mou>start_heading) {
+ /* war ein ueberlauf */
+ turned_angle=360-(int16)heading_mou+start_heading;
+ } else {
+ turned_angle=start_heading-(int16)heading_mou;
+ }
+
+ }
+
+ /* sensorwert abhaengig von der Drehrichtung abnehmen */
+ int16 sensor=(measure_direction==MEASURE_LEFT)?sensDistL:sensDistR;
+ /* solange drehen, bis Hindernis innerhalb Messstrecke oder 360 Grad komplett */
+ switch(measureState){
+ case MEASURE_TURN:
+ /* nicht mehr als eine komplette Drehung machen! */
+ if (turned_angle>=360) {
+ measure_direction=-measure_direction;
+ measureState=MEASUREMENT_DONE;
+ bot_turn(caller,measure_direction*turned_angle);
+ measured_angle=0; /* kein Hindernis gefunden */
+ break;
+ }
+ /* Ist ein Objekt in Reichweite? */
+ if (sensor<=measure_distance) {
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ measureState=FOUND_OBSTACLE;
+ break;
+ }
+ /* Beginnen, zurueckzudrehen */
+ speedWishLeft = (measure_direction > 0) ? -BOT_SPEED_FOLLOW : BOT_SPEED_FOLLOW;
+ speedWishRight = (measure_direction > 0) ? BOT_SPEED_FOLLOW : -BOT_SPEED_FOLLOW;
+ break;
+
+ case FOUND_OBSTACLE:
+ /* dafuer sorgen, dass wir nur verlaessliche Werte haben
+ * dazu muss der wert dreimal nacheinander max. um +/- 5
+ * unterschiedlich sein */
+ if (measureCount==0) {
+ lastSensor=sensor;
+ measureCount++;
+ break;
+ }
+ if (sensor>=lastSensor-5 && sensor<=lastSensor+5 && measureCount<4) {
+ /* Messwert ist ok */
+ measureCount++;
+ break;
+ } else if (measureCount<4) {
+ /* Messwert weicht zu doll ab -> von Neuem messen */
+ measureCount=0;
+ break;
+ }
+ /* ok, wir hatten drei Messungen mit nahezu identischen Werten */
+ measure_distance=sensor;
+ /* Hindernis gefunden, nun Bot wieder in Ausgangsstellung drehen */
+ measure_direction=-measure_direction;
+ measured_angle=turned_angle;
+ measureState=MEASUREMENT_DONE;
+ bot_turn(caller,measure_direction*turned_angle);
+ break;
+
+ case MEASUREMENT_DONE:
+ measureState=MEASURE_TURN;
+ measureCount=0;
+ return_from_behaviour(caller);
+ break;
+ }
+ }
+
+ /*!
+ * Das Verhalten dreht den Bot in die angegebene Richtung bis ein Hindernis
+ * im Sichtbereich erscheint, das eine Entfernung bis max. zur angegebenen
+ * Distanz zum Bot hat.
+ */
+
+ void bot_measure_angle(Behaviour_t *caller, int8 direction, int16 distance) {
+ /* maximale Messentfernung und Richtung setzen */
+ measure_direction=direction;
+ measure_distance=distance;
+ /* Heading zu Anfang des Verhaltens merken */
+ start_heading=(int16)heading_mou;
+ switch_to_behaviour(caller, bot_measure_angle_behaviour,NOOVERRIDE);
+ }
+#else
+/*!
+ * Das Verhalten dreht den Bot in die angegebene Richtung bis ein Hindernis
+ * im Sichtbereich erscheint, das eine Entfernung bis max. zur angegebenen
+ * Distanz zum Bot hat.
+ */
+
+void bot_measure_angle_behaviour(Behaviour_t *caller) {
+ /* Zustaende measure_angle_behaviour-Verhalten */
+ #define MEASURE_TURN 0
+ #define FOUND_OBSTACLE 1
+ #define TURN_COMPLETED 2
+ #define TURN_BACK 3
+ #define CORRECT_ANGLE 4
+ #define MEASUREMENT_DONE 5
+
+ static int8 measureState=MEASURE_TURN;
+
+ /* bereits gedrehte Strecke errechnen */
+ int16 turnedLeft=(measure_direction>0)?-(sensEncL-startEncL):(sensEncL-startEncL);
+ int16 turnedRight=(measure_direction>0)?(sensEncR-startEncR):-(sensEncR-startEncR);
+ int16 turnedSteps=(abs(turnedLeft)+abs(turnedRight))/2;
+
+ /* sensorwert abhaengig von der Drehrichtung abnehmen */
+ int16 sensor=(measure_direction==MEASURE_LEFT)?sensDistL:sensDistR;
+ /* solange drehen, bis Hindernis innerhalb Messstrecke oder 360� komplett */
+ switch(measureState){
+ case MEASURE_TURN:
+ /* nicht mehr als eine komplette Drehung machen! */
+ if (turnedSteps>=ANGLE_CONSTANT) {
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ measureState=TURN_COMPLETED;
+ measured_angle=0; /* kein Hindernis gefunden */
+ break;
+ }
+ /* Ist ein Objekt in Reichweite? */
+ if (sensor<=measure_distance) {
+ measure_distance=sensor;
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ measureState=FOUND_OBSTACLE;
+ break;
+ }
+ /* Beginnen, zurueckzudrehen */
+ speedWishLeft = (measure_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
+ speedWishRight = (measure_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
+ break;
+
+ case FOUND_OBSTACLE:
+ /* Hindernis gefunden, nun Bot wieder in Ausgangsstellung drehen */
+ measure_direction=-measure_direction;
+ measured_angle=(int16)((long)(turnedSteps*360)/ANGLE_CONSTANT);
+ measureState=TURN_BACK;
+ speedWishLeft = (measure_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
+ speedWishRight = (measure_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
+ break;
+
+ case TURN_COMPLETED:
+ /* bot steht wieder in Ausgangsrichtung, Verhalten beenden */
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ measureState=CORRECT_ANGLE;
+ break;
+
+ case TURN_BACK:
+ /* Bot in Ausgangsposition drehen */
+ if ((turnedLeft+turnedRight)/2>=0) {
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ measureState=TURN_COMPLETED;
+ break;
+ }
+ speedWishLeft = (measure_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
+ speedWishRight = (measure_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
+ break;
+
+ case CORRECT_ANGLE:
+ /* Evtl. etwas zuruecksetzen, falls wir zu weit gefahren sind */
+ if (turnedRight>0) {
+ /* rechts zu weit gefahren..langsam zurueck */
+ speedWishRight = (measure_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
+ } else if (turnedRight<0) {
+ /* rechts noch nicht weit genug...langsam vor */
+ speedWishRight = (measure_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
+ } else {
+ /* Endposition erreicht, rechtes Rad anhalten */
+ speedWishRight = BOT_SPEED_STOP;
+ }
+ if (turnedLeft<0) {
+ /* links zu weit gefahren..langsam zurueck */
+ speedWishLeft = (measure_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
+ } else if (turnedLeft>0) {
+ /* links noch nicht weit genug...langsam vor */
+ speedWishLeft = (measure_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
+ } else {
+ /* Endposition erreicht, linkes Rad anhalten */
+ speedWishLeft = BOT_SPEED_STOP;
+ }
+ if (speedWishLeft == BOT_SPEED_STOP && speedWishRight == BOT_SPEED_STOP) {
+ /* beide Raeder haben nun wirklich die Endposition erreicht, daher anhalten */
+ measureState=MEASUREMENT_DONE;
+ }
+ break;
+
+ case MEASUREMENT_DONE:
+ measureState=MEASURE_TURN;
+ return_from_behaviour(caller);
+ break;
+ }
+}
+
+/*!
+ * Das Verhalten dreht den Bot in die angegebene Richtung bis ein Hindernis
+ * im Sichtbereich erscheint, das eine Entfernung bis max. zur angegebenen
+ * Distanz zum Bot hat.
+ */
+
+void bot_measure_angle(Behaviour_t *caller, int8 direction, int16 distance) {
+ /* maximale Messentfernung und Richtung setzen */
+ measure_direction=direction;
+ measure_distance=distance;
+ /* Encoderwerte zu Anfang des Verhaltens merken */
+ startEncL=sensEncL;
+ startEncR=sensEncR;
+ switch_to_behaviour(caller, bot_measure_angle_behaviour,NOOVERRIDE);
+}
+#endif
+/*!
+ * Das Verhalten findet seinen Weg durch ein Labyrinth, das nach gewissen Grundregeln gebaut ist
+ * in nicht immer optimaler Weise aber in jedem Fall. Es arbeitet nach dem Hoehlenforscher-Algorithmus.
+ * Einschraenkung: Objekte im Labyrinth, die Endlossschleifen verursachen koennen, z.b. ein einzeln
+ * stehender Pfeiler im Labyrinth um den der Bot dann immer wieder herum fahren wuerde.
+ */
+void bot_solve_maze_behaviour(Behaviour_t *data){
+ /* Zustaende fuer das bot_solve_maze_behaviour-Verhalten */
+ #define CHECK_FOR_STARTPAD 0
+ #define CHECK_FOR_WALL_RIGHT 1
+ #define CHECK_FOR_WALL_LEFT 2
+ #define CHECK_WALL_PRESENT 3
+ #define SOLVE_MAZE_LOOP 4
+ #define SOLVE_TURN_WALL 5
+ #define CHECK_CONDITION 6
+ #define TURN_TO_BRANCH 7
+ #define DETECTED_CROSS_BRANCH 8
+ #define APPROACH_CORNER 9
+ #define AVOID_ABYSS 10
+ #define REACHED_GOAL 11
+ static int8 mazeState=CHECK_FOR_STARTPAD;
+ static int8 followWall=-1;
+ static int8 checkedWalls=0;
+
+ int16 distance;
+ double x;
+ switch(mazeState) {
+ case CHECK_FOR_STARTPAD:
+ /* Wo beginnen wir, nach einer Wand zu suchen?
+ * Abgrund- und Kollisions-Verhalten ausschalten */
+ #ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
+ deactivateBehaviour(bot_avoid_col_behaviour);
+ #endif
+ #ifdef BEHAVIOUR_AVOID_BORDER_AVAILABLE
+ deactivateBehaviour(bot_avoid_border_behaviour);
+ #endif
+ /* sieht nach, ob der Bot auf einem definierten Startpad steht und
+ * beginnt dann mit der Suche gleich an der richtigen Wand */
+ /* Zuserst bei nach Startpad1 gucken */
+ checkedWalls=0;
+ if ((sensLineL>=STARTPAD1-10 && sensLineL<=STARTPAD1+10) ||
+ (sensLineR>=STARTPAD1-10 && sensLineR<=STARTPAD1+10)) {
+ mazeState=CHECK_FOR_WALL_LEFT;
+ break;
+ }
+ mazeState=CHECK_FOR_WALL_RIGHT;
+ break;
+
+ case CHECK_FOR_WALL_RIGHT:
+
+ mazeState=CHECK_WALL_PRESENT;
+ followWall=CHECK_WALL_RIGHT;
+ bot_check_wall(data,followWall);
+ break;
+
+ case CHECK_FOR_WALL_LEFT:
+
+ followWall=CHECK_WALL_LEFT;
+ bot_check_wall(data,followWall);
+ mazeState=CHECK_WALL_PRESENT;
+ break;
+
+
+ case CHECK_WALL_PRESENT:
+ /* wenn keine Wand gefunden aber links noch nicht nachgesehen, andere
+ * Richtung checken, sonst vorfahren */
+ checkedWalls++;
+ if (wall_detected==False){
+ /* Wand noch nicht entdeckt...haben wir schon beide gecheckt? */
+ if (checkedWalls<2) {
+ if (followWall==CHECK_WALL_RIGHT) {
+ mazeState=CHECK_FOR_WALL_LEFT;
+ break;
+ } else {
+ mazeState=CHECK_FOR_WALL_RIGHT;
+ break;
+ }
+ } else {
+ /* keine wand? dann vorfahren und selbes prozedere nochmal */
+ bot_drive_distance(data,0,BOT_SPEED_NORMAL,BOT_DIAMETER);
+ mazeState=CHECK_FOR_WALL_RIGHT;
+ checkedWalls=0;
+ break;
+ }
+ }
+ /* ok, wir haben unsere richtung im labyrinth gefunden jetzt dieser
+ * nur noch folgen bis Ziel, Abzweig oder Abgrund */
+ mazeState=SOLVE_MAZE_LOOP;
+ break;
+
+ case SOLVE_MAZE_LOOP:
+ /* Einen Schritt (=halbe BOT-Groesse) vorwaerts */
+ mazeState=SOLVE_TURN_WALL;
+ bot_drive_distance(data,0,BOT_SPEED_NORMAL,BOT_DIAMETER);
+ break;
+
+ case SOLVE_TURN_WALL:
+ /* Ziel erreicht? */
+ if ((sensLineL>GROUND_GOAL-20 && sensLineL<GROUND_GOAL+20) ||
+ (sensLineR>GROUND_GOAL-20 && sensLineR<GROUND_GOAL+20)) {
+ /* Bot hat Ziel erreicht...aus Freude einmal um die Achse drehen */
+ bot_turn(data,360);
+ mazeState=REACHED_GOAL;
+ break;
+ }
+ /* checken, ob wand vor uns (Abstand 2.5*Bot-Durchmesser in mm) */
+ distance=(sensDistL+sensDistR)/2;
+ if (distance<=25*BOT_DIAMETER) { // umrechnen 10*BOT_DIAMETER, da letzteres in cm angegeben wird
+ /* berechnete Entfernung zur Wand abzueglich optimale Distanz fahren */
+ mazeState=DETECTED_CROSS_BRANCH;
+ bot_drive_distance(data,0,BOT_SPEED_NORMAL,(distance-OPTIMAL_DISTANCE)/10);
+ break;
+ }
+ /* Zur Wand drehen....ist die Wand noch da? */
+ mazeState=CHECK_CONDITION;
+ bot_check_wall(data,followWall);
+ break;
+
+ case CHECK_CONDITION:
+ /* Solange weiter, wie die Wand zu sehen ist */
+ if (wall_detected==True) {
+ mazeState=SOLVE_MAZE_LOOP;
+ break;
+ }
+ /* messen, wo genau die Ecke ist */
+ mazeState=APPROACH_CORNER;
+ if (followWall==CHECK_WALL_LEFT){
+ bot_measure_angle(data,MEASURE_LEFT,300);
+ } else {
+ bot_measure_angle(data,MEASURE_RIGHT,300);
+ }
+ break;
+
+ case TURN_TO_BRANCH:
+ /* nun in Richtung Abzweig drehen , dann mit Hauptschleife weiter*/
+ mazeState=SOLVE_MAZE_LOOP;
+ if (followWall==CHECK_WALL_RIGHT) {
+ bot_turn(data,-90);
+ } else {
+ bot_turn(data,90);
+ }
+ break;
+
+ case DETECTED_CROSS_BRANCH:
+ /* Bot faehrt auf eine Ecke zu, in Richtung Gang drehen */
+ if (followWall==CHECK_WALL_LEFT) {
+ mazeState=SOLVE_MAZE_LOOP;
+ bot_turn(data,-90);
+ } else {
+ mazeState=SOLVE_MAZE_LOOP;
+ bot_turn(data,90);
+ }
+ break;
+
+ case APPROACH_CORNER:
+ /* ok, nun strecke bis zur Kante berechnen */
+ x=measure_distance*cos(measured_angle*M_PI/180)/10+BOT_DIAMETER*1.5;
+ mazeState=TURN_TO_BRANCH;
+ bot_drive_distance(data,0,BOT_SPEED_NORMAL,(int16)x);
+ break;
+
+ case REACHED_GOAL:
+ mazeState=CHECK_WALL_RIGHT;
+ speedWishLeft=BOT_SPEED_STOP;
+ speedWishRight=BOT_SPEED_STOP;
+ return_from_behaviour(data);
+ break;
+ }
+}
+
+
+/*!
+ * Das Verhalten findet seinen Weg durch ein Labyrinth, das nach gewissen Grundregeln gebaut ist
+ * in nicht immer optimaler Weise aber in jedem Fall. Es arbeitet nach dem Hoehlenforscher-Algorithmus.
+ * Einschraenkung: Objekte im Labyrinth, die Endlossschleifen verursachen koennen, z.b. ein einzeln
+ * stehender Pfeiler im Labyrinth um den der Bot dann immer wieder herum fahren wuerde.
+ */
+
+void bot_solve_maze(Behaviour_t *caller){
+ LOG_DEBUG(("bot_solve_maze()"));
+ switch_to_behaviour(caller, bot_solve_maze_behaviour,NOOVERRIDE);
+}
+
+/*!
+ * Initialisiert den Hoelenforscher
+ * @param prio_main Prioritaet des Hoehlenforschers (typ. 100)
+ * @param prio_helper Prioritaet der Hilfsfunktionen (typ. 42)
+ * @param active ACTIVE wenn der hoehlenforcher sofort starten soll, sonst INACTIVE
+ */
+void bot_solve_maze_init(int8 prio_main,int8 prio_helper, int8 active){
+ // Verhalten, um ein Labyrinth nach der Hoehlenforscher-Methode loesen
+ insert_behaviour_to_list(&behaviour, new_behaviour(prio_main, bot_solve_maze_behaviour,active));
+
+ insert_behaviour_to_list(&behaviour, new_behaviour(prio_helper--, bot_measure_angle_behaviour,INACTIVE));
+ insert_behaviour_to_list(&behaviour, new_behaviour(prio_helper, bot_check_wall_behaviour,INACTIVE));
+
+}
+#endif