Beim Fahren entlang einer Wand ist zu berücksichtigen, dass die Abstandssensoren schräg nach vorne gerichtet sind, und so eine Wand(ecke) neben dem Roboter nicht mehr erfassen. So kann der Roboter nicht sofort entscheiden ob die Wand nur krum ist oder zu Ende ist, d.h. eine scharfe Ecke hat. Weiterhin reicht schon eine leichte Drehung um einen grossen Unterschied im Abstandswert zu bekommen (Gefahr des ständigen überschwingens beim Regeln).
Die nachfolgende Prozedur steuert den Roboter so, dass er an der uebergeben Wand (line/rechte) entlang fährt. Dazu wird eine Regelung um den vordefinierten Sollabstand herum vorgenommen. Befindet sich der Roboter zu nahe an der Wand, so dreht er sich so weit, bis er, ohne die Wand zu berühren, losfahren kann.
Damit der Roboter nicht ständig an einer einmal gefundenen Wand entlangfährt (z.B. die Spielfeldbergenzung), sondern 'auch mal wieder' nach dem Turm sucht, gibt es ein Timeout mit Zufallsanteil.
LEFT_IR und RIGHT_IR sind Makros der Bibliothek, die der Abstandswert des linken bzw. rechten Sensord zurückgeben.
#define AVOID_THRESHOLD 94 /* Sollabstand */ #define MIN_IR 91 /* unterhalb: Annahme, dass Wand weg */ #define MAX_IR 108 /* uberhalb: Zu dicht zum Losfahren */ #define PREG 6 /* Wert fuer den Proportionalregler */ #define WAND_AVRG_NUM 16 /* Durchschnittswertbildung */ #define WAND_AVRG_SHIFT 4 /*** Faehrt den Roboter an der uebergeben Wand *** entlang (LEFT_WALL oder RIGHT_WALL) *** bis sie endet oder der Zielflaeche begegnet *** wird oder timeout ist ***/ void an_der_wand_lang(int wand) { int speedr, speedl; static int avrga[WAND_AVRG_NUM]; int avrgi, cur; int avrg; int i; /* avrg's initialisieren */ cur = (wand==LEFT_WALL)?LEFT_IR+_ldelta:RIGHT_IR; for(i=0; i<WAND_AVRG_NUM; i++) avrga[i] = cur; avrg = cur; avrgi = 0; while((avrg>=MIN_IR) && (BODEN>BODEN_THRESHOLD) && (timertjp<to)) { cur = avrga[avrgi] = (wand==LEFT_WALL)?LEFT_IR+_ldelta:RIGHT_IR; avrgi = (avrgi+1) % WAND_AVRG_NUM; avrg = 0; for(i=0; i<WAND_AVRG_NUM; i++) avrg += avrga[i]; avrg >>= WAND_AVRG_SHIFT; /* zu nahe an der wand */ if(cur > MAX_IR) { speedl = LOW_BW; speedr = LOW_FW; } /* guter abstand zur wand */ else { if(cur > AVOID_THRESHOLD) { speedl = HIGH_FW + (AVOID_THRESHOLD - cur)*PREG; speedr = HIGH_FW; } else if(cur < AVOID_THRESHOLD) { speedl = HIGH_FW; speedr = HIGH_FW - (AVOID_THRESHOLD - cur)*PREG; } else { speedl = HIGH_FW; speedr = HIGH_FW; } } /* routine war urspruenglich fuer die rechte wand, */ /* also jetzt fuer die linke umgekehrt */ if(wand==LEFT_WALL) { motorv(LEFT_MOTOR, speedr); motorv(RIGHT_MOTOR, speedl); } else { motorv(LEFT_MOTOR, speedl); motorv(RIGHT_MOTOR, speedr); } } }