429 lines
17 KiB
C
429 lines
17 KiB
C
![]() |
/*
|
|||
|
* 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_olympic.c
|
|||
|
* @brief Bot sucht saeulen und faehrt dann slalom
|
|||
|
*
|
|||
|
* @author Benjamin Benz (bbe@heise.de)
|
|||
|
* @date 03.11.06
|
|||
|
*/
|
|||
|
|
|||
|
#include "bot-logic/bot-logik.h"
|
|||
|
|
|||
|
#ifdef BEHAVIOUR_OLYMPIC_AVAILABLE
|
|||
|
#include <stdlib.h>
|
|||
|
|
|||
|
/* Zustaende des bot_explore-Verhaltens */
|
|||
|
|
|||
|
#define EXPLORATION_STATE_GOTO_WALL 1 /*!< Zustand: Bot sucht eine Wand o.ae. Hinderniss */
|
|||
|
#define EXPLORATION_STATE_TURN_PARALLEL_LEFT 2 /*!< Zustand: Bot dreht sich nach links, bis er parallel zur Wand blickt. */
|
|||
|
#define EXPLORATION_STATE_TURN_PARALLEL_RIGHT 3 /*!< Zustand: Bot dreht sich nach rechts, bis er parallel zur Wand blickt. */
|
|||
|
#define EXPLORATION_STATE_DRIVE_PARALLEL_LEFT 4 /*!< Zustand: Bot faehrt parallel zur Wand links von sich. */
|
|||
|
#define EXPLORATION_STATE_DRIVE_PARALLEL_RIGHT 5 /*!< Zustand: Bot faehrt parallel zur Wand rechts von sich. */
|
|||
|
#define EXPLORATION_STATE_TURN_ORTHOGONAL_LEFT 6 /*!< Zustand: Bot dreht sich nach links, bis er senkrecht zur Wand steht. */
|
|||
|
#define EXPLORATION_STATE_TURN_ORTHOGONAL_RIGHT 7 /*!< Zustand: Bot dreht sich nach rechts, bis er senkrecht zur Wand steht. */
|
|||
|
#define EXPLORATION_STATE_DRIVE_ARC 8 /*!< Zustand: Bot faehrt einen Bogen. Der Winkel des Bogens sollte in einer
|
|||
|
*!< weiteren static Variablen (z.B. curve) gespeichert sein. */
|
|||
|
|
|||
|
/* Zustaende des bot_olympic_behaviour-Verhaltens */
|
|||
|
|
|||
|
#define CB_STATE_EXPLORATION 0 /*!< Zustand: Bot erforscht die Umgebung. */
|
|||
|
#define CB_STATE_DOING_SLALOM 1 /*!< Zustand: Bot ist dabei Slalom zu fahren. */
|
|||
|
|
|||
|
/* Zustaende des bot_do_slalom-Verhaltens */
|
|||
|
|
|||
|
#define SLALOM_STATE_START 0 /*!< Zustand: Bot startet eine Slalomlauf und positioniert sich vor der Saeule. */
|
|||
|
#define SLALOM_STATE_TURN_1 1 /*!< Zustand: Bot dreht sich um 90<39>. */
|
|||
|
#define SLALOM_STATE_DRIVE_ARC 2 /*!< Zustand: Bot faehrt den Bogen um die Saeule. */
|
|||
|
#define SLALOM_STATE_TURN_2 3 /*!< Zustand: Bot dreht sich fuer den Sweep um 45<34>. */
|
|||
|
#define SLALOM_STATE_SWEEP_RUNNING 4 /*!< Zustand: Bot macht den Sweep. */
|
|||
|
#define SLALOM_STATE_SWEEP_DONE 5 /*!< Zustand: Bot ist fertig mit dem Sweep. */
|
|||
|
#define SLALOM_STATE_CHECK_PILLAR 6 /*!< Zustand: Bot ueberprueft, ob er den Slalom fortsetzen kann. */
|
|||
|
|
|||
|
#define SLALOM_ORIENTATION_LEFT 0
|
|||
|
#define SLALOM_ORIENTATION_RIGHT 1
|
|||
|
|
|||
|
/* Parameter fuer das bot_explore_behaviour() */
|
|||
|
int8 (*exploration_check_function)(void); /*!< Die Funktion, mit der das bot_explore_behaviour() feststellt, ob es etwas gefunden hat.
|
|||
|
* Die Funktion muss True (1) zurueck geben, wenn dem so ist, sonst False (0).
|
|||
|
* Beispiele fuer eine solche Funktion sind check_for_light, is_good_pillar_ahead etc.*/
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*!
|
|||
|
* Das Verhalten dreht den Bot so, dass er auf eine Lichtquelle zufaehrt. */
|
|||
|
void bot_goto_light(void){
|
|||
|
int16 speed, curve = (sensLDRL - sensLDRR)/1.5;
|
|||
|
|
|||
|
if(curve < -127) curve = -127;
|
|||
|
if(curve > 127) curve = 127;
|
|||
|
|
|||
|
if(abs(sensLDRL - sensLDRR) < 20){
|
|||
|
speed = BOT_SPEED_MAX;
|
|||
|
}else if(abs(sensLDRL - sensLDRR) < 150) {
|
|||
|
speed = BOT_SPEED_FAST;
|
|||
|
}else {
|
|||
|
speed = BOT_SPEED_NORMAL;
|
|||
|
}
|
|||
|
|
|||
|
bot_drive(curve, speed);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*!
|
|||
|
* Gibt aus, ob der Bot Licht sehen kann.
|
|||
|
* @return True, wenn der Bot Licht sieht, sonst False. */
|
|||
|
int8 check_for_light(void){
|
|||
|
// Im Simulator kann man den Bot gut auf den kleinsten Lichtschein
|
|||
|
// reagieren lassen, in der Realitaet gibt es immer Streulicht, so dass
|
|||
|
// hier ein hoeherer Schwellwert besser erscheint.
|
|||
|
// Simulator:
|
|||
|
if(sensLDRL >= 1023 && sensLDRR >= 1023) return False;
|
|||
|
// Beim echten Bot eher:
|
|||
|
// if(sensLDRL >= 100 && sensLDRR >= 100) return False;
|
|||
|
|
|||
|
else return True;
|
|||
|
}
|
|||
|
|
|||
|
/*!
|
|||
|
* Die Funktion gibt aus, ob sich innerhalb einer gewissen Entfernung ein Objekt-Hindernis befindet.
|
|||
|
* @param distance Entfernung in mm, bis zu welcher ein Objekt gesichtet wird.
|
|||
|
* @return Gibt False (0) zurueck, wenn kein Objekt innerhalb von distance gesichtet wird. Ansonsten die Differenz
|
|||
|
* zwischen dem linken und rechten Sensor. Negative Werte besagen, dass das Objekt naeher am linken, positive, dass
|
|||
|
* es naeher am rechten Sensor ist. Sollten beide Sensoren den gleichen Wert haben, gibt die Funktion 1 zurueck, um
|
|||
|
* von False unterscheiden zu koennen. */
|
|||
|
int16 is_obstacle_ahead(int16 distance){
|
|||
|
if(sensDistL > distance && sensDistR > distance) return False;
|
|||
|
if(sensDistL - sensDistR == 0) return 1;
|
|||
|
else return (sensDistL - sensDistR);
|
|||
|
}
|
|||
|
|
|||
|
/*!
|
|||
|
* Gibt aus, ob der Bot eine fuer sein Slalomverhalten geeignete Saeule vor sich hat.
|
|||
|
* @return True, wenn er eine solche Saeule vor sich hat, sonst False.*/
|
|||
|
int8 is_good_pillar_ahead(void){
|
|||
|
if(is_obstacle_ahead(COL_NEAR) != False && sensLDRL < 600 && sensLDRR < 600) return True;
|
|||
|
else return False;
|
|||
|
}
|
|||
|
|
|||
|
/*!
|
|||
|
* Das Verhalten verhindert, dass dem Bot boese Dinge wie Kollisionen oder Abstuerze widerfahren.
|
|||
|
* @return Bestand Handlungsbedarf? True, wenn das Verhalten ausweichen musste, sonst False.
|
|||
|
* TODO: Parameter einfuegen, der dem Verhalten vorschlaegt, wie zu reagieren ist.
|
|||
|
* */
|
|||
|
int8 bot_avoid_harm(void){
|
|||
|
if(is_obstacle_ahead(COL_CLOSEST) != False || sensBorderL > BORDER_DANGEROUS || sensBorderR > BORDER_DANGEROUS){
|
|||
|
speedWishLeft = -BOT_SPEED_NORMAL;
|
|||
|
speedWishRight = -BOT_SPEED_NORMAL;
|
|||
|
return True;
|
|||
|
} else return False;
|
|||
|
}
|
|||
|
|
|||
|
/*!
|
|||
|
* Das Verhalten laesst den Roboter den Raum durchsuchen.
|
|||
|
* Das Verhalten hat mehrere unterschiedlich Zustaende:
|
|||
|
* 1. Zu einer Wand oder einem anderen Hindernis fahren.
|
|||
|
* 2. Zu einer Seite drehen, bis der Bot parallel zur Wand ist.
|
|||
|
* Es macht vielleicht Sinn, den Maussensor auszulesen, um eine Drehung um
|
|||
|
* einen bestimmten Winkel zu realisieren. Allerdings muesste dafuer auch der
|
|||
|
* Winkel des Bots zur Wand bekannt sein.
|
|||
|
* 3. Eine feste Strecke parallel zur Wand vorwaerts fahren.
|
|||
|
* Da bot_glance_behaviour abwechselnd zu beiden Seiten schaut, ist es fuer die Aufgabe,
|
|||
|
* einer Wand auf einer Seite des Bots zu folgen, nur bedingt gewachsen und muss
|
|||
|
* evtl. erweitert werden.
|
|||
|
* 4. Senkrecht zur Wand drehen.
|
|||
|
* Siehe 2.
|
|||
|
* 5. Einen Bogen fahren, bis der Bot wieder auf ein Hindernis stoesst.
|
|||
|
* Dann das Ganze von vorne beginnen, nur in die andere Richtung und mit einem
|
|||
|
* weiteren Bogen. So erforscht der Bot einigermassen systematisch den Raum.
|
|||
|
*
|
|||
|
* Da das Verhalten jeweils nach 10ms neu aufgerufen wird, muss der Bot sich
|
|||
|
* 'merken', in welchem Zustand er sich gerade befindet.
|
|||
|
* */
|
|||
|
void bot_explore_behaviour(Behaviour_t *data){
|
|||
|
static int8 curve = 0,state = EXPLORATION_STATE_GOTO_WALL, running_curve = False;
|
|||
|
|
|||
|
if((*exploration_check_function)()) return_from_behaviour(data);
|
|||
|
|
|||
|
switch(state){
|
|||
|
// Volle Fahrt voraus, bis ein Hindernis erreicht ist.
|
|||
|
case EXPLORATION_STATE_GOTO_WALL:
|
|||
|
// Der Bot steht jetzt vor einem Hindernis und soll sich nach rechts drehen
|
|||
|
if(bot_avoid_harm()) {
|
|||
|
state = EXPLORATION_STATE_TURN_PARALLEL_RIGHT;
|
|||
|
#ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
|
|||
|
deactivateBehaviour(bot_avoid_col_behaviour);
|
|||
|
#endif
|
|||
|
}
|
|||
|
// Es befindet sich kein Hindernis direkt vor dem Bot.
|
|||
|
else {
|
|||
|
if(sensDistL < COL_NEAR || sensDistR < COL_NEAR){
|
|||
|
bot_drive(0,BOT_SPEED_FAST);
|
|||
|
} else {
|
|||
|
bot_drive(0,BOT_SPEED_MAX);
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
// Nach links drehen, bis der Bot parallel zum Hindernis auf der rechten Seite steht.
|
|||
|
/* TODO: Aufgabe: Entwickle ein Verhalten, dass auch bei Loechern funktioniert.
|
|||
|
* Tipp dazu: Drehe den Roboter auf das Loch zu, bis beide Bodensensoren das Loch 'sehen'. Anschliessend drehe den Bot um 90 Grad.
|
|||
|
* Es ist noetig, neue Zustaende zu definieren, die diese Zwischenschritte beschreiben.
|
|||
|
* TODO: Drehung mit dem Maussensor ueberwachen. */
|
|||
|
case EXPLORATION_STATE_TURN_PARALLEL_LEFT:
|
|||
|
if(sensDistR < COL_FAR){
|
|||
|
// Volle Drehung nach links mit ca. 3Grad/10ms
|
|||
|
bot_drive(-127,BOT_SPEED_FAST);
|
|||
|
} else {
|
|||
|
// Nachdem das Hindernis nicht mehr in Sicht ist, dreht der Bot noch ca. 3 Grad weiter.
|
|||
|
// Im Zweifelsfall dreht das den Bot zu weit, aber das ist besser, als ihn zu kurz zu drehen.
|
|||
|
bot_drive(-127,BOT_SPEED_FAST);
|
|||
|
state = EXPLORATION_STATE_DRIVE_PARALLEL_RIGHT;
|
|||
|
}
|
|||
|
break;
|
|||
|
// Nach rechts drehen, bis der Bot parallel zum Hindernis auf der linken Seite steht.
|
|||
|
/* Aufgabe: siehe EXPLORATION_STATE_TURN_PARALLEL_LEFT */
|
|||
|
case EXPLORATION_STATE_TURN_PARALLEL_RIGHT:
|
|||
|
if(sensDistL < COL_FAR){
|
|||
|
// Volle Drehung nach rechts mit ca. 3Grad/10ms
|
|||
|
bot_drive(127,BOT_SPEED_FAST);
|
|||
|
} else {
|
|||
|
/* Nachdem das Hindernis nicht mehr in Sicht ist, dreht der Bot noch ca. 3 Grad weiter.
|
|||
|
* Im Zweifelsfall dreht das den Bot zu weit, aber das ist besser, als ihn zu kurz zu drehen. */
|
|||
|
bot_drive(127,BOT_SPEED_FAST);
|
|||
|
state = EXPLORATION_STATE_DRIVE_PARALLEL_LEFT;
|
|||
|
}
|
|||
|
break;
|
|||
|
case EXPLORATION_STATE_DRIVE_PARALLEL_LEFT:
|
|||
|
bot_drive_distance(data,0,BOT_SPEED_FAST,15);
|
|||
|
state = EXPLORATION_STATE_TURN_ORTHOGONAL_RIGHT;
|
|||
|
break;
|
|||
|
case EXPLORATION_STATE_DRIVE_PARALLEL_RIGHT:
|
|||
|
bot_drive_distance(data,0,BOT_SPEED_FAST,15);
|
|||
|
state = EXPLORATION_STATE_TURN_ORTHOGONAL_LEFT;
|
|||
|
break;
|
|||
|
case EXPLORATION_STATE_TURN_ORTHOGONAL_LEFT:
|
|||
|
// Drehe den Bot um 90 Grad nach links.
|
|||
|
/* Da der Bot sich immer ein bisschen zu weit von der Wand weg dreht, soll er sich
|
|||
|
* hier nur um 85 Grad drehen. Nicht schoen, aber klappt.*/
|
|||
|
bot_turn(data,85);
|
|||
|
state = EXPLORATION_STATE_DRIVE_ARC;
|
|||
|
#ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
|
|||
|
activateBehaviour(bot_avoid_col_behaviour);
|
|||
|
#endif
|
|||
|
break;
|
|||
|
case EXPLORATION_STATE_TURN_ORTHOGONAL_RIGHT:
|
|||
|
// Drehe den Bot um 90 Grad nach rechts.
|
|||
|
/* Da der Bot sich immer ein bisschen zu weit von der Wand weg dreht, soll er sich
|
|||
|
* hier nur um 85 Grad drehen. Nicht schoen, aber klappt.*/
|
|||
|
bot_turn(data,-85);
|
|||
|
state = EXPLORATION_STATE_DRIVE_ARC;
|
|||
|
#ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
|
|||
|
activateBehaviour(bot_avoid_col_behaviour);
|
|||
|
#endif
|
|||
|
break;
|
|||
|
case EXPLORATION_STATE_DRIVE_ARC:
|
|||
|
/* Fahre einen Bogen.
|
|||
|
* Der Bot soll im Wechsel Links- und Rechtsboegen fahren. Daher muss das Vorzeichen von curve wechseln.
|
|||
|
* Ausserdem soll der Bogen zunehmend weiter werden, so dass der absolute Wert von curve abnehmen muss.
|
|||
|
* Ist der Wert 0, wird er auf den engsten Bogen initialisiert. Da der Bot am Anfang nach rechts abbiegt,
|
|||
|
* muss der Wert positiv sein.
|
|||
|
* Aufgabe: Manchmal kann es passieren, dass der Bot bei einer kleinen Kurve zu weit weg von der Wand
|
|||
|
* startet und dann nur noch im Kreis faehrt. Unterbinde dieses Verhalten.
|
|||
|
*/
|
|||
|
if(curve == 0){
|
|||
|
curve = 25;
|
|||
|
running_curve = True;
|
|||
|
} else if (running_curve == False){
|
|||
|
curve *= -0.9;
|
|||
|
running_curve = True;
|
|||
|
}
|
|||
|
/* Sobald der Bot auf ein Hindernis stoesst, wird der naechste Zyklus eingeleitet.
|
|||
|
* Auf einen Rechtsbogen (curve > 0) folgt eine Linksdrehung und auf einen Linksbogen eine Rechtsdrehung.
|
|||
|
* Wenn der Wert von curve (durch Rundungsfehler bei int) auf 0 faellt, beginnt das Suchverhalten erneut.*/
|
|||
|
if(bot_avoid_harm()) {
|
|||
|
state = (curve > 0) ? EXPLORATION_STATE_TURN_PARALLEL_LEFT : EXPLORATION_STATE_TURN_PARALLEL_RIGHT;
|
|||
|
running_curve = False;
|
|||
|
#ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
|
|||
|
deactivateBehaviour(bot_avoid_col_behaviour);
|
|||
|
#endif
|
|||
|
} else {
|
|||
|
bot_drive(curve, BOT_SPEED_MAX);
|
|||
|
}
|
|||
|
break;
|
|||
|
default:
|
|||
|
state = EXPLORATION_STATE_GOTO_WALL;
|
|||
|
curve = 0;
|
|||
|
#ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
|
|||
|
activateBehaviour(bot_avoid_col_behaviour);
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
/*!
|
|||
|
* Aktiviert bot_explore_behaviour. */
|
|||
|
void bot_explore(Behaviour_t *caller, int8 (*check)(void)){
|
|||
|
exploration_check_function = check;
|
|||
|
switch_to_behaviour(caller,bot_explore_behaviour,NOOVERRIDE);
|
|||
|
}
|
|||
|
|
|||
|
/*!
|
|||
|
* Das Verhalten laesst den Bot einen Slalom fahren.
|
|||
|
* @see bot_do_slalom()
|
|||
|
* */
|
|||
|
void bot_do_slalom_behaviour(Behaviour_t *data){
|
|||
|
static int8 state = SLALOM_STATE_CHECK_PILLAR;
|
|||
|
static int8 orientation = SLALOM_ORIENTATION_RIGHT;
|
|||
|
static int8 sweep_state;
|
|||
|
static int8 sweep_steps = 0;
|
|||
|
int16 turn;
|
|||
|
int8 curve;
|
|||
|
|
|||
|
switch(state){
|
|||
|
case SLALOM_STATE_CHECK_PILLAR:
|
|||
|
// Der Bot sollte jetzt Licht sehen koennen...
|
|||
|
if(check_for_light()){
|
|||
|
// Wenn der Bot direkt vor der Saeule steht, kann der Slalom anfangen, sonst zum Licht fahren
|
|||
|
if(bot_avoid_harm()){
|
|||
|
state = SLALOM_STATE_START;
|
|||
|
} else bot_goto_light();
|
|||
|
} else {// ... sonst muss er den Slalom-Kurs neu suchen.
|
|||
|
#ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
|
|||
|
activateBehaviour(bot_avoid_col_behaviour);
|
|||
|
#endif
|
|||
|
return_from_behaviour(data);
|
|||
|
}
|
|||
|
break;
|
|||
|
case SLALOM_STATE_START:
|
|||
|
// Hier ist Platz fuer weitere Vorbereitungen, falls noetig.
|
|||
|
#ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
|
|||
|
deactivateBehaviour(bot_avoid_col_behaviour);
|
|||
|
#endif
|
|||
|
state = SLALOM_STATE_TURN_1;
|
|||
|
// break;
|
|||
|
case SLALOM_STATE_TURN_1:
|
|||
|
turn = (orientation == SLALOM_ORIENTATION_LEFT) ? 90 : -90;
|
|||
|
bot_turn(data,turn);
|
|||
|
state = SLALOM_STATE_DRIVE_ARC;
|
|||
|
break;
|
|||
|
case SLALOM_STATE_DRIVE_ARC:
|
|||
|
// Nicht wundern: Bei einem Links-Slalom faehrt der Bot eine Rechtskurve.
|
|||
|
curve = (orientation == SLALOM_ORIENTATION_LEFT) ? 25 : -25;
|
|||
|
bot_drive_distance(data,curve,BOT_SPEED_FAST,20);
|
|||
|
state = SLALOM_STATE_TURN_2;
|
|||
|
break;
|
|||
|
case SLALOM_STATE_TURN_2:
|
|||
|
turn = (orientation == SLALOM_ORIENTATION_LEFT) ? 45 : -45;
|
|||
|
bot_turn(data,turn);
|
|||
|
state = SLALOM_STATE_SWEEP_RUNNING;
|
|||
|
break;
|
|||
|
case SLALOM_STATE_SWEEP_RUNNING:
|
|||
|
if(sweep_steps == 0){
|
|||
|
sweep_state = SWEEP_STATE_CHECK;
|
|||
|
}
|
|||
|
// Insgesamt 6 Schritte drehen
|
|||
|
if(sweep_steps < 6) {
|
|||
|
if(sweep_state == SWEEP_STATE_CHECK){
|
|||
|
// Phase 1: Pruefen, ob vor dem Bot eine gute Saeule ist
|
|||
|
if(is_good_pillar_ahead() == True){
|
|||
|
// Wenn die Saeule gut ist, drauf zu und Slalom anders rum fahren.
|
|||
|
state = SLALOM_STATE_CHECK_PILLAR;
|
|||
|
orientation = (orientation == SLALOM_ORIENTATION_LEFT) ? SLALOM_ORIENTATION_RIGHT : SLALOM_ORIENTATION_LEFT;
|
|||
|
sweep_steps = 0;
|
|||
|
} else {
|
|||
|
// Sonst drehen.
|
|||
|
sweep_state = SWEEP_STATE_TURN;
|
|||
|
}
|
|||
|
}
|
|||
|
if(sweep_state == SWEEP_STATE_TURN) {
|
|||
|
// Phase 2: Bot um 15 Grad drehen
|
|||
|
turn = (orientation == SLALOM_ORIENTATION_LEFT) ? 15 : -15;
|
|||
|
bot_turn(data,turn);
|
|||
|
sweep_state = SWEEP_STATE_CHECK;
|
|||
|
sweep_steps++;
|
|||
|
}
|
|||
|
} else {
|
|||
|
turn = (orientation == SLALOM_ORIENTATION_LEFT) ? -90 : 90;
|
|||
|
bot_turn(data,turn);
|
|||
|
state = SLALOM_STATE_SWEEP_DONE;
|
|||
|
sweep_steps = 0;
|
|||
|
}
|
|||
|
break;
|
|||
|
case SLALOM_STATE_SWEEP_DONE:
|
|||
|
turn = (orientation == SLALOM_ORIENTATION_LEFT) ? -135 : 135;
|
|||
|
bot_turn(data,turn);
|
|||
|
state = SLALOM_STATE_CHECK_PILLAR;
|
|||
|
break;
|
|||
|
default:
|
|||
|
state = SLALOM_STATE_CHECK_PILLAR;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
/*!
|
|||
|
* Das Verhalten laesst den Bot zwischen einer Reihe beleuchteter Saeulen Slalom fahren.
|
|||
|
* Das Verhalten ist wie bot_explore() in eine Anzahl von Teilschritten unterteilt.
|
|||
|
* 1. Vor die aktuelle Saeule stellen, so dass sie zentral vor dem Bot und ungefaehr
|
|||
|
* COL_CLOSEST (100 mm) entfernt ist.
|
|||
|
* 2. 90 Grad nach rechts drehen.
|
|||
|
* 3. In einem relativ engen Bogen 20 cm weit fahren.
|
|||
|
* 4. Auf der rechten Seite des Bot nach einem Objekt suchen, dass
|
|||
|
* a) im rechten Sektor des Bot liegt, also zwischen -45 Grad und -135 Grad zur Fahrtrichtung liegt,
|
|||
|
* b) beleuchtet und
|
|||
|
* c) nicht zu weit entfernt ist.
|
|||
|
* Wenn es dieses Objekt gibt, wird es zur aktuellen Saeule und der Bot faehrt jetzt Slalom links.
|
|||
|
* 5. Sonst zurueck drehen, 90 Grad drehen und Slalom rechts fahren.
|
|||
|
* In diesem Schritt kann der Bot das Verhalten auch abbrechen, falls er gar kein Objekt mehr findet.
|
|||
|
*/
|
|||
|
void bot_do_slalom(Behaviour_t *caller){
|
|||
|
switch_to_behaviour(caller, bot_do_slalom_behaviour,NOOVERRIDE);
|
|||
|
}
|
|||
|
|
|||
|
/*!
|
|||
|
* Das Verhalten setzt sich aus 3 Teilverhalten zusammen:
|
|||
|
* Nach Licht suchen, auf das Licht zufahren, im Licht Slalom fahren. */
|
|||
|
void bot_olympic_behaviour(Behaviour_t *data){
|
|||
|
if(check_for_light()){
|
|||
|
/* Sobald der Bot auf ein Objekt-Hinderniss stoesst, versucht er, Slalom zu fahren.
|
|||
|
* Aufgabe: Wenn der Bot vor einem Loch steht, hinter welchem sich die Lichtquelle
|
|||
|
* befindet, wird er daran haengen bleiben. Schreibe ein Verhalten, dass das verhindert. */
|
|||
|
if(bot_avoid_harm() && is_obstacle_ahead(COL_NEAR)){
|
|||
|
bot_do_slalom(data);
|
|||
|
} else bot_goto_light();
|
|||
|
} else bot_explore(data,check_for_light);
|
|||
|
}
|
|||
|
|
|||
|
/*!
|
|||
|
* Initialisiert das Olympische Verhalten
|
|||
|
* @param prio_main Prioritaet des Olympischen Verhalten (typ. 100)
|
|||
|
* @param prio_helper Prioritaet der Hilfsfunktionen (typ. 52)
|
|||
|
* @param active ACTIVE wenn es sofort starten soll, sonst INACTIVE
|
|||
|
*/
|
|||
|
void bot_olympic_init(int8 prio_main,int8 prio_helper, int8 active){
|
|||
|
// unwichtigere Hilfsverhalten
|
|||
|
insert_behaviour_to_list(&behaviour, new_behaviour(prio_helper--, bot_explore_behaviour,INACTIVE));
|
|||
|
insert_behaviour_to_list(&behaviour, new_behaviour( prio_helper, bot_do_slalom_behaviour,INACTIVE));
|
|||
|
// Demo-Verhalten fuer aufwendiges System, inaktiv
|
|||
|
insert_behaviour_to_list(&behaviour, new_behaviour(prio_main, bot_olympic_behaviour, active));
|
|||
|
}
|
|||
|
|
|||
|
#endif
|