Archiv verlassen und diese Seite im Standarddesign anzeigen : Wie die Bumper richtig ins Programm einbringen?
Morginzez
12.10.2009, 12:00
Hallo.
Ich habe jetzt mal probiert, den RP6 zu programmieren. Eine einfache Strecke mit Kurven ist kein Problem und die passend dazu blinkenden LEDs auch nicht.
Jetzt möchte ich den Roboter aber so einstellen, dass er zurücksetzt, wenn er irgentwo gegen fährt. Ich habe noch keine wirkliche Erfahrung mit "C" und hab das einfach mal versucht, nach bestem Verständnis aus Programm-Schipseln zusammen zusetzen.
LEIDER hat das nicht funktioniert.
Ich weiss, dass das alles doof und falsch ist, könnte mir trotzdem jemand sagen, wie ich den Text ändern muss, damit der Roboter die Bumper WÄHREND seiner "Tour" verwendet?
#include "RP6RobotBaseLib.h"
int main(void)
{
initRobotBase();
setLEDs(0b111111);
mSleep(2500);
powerON();
switch(move_state)
{
case STATE_START:
setLEDs(0b010000);
move_state = STATE_WAIT_FOR_BUMPER_HIT_LEFT;
break;
case STATE_WAIT_FOR_BUMPER_HIT_LEFT:
if(getStopwatch1() > 500)
{
statusLEDs.LED5 = !statusLEDs.LED5;
updateStatusLEDs();
setStopwatch1(0);
}
if(bumper_left)
{
setLEDs(0b011001);
move(50, BWD, DIST_MM(150), NON_BLOCKING);
move_state = STATE_MOVE_BACKWARDS;
}
while(true)
{
setLEDs(0b110110);
move(75, FWD, DIST_MM(900), true);
setLEDs(0b000111);
rotate(50, RIGHT, 90, true);
setLEDs(0b110110);
move(75, FWD, DIST_MM(500), true);
setLEDs(0b111000);
rotate(50, LEFT, 90, true);
setLEDs(0b110110);
move(75, FWD, DIST_MM(1400), true);
setLEDs(0b000111);
rotate(50, RIGHT, 90, true);
setLEDs(0b110110);
move(75, FWD, DIST_MM(1300), true);
setLEDs(0b000111);
rotate(50, RIGHT, 90, true);
setLEDs(0b110110);
move(75, FWD, DIST_MM(1000), true); //MITTE!
setLEDs(0b111111);
rotate(50, RIGHT, 360, true);
setLEDs(0b111011);
move(75, BWD, DIST_MM(1000), true);
setLEDs(0b111000);
rotate(50, LEFT, 90, true);
setLEDs(0b011011);
move(75, BWD, DIST_MM(1300), true);
setLEDs(0b111000);
rotate(50, LEFT, 90, true);
setLEDs(0b011011);
move(75, BWD, DIST_MM(1400), true);
setLEDs(0b000111);
rotate(50, RIGHT, 90, true);
setLEDs(0b011011);
move(75, BWD, DIST_MM(500), true);
setLEDs(0b111000);
rotate(50, LEFT, 90, true);
setLEDs(0b011011);
move(75, BWD, DIST_MM(900), true);
}
return 0;
}
Ja, ich weiss, dass ich mich doof anstelle, aber die Anleitung verrät ja auch nichts -.-
Könntet ihr mir da helfen?
Danke schon mal im Vorraus :D
MfG Tim :D
radbruch
12.10.2009, 14:35
Hallo
Keine Erfahrung hat nichts mit "doof" zu tun. Ich bin auch nicht so das Programmierass:
// Einfaches Fahrprogramm mit Überprüfung der Bumper 12.10.09 mic
// Wegen der Belastung durch den Aufprall ist die Verwendung
// des ACS natürlich besser!
#include "RP6RobotBaseLib.h"
#define test 1 // 0 bedeutet Simulation ohne Motorenansteuerung
#define status_start 0
#define status_fahren 1 // Vorwärtsfahrt mit Überprüfung der Bumpers
#define status_angestossen_links 2
#define status_angestossen_rechts 3
#define status_angestossen_beide 4
uint8_t move_state; // Speicher für die aktuelle Fahrsituation
int main(void)
{
initRobotBase(); // Sollte man immer machen!
setLEDs(0b111111);
mSleep(500);
if(test) powerON(); // Ab jetzt könnte der RP6 losfahren und sich verletzen!
move_state=status_start; // Startstatus setzen
while(true) // Endlos bis Akkus leer
{
switch(move_state)
{
case status_start:
setLEDs(0b011011);
setMotorDir(FWD, FWD);
if(test) moveAtSpeed(150,150);
move_state=status_fahren;
break;
case status_fahren:
setLEDs(0b001001);
do
{
task_Bumpers();
task_motionControl();
if(bumper_left && bumper_right) move_state=status_angestossen_beide;
else if(bumper_left) move_state=status_angestossen_links;
else if(bumper_right) move_state=status_angestossen_rechts;
}while(move_state==status_fahren);
setLEDs(0);
if(test) move(150,100,BWD,1); // Geregelt bremsen und 100 zurückfahren
else mSleep(500); // Simmulation
break;
case status_angestossen_links:
setLEDs(0b010000);
if(test) rotate(150,RIGHT,90,1); // Geregelt drehen
else mSleep(2000);
move_state=status_start;
break;
case status_angestossen_rechts:
setLEDs(0b000010);
if(test) rotate(150,LEFT,90,1);
else mSleep(2000);
move_state=status_start;
break;
case status_angestossen_beide:
setLEDs(0b010010);
if(test) rotate(150,LEFT,180,1);
else mSleep(2000);
move_state=status_start;
break;
}
}
return 0;
}
Ach, jetzt habe das mit der Tour völlig vergessen. Das dauert noch etwas...
Gruß
mic
[Edit]
Jetzt mit Tour, allerdings ist das Ausweichmanöver eher sinnfrei:
// Besseres Fahrprogramm mit Überprüfung der Bumper 12.10.09 mic
// Wegen der Belastung durch den Aufprall ist die Verwendung des ACS
// natürlich besser!
// Die jetzt nichtblockiernden Fahrfunktionen müssen "von Hand" mit der
// task_motionControl()-Funktion solange angestossen werden bis isMovementComplete()
// das Erreichen des Etappenziels signalisiert. Dann wird die Tour weitergeschaltet.
// Sollte während der Fahrt ein Bumper betätigt werden, weicht der RP6 aus.
// Danach setzt setzt er die Fahrt mit dem aktellen Etappenziel fort.
// Allerdings kann ich das alles im Moment nicht testen und weiß deshalb nicht,
// wie die Tour überhaupt aussieht und wohin er sinnvollerweise ausweichen sollte ;)
#include "RP6RobotBaseLib.h"
#define status_fahren 0 // Vorwärtsfahrt mit Überprüfung der Bumper
#define status_angestossen_links 1
#define status_angestossen_rechts 2
#define status_angestossen_beide 3
uint8_t move_state; // Speicher für die aktuelle Fahrsituation
uint8_t tour; // Einzelschritte der Tour
int main(void)
{
initRobotBase(); // Sollte man immer machen!
setLEDs(0b111111);
mSleep(2500);
powerON(); // Ab jetzt könnte der RP6 losfahren und sich verletzen!
move_state=status_fahren; // Startstatus setzen
tour=1; // die Tour beginnt bei Schritt 1
while(true) // Endlos bis Akkus leer
{
if(move_state==status_fahren) switch(tour) // nur wenn kein Ausweichen aktiv
{
case 1: setLEDs(0b110110); move(75, FWD, DIST_MM(900), false);
break;
case 2: setLEDs(0b000111); rotate(50, RIGHT, 90, false);
break;
case 3: setLEDs(0b110110); move(75, FWD, DIST_MM(500), false);
break;
case 4: setLEDs(0b111000); rotate(50, LEFT, 90, false);
break;
case 5: setLEDs(0b110110); move(75, FWD, DIST_MM(1400), false);
break;
case 6: setLEDs(0b000111); rotate(50, RIGHT, 90, false);
break;
case 7: setLEDs(0b110110); move(75, FWD, DIST_MM(1300), false);
break;
case 8: setLEDs(0b000111); rotate(50, RIGHT, 90, false);
break;
case 9: setLEDs(0b110110); move(75, FWD, DIST_MM(1000), false); //MITTE!
break;
case 10: setLEDs(0b111111); rotate(50, RIGHT, 360, false);
break;
case 11: setLEDs(0b111011); move(75, BWD, DIST_MM(1000), false);
break;
case 12: setLEDs(0b111000); rotate(50, LEFT, 90, false);
break;
case 13: setLEDs(0b011011); move(75, BWD, DIST_MM(1300), false);
break;
case 14: setLEDs(0b111000); rotate(50, LEFT, 90, false);
break;
case 15: setLEDs(0b011011); move(75, BWD, DIST_MM(1400), false);
break;
case 16: setLEDs(0b000111); rotate(50, RIGHT, 90, false);
break;
case 17: setLEDs(0b011011); move(75, BWD, DIST_MM(500), false);
break;
case 18: setLEDs(0b111000); rotate(50, LEFT, 90, false);
break;
case 19: setLEDs(0b011011); move(75, BWD, DIST_MM(900), false);
break;
case 20: while(1) // Ende der Tour mit blinken
{setLEDs(0b111000); mSleep(200); setLEDs(0b000111); mSleep(200);}
break;
}
switch(move_state) // Fahren bis Etappenziel oder Ausweichen bei Bumper
{
case status_fahren:
do
{
task_Bumpers();
task_motionControl();
if(bumper_left && bumper_right) move_state=status_angestossen_beide;
else if(bumper_left) move_state=status_angestossen_links;
else if(bumper_right) move_state=status_angestossen_rechts;
}while((move_state==status_fahren) && !isMovementComplete());
if(move_state==status_fahren)
{
tour++; // Etappenziel erreicht, weiterschalten zu nächstem Ziel
// if(tour>19) tour=1 // Neustart der Tour (bei 20 ist Ende!)
}
else // oder bremsen weil ein Bumper betätigt ist
{
setLEDs(0);
move(150,100,BWD,1); // mit Rampen bremsen und 100 zurückfahren
}
break;
case status_angestossen_links:
setLEDs(0b010000);
rotate(150,RIGHT,90,1); // mit Rampen blockierend drehen
move_state=status_fahren;
break;
case status_angestossen_rechts:
setLEDs(0b000010);
rotate(150,LEFT,90,1); // mit Rampen blockierend drehen
move_state=status_fahren;
break;
case status_angestossen_beide:
setLEDs(0b010010);
rotate(150,LEFT,180,1); // mit Rampen blockierend wenden
move_state=status_fahren;
break;
}
}
return 0;
}
[Edit2]
Mit ACS-Vorbereitung:
// Gutes Fahrprogramm mit Überprüfung der Bumper und ACS 12.10.09 mic
// Die nichtblockiernden Fahrfunktionen müssen "von Hand" mit der
// task_motionControl()-Funktion solange angestossen werden bis isMovementComplete()
// das Erreichen des Etappenziels signalisiert. Dann wird die Tour weitergeschaltet.
// Sollte während der Fahrt ein Bumper betätigt werden oder das ACS ansprechen,
// weicht der RP6 aus.
// Danach setzt setzt er die Fahrt mit dem aktellen Etappenziel fort.
// Allerdings kann ich das alles im Moment nicht testen und weiß deshalb nicht,
// wie die Tour überhaupt aussieht und wohin er sinnvollerweise ausweichen sollte ;)
#include "RP6RobotBaseLib.h"
#define status_fahren 0 // Vorwärtsfahrt mit Überprüfung der Bumper
#define status_angestossen_links 1
#define status_angestossen_rechts 2
#define status_angestossen_beide 3
#define status_ACS_links 4
#define status_ACS_rechts 5
#define status_ACS_beide 6
uint8_t move_state; // Speicher für die aktuelle Fahrsituation
uint8_t tour; // Einzelschritte der Tour
int main(void)
{
initRobotBase(); // Sollte man immer machen!
setLEDs(0b111111);
mSleep(2500);
powerON(); // Ab jetzt könnte der RP6 losfahren und sich verletzen!
setACSPwrMed(); // mittelweites ACS aktivieren
move_state=status_fahren; // Startstatus setzen
tour=1; // die Tour beginnt bei Schritt 1
while(true) // Endlos bis Akkus leer
{
if(move_state==status_fahren) switch(tour) // nur wenn kein Ausweichen aktiv
{
case 1: setLEDs(0b110110); move(75, FWD, DIST_MM(900), false);
break;
case 2: setLEDs(0b000111); rotate(50, RIGHT, 90, false);
break;
case 3: setLEDs(0b110110); move(75, FWD, DIST_MM(500), false);
break;
case 4: setLEDs(0b111000); rotate(50, LEFT, 90, false);
break;
case 5: setLEDs(0b110110); move(75, FWD, DIST_MM(1400), false);
break;
case 6: setLEDs(0b000111); rotate(50, RIGHT, 90, false);
break;
case 7: setLEDs(0b110110); move(75, FWD, DIST_MM(1300), false);
break;
case 8: setLEDs(0b000111); rotate(50, RIGHT, 90, false);
break;
case 9: setLEDs(0b110110); move(75, FWD, DIST_MM(1000), false); //MITTE!
break;
case 10: setLEDs(0b111111); rotate(50, RIGHT, 360, false);
break;
case 11: setLEDs(0b111011); move(75, BWD, DIST_MM(1000), false);
break;
case 12: setLEDs(0b111000); rotate(50, LEFT, 90, false);
break;
case 13: setLEDs(0b011011); move(75, BWD, DIST_MM(1300), false);
break;
case 14: setLEDs(0b111000); rotate(50, LEFT, 90, false);
break;
case 15: setLEDs(0b011011); move(75, BWD, DIST_MM(1400), false);
break;
case 16: setLEDs(0b000111); rotate(50, RIGHT, 90, false);
break;
case 17: setLEDs(0b011011); move(75, BWD, DIST_MM(500), false);
break;
case 18: setLEDs(0b111000); rotate(50, LEFT, 90, false);
break;
case 19: setLEDs(0b011011); move(75, BWD, DIST_MM(900), false);
break;
case 20: while(1) // Ende der Tour mit blinken
{setLEDs(0b111000); mSleep(200); setLEDs(0b000111); mSleep(200);}
break;
}
switch(move_state) // Fahren bis Etappenziel oder Ausweichen bei Bumper oder ACS
{
case status_fahren:
do
{
task_ACS();
task_Bumpers();
task_motionControl();
if(bumper_left && bumper_right) move_state=status_angestossen_beide;
else if(bumper_left) move_state=status_angestossen_links;
else if(bumper_right) move_state=status_angestossen_rechts;
if(obstacle_left && obstacle_right) move_state=status_ACS_beide;
else if(obstacle_left) move_state=status_ACS_links;
else if(obstacle_right) move_state=status_ACS_rechts;
}while((move_state==status_fahren) && !isMovementComplete());
if(move_state==status_fahren)
{
tour++; // Etappenziel erreicht, weiterschalten zu nächstem Ziel
// if(tour>19) tour=1 // Neustart der Tour (bei 20 ist Ende!)
}
else // oder bremsen weil ein Bumper betätigt ist
{
setLEDs(0);
move(150,100,BWD,1); // mit Rampen bremsen und 100 zurückfahren
}
break;
case status_angestossen_links:
setLEDs(0b010000);
rotate(150,RIGHT,90,1); // mit Rampen blockierend drehen
move_state=status_fahren;
break;
case status_angestossen_rechts:
setLEDs(0b000010);
rotate(150,LEFT,90,1); // mit Rampen blockierend drehen
move_state=status_fahren;
break;
case status_angestossen_beide:
setLEDs(0b010010);
rotate(150,LEFT,180,1); // mit Rampen blockierend wenden
move_state=status_fahren;
break;
case status_ACS_links:
break;
case status_ACS_rechts:
break;
case status_ACS_beide:
break;
}
}
return 0;
}
Macht Spass :)
Morginzez
12.10.2009, 16:15
Soooo... Sorry, dass ich erst jetzt antworten kann.
Aber: WOOOOOOW!!!
Fettes Danke! Da scheint ech sau viel Arbeit drin zu stecken!!!
Danke, danke, danke, dankeee!!!
Coole Sache.
Also, ich brauche dieses AusweichSystem, weil sich der Roboter immer ein wenig zu weit dreht... Ich muss die genaue Zahl, damit er sich dann 90° dreht, noch herausfinden... Wird wohl bei 85 oder 87 oder so liegen. Muss ich halt noch herausfinden. Das ACS sorgt dann dafür, dass er nicht wieder vor eine Wand fährt. Eigentlich wollte ich das ja mit den Bumpern bewerkstelligen, aber mit dem ACS ist es natürlich noch viel besser.
Außerdem kann man das ACS (Anti-Collision-System, oder?) ja auch später noch einsetzen. Beispielsweise dann bei einer Aufgabe, wie: Wenn Hindernis, dann anhalten und "PIEP" machen (Ich hab noch vor, einen kleiner Pieper, der bei meinem PC-Case dabei war, anzuschliessen. Wo, weiss ich noch nicht, aber ich bekomm das i-wie hin, sonst frag ich halt noch mal.).
AUßERDEM: Danke für die deutschen Anmerkungen. Es ist viieeel leichter als mit den Englischen. :D =D>
Aber eine Frage noch: Wie arbeitet das ACS? Kann es erkennen, wie weit es noch bis irgentwohin ist, oder merkt es "nur", dass da was kommt? Und auf welcher Basis läuft das? Also, so wie bei einer Fledermaus, bloss mit irgentwelchen Lichtsignalen?
Jaja... Ich hab keine Ahnung von Robotik.. Macht bis jetzt aber sau viel Spass :D
MfG Tim
Und wirklich: DANKE! :D =D>
radbruch
12.10.2009, 16:36
Hallo
Immer gerne. Funktionert es überhaupt? Wie geschrieben kann ich es selbst im Moment nicht testen.
Bei der Wegmessung wird es durch den Schlupf immer Abweichungen geben. In der Datei RP6Config.h kann man seinen RP6 kalibrieren damit 90° auch wirklich 90° sind.
Das ACS arbeitet in drei Stufen, man kann also drei Abstandsbereiche damit unterscheiden. Zusätzlich kann das ACS ebenfalls in der Datei RP6Config.h an eigene Ansprüche angepasst werden. (Allerdings nur bei den aktuellen Versionen der Library von der arexx-RP6-HP (http://arexx.com/rp6/))
Updates der Lib und ACS-Einstellungen:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=32840
Encoder Wegstrecken kalibrieren:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=36651
ACS, Encorder und mehr Hardware:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=32141
Das sind nur ein paar Beispiele die ich auf die Schnelle zusammengesucht habe.
Gruß
mic
Morginzez
12.10.2009, 16:44
Danke nochmal :D Um dir zu sagen, wohin der Roboter fährt: Er fährt neben meinem Rechner los, bis kurz vor meinen Schrank. Dann nach rechts, bis zu Tür, dann nach links und auf den Flur. Da wieder rechts und dann gradeaus, bis zur Tür von meinem Bro. Dann wieder rechts und ins Zimmer von ihm :D
EDIT:
Langsam fange ich an, das zu schnallen. Jedenfalls einen Teil.
Was kann dieses #define Käsekuchen 3 oben immer? Und wieso funktioniert der befehl: status_angstossen_links? Ist das Teil von "c"???
Edit von radbruch:
schau mal hier: http://tinyurl.com/yz5lbyf
Aufrege-Edit:
Ja, ich weiss, dass es Google gibt. Aber wenn man die Frage persönlich stellt, dann kann man auch wieder nachfragen, falls etwas noch nicht klar ist. Sonst gäbe es NUR Schulbücher und keine Lehrer.
Und wenn man für alles Google nehmen würde, dann wären solche Foren grösstenteils unnütz. Man müsste natürlich erstmal alles Wissen ins Netz stellen, aber dann wären sie unnütz.
Aber, jetzt weiss ich, was ich gesucht habe :D
Abrege-Edit von radbruch:
Solche Foren wollen in erster Linie dann helfen, wenn selbst google ratlos ist oder sein Wissen so gut versteckt, dass es nur mit großem Aufwand gefunden werden kann. Für mich war der Zeitaufwand mit dem lmdfdg (http://lmdfdg.de)-Link geringer als einen der gefundenen Artikel nachzuschreiben *zwinker*
Viel Spaß noch
Weiter-Chat-Edit: :D:D Ja... Ich hab das jetzt alles soweit hinbekommen.... Morgen seh ich dann weiter ;D
Morginzez
13.10.2009, 20:08
Huhu nochmal!
So. Ich glaube, das ist eine neue Antwort und keinen Edit wert. Ich habe jetzt, mit Hilfe von Radbruchs so freundlicher Weise geschriebenen Programm, ein Eigenes "entwickelt". Es ist nach wie vor nicht sehr komplex. Aber ich bin, dafür das ich mich seit zwei Tagen damit beschäftige und auch noch andere Dinge zu tun habe/ Hobbys ausüben möchte, sehr zufrieden damit. Dadurch, dass ich das Programm von dir immer abgeschrieben und nicht etwa Copy&Paste angewandt hätte, habe ich die einzelnen Schritte besser verstanden und kann sie nun auch selber weitestgehend verwenden. Kleine Rechtschreibfehler hier und da sind noch drin, aber ich bessere mich. Und einige Denk- und Strukturfehler im Programm habe ich auch noch, aber in meinem heutigen "Werk" ist kein Fehlercode mehr enthalten und es macht auch weitestgehend, was ich mir gewünscht habe.
//Erste eigene Tour, die vom PC zum Schlafzimmer und zurück führt.
//Mit Einsatz von ACS und Bumpern.
//Bumper nur als Sicherung, falls Hinderniss vom ACS nicht erkannt wird.
#include "RP6RobotBaseLib.h"
#define status_fahren 0 // Vorwärtsfahrt mit Überprüfung der Bumper
#define status_angestossen_links 1
#define status_angestossen_rechts 2
#define status_angestossen_beide 3
#define status_ACS_links 4
#define status_ACS_rechts 5
#define status_ACS_beide 6
uint8_t move_state;
uint8_t tour;
int main(void)
{
initRobotBase(); //Microcontroller an.
setLEDs(0b111111); //LEDs fangen alle an zu leuchten.
mSleep(2500); //Er wartet 2500 Zeiteinheiten. --> Was ist eine Zeiteinheit in Sekunden?
powerON(); //Ab jetzt ist der Roboter an und die Gefahr eines Unfalls besteht.
setACSPwrLow(); //Geringes ACS aktiviert.
move_state=status_fahren; //Startstatus setzen.
tour=1; //Tour beginnt bei Schritt1.
while(true) //Endlos bis der Akku leer ist.
{
if(move_state==status_fahren) switch(tour) //Wenn kein Ausweichen aktiv. Was bedeutet das? -->Ausweichfunktion?
{
case 1: setLEDs(0b110110); move(100, FWD, DIST_MM(4000), false);
break;
case 2: setLEDs(0b000111); rotate(100, RIGHT, 90, false);
break;
case 3: setLEDs(0b110110); move(100, FWD, DIST_MM(2000), false);
break;
case 4: setLEDs(0b111000); rotate(100,LEFT,90, false);
break;
case 5: setLEDs(0b110110); move(100, FWD, DIST_MM(1000), false);
break;
case 6: setLEDs(0b101010); rotate(100, LEFT, 360, false);
break;
case 7: setLEDs(0b010101); rotate(100, RIGHT,360, false);
break;
case 8: while(1) //Ende der Tour mit Blinken.
{setLEDs(0b001001); mSleep(200); setLEDs(0b010010); mSleep(200); setLEDs(0b100100); //Beide "Lichterzeilen" blinken auf und ab.
setLEDs(0b001001); mSleep(200); setLEDs(0b010010); mSleep(200); setLEDs(0b100100);}
break;
}
switch(move_state) //Fahren bis Etappenziel oder ausweichen, wenn ACS oder Bumper anschlägt.
{
case status_fahren:
do
{
task_ACS();
task_Bumpers();
task_motionControl();
if(bumper_left && bumper_right) move_state=status_angestossen_beide; //Wenn beide Bumper, dann mach "status_angstossen_beide".
else if(bumper_left) move_state=status_angestossen_links; //Dasselbe mit links.
else if(bumper_right) move_state=status_angestossen_rechts;//Dasselbe mit rechts.
if(obstacle_left && obstacle_right) move_state=status_ACS_beide; //Dasselbe wie oben, nur mit dem ACS.
else if(obstacle_left) move_state=status_ACS_links;
else if(obstacle_right) move_state=status_ACS_rechts;
}while((move_state==status_fahren) && !isMovementComplete());
if(move_state==status_fahren)
{
tour++;
//Neustart der Tour. Bei 10 ist Ende.
}
else
{
setLEDs(0b111111);
move(150,100,BWD,1); //Mit Rampen bremsen und 100 zurückfahren.
}
break;
//Die einzelnen Möglichkeiten:
case status_angestossen_links:
setLEDs(0b101101);
rotate(150,RIGHT,90,1);
move_state=status_fahren;
break;
case status_angestossen_rechts:
setLEDs(0b101101);
rotate(150,LEFT,90,1);
move_state=status_fahren;
break;
case status_angestossen_beide:
setLEDs(0b101101);
rotate(150,LEFT,180,1);
move_state=status_fahren;
break;
case status_ACS_links:
setLEDs(0b101101);
rotate(150,RIGHT,90,1);
move_state=status_fahren;
break;
case status_ACS_rechts:
setLEDs(0b101101);
rotate(150,LEFT,90,1);
move_state=status_fahren;
break;
case status_ACS_beide:
setLEDs(0b101101);
rotate(150,RIGHT,180,1);
break;
}
}
return 0;
}
Der Roboter fährt die Strecke und versucht auszuweichen, sobald ein Hinderniss auftaucht. Aber grade hier gibt es Probleme. Der Roboter erkennt zwar alles richtig und kann auch ziemlich richtig agieren. Jedoch verfranst er sich dann an dieser Stelle des Programms. Wenn z.B. eine Wand als Hinderniss kommt (weil ich den Roboter am Start ein wenig falsch abgestellt habe ](*,) ), dann weicht er, wie gewünscht, z.B. nach Links aus. Jedoch versucht er dann ja den Teil seiner Tour wieder auszuführen, was aber dazu führt, dass ein weiteres Hinderniss erkannt wird, weil er ja woanders hingefahren ist, als geplant. Diesem will er wieder ausweichen und fährt noch "falscher". Und dann wieder und wieder und wieder... Bis er irgentwann in einer Ecke hängt und sich im Kreis dreht -.-
LEIDER nicht der gewünschte Effekt.
Jetzt: Was kann ich tun? Gibt es eine Möglichkeit, den Roboter vielleicht wieder auf die "richtige Bahn" zu bringen?
Wäre euch sehr verbunden.
Es genügt mir auch schon, wenn mir ein "Denk-anstoss" gegeben wird, sodass ich noch selber denken muss. Mag ich nicht so gerne, aber manchmal muss man das ja auch :D
MfG Tim
radbruch
13.10.2009, 22:23
Hallo
Das war ja eigentlich zu erwarten. Das erste große Problem ist das sture Ausweichmanöver. Der RP6 müßte mehr an die jeweilige Situation angepasst reagieren. Hier könnte man im Ausweichmanöver den jeweiligen Schritt der Tour (zufällig sind die move() ungerade und die rotate() gerade Schritte ;) berücksichtigen. Vermutlich treten die meisten Kollisionen aber bei Fahren auf. Dann weiß man aber nicht, wo eigentlich der Fehler aufgetreten war, was weiter zur Verirrung führt.
Das zweite große Problem ist die sture Wiederholung der aktuellen Etappe nach dem Ausweichen, unabhängig vom schon zurückgelegeten Weg. Hier könnte man in den Untiefen der Motion-Controll-Task zwar die aktuellen Zwischenwerte erkunden und als Startparameter für die Weiterfahrt verwenden. Letztlich werden aber auch hier wieder Fehler auftreten die sich zu weiteren Kursabweichungen summieren werden.
Eine Zwischenlösung wäre vielleicht, das Ausweichmanöver direkt im Tourschritt mit anzugeben:
// Guteres Fahrprogramm mit Überprüfung der Bumper und ACS 13.10.09 mic
// Neu sind nun individuelle Ausweichmanöver bei den einzelnen Touretappen.
#include "RP6RobotBaseLib.h"
#define status_fahren 0 // Vorwärtsfahrt mit Überprüfung der Bumper
#define status_angestossen_links 1
#define status_angestossen_rechts 2
#define status_angestossen_beide 3
#define status_ACS_links 4
#define status_ACS_rechts 5
#define status_ACS_beide 6
uint8_t move_state; // Speicher für die aktuelle Fahrsituation
uint8_t tour; // Einzelschritte der Tour
uint8_t ausweich_winkel; // Drehwinkel bei Kurskorrektur
uint16_t ausweich_weg; // Zurückfahrstrecke bei Kollisition
int main(void)
{
initRobotBase(); // Sollte man immer machen!
setLEDs(0b111111);
mSleep(2500);
powerON(); // Ab jetzt könnte der RP6 losfahren und sich verletzen!
setACSPwrMed(); // mittelweites ACS aktivieren
move_state=status_fahren; // Startstatus setzen
tour=1; // die Tour beginnt bei Schritt 1
while(true) // Endlos bis Akkus leer
{
if(move_state==status_fahren) switch(tour) // nur wenn kein Ausweichen aktiv
{
case 1: setLEDs(0b110110); move(75, FWD, DIST_MM(900), false);
ausweich_weg=30; ausweich_winkel=20; // Ausweichen: 30 zurück, 20 drehen
break;
case 2: setLEDs(0b000111); rotate(50, RIGHT, 90, false);
ausweich_weg=30, ausweich_winkel=60;
break;
case 3: setLEDs(0b110110); move(75, FWD, DIST_MM(500), false);
ausweich_weg=600; ausweich_winkel=0; // nur zurück, kein drehen!
break;
case 4: setLEDs(0b111000); rotate(50, LEFT, 90, false);
ausweich_weg=50, ausweich_winkel=20; // gilt für den Rest der Tour!
break;
case 5: setLEDs(0b110110); move(75, FWD, DIST_MM(1400), false);
break;
case 6: setLEDs(0b000111); rotate(50, RIGHT, 90, false);
break;
case 7: setLEDs(0b110110); move(75, FWD, DIST_MM(1300), false);
break;
case 8: setLEDs(0b000111); rotate(50, RIGHT, 90, false);
break;
case 9: setLEDs(0b110110); move(75, FWD, DIST_MM(1000), false); //MITTE!
break;
case 10: setLEDs(0b111111); rotate(50, RIGHT, 360, false);
break;
case 11: setLEDs(0b111011); move(75, BWD, DIST_MM(1000), false);
break;
case 12: setLEDs(0b111000); rotate(50, LEFT, 90, false);
break;
case 13: setLEDs(0b011011); move(75, BWD, DIST_MM(1300), false);
break;
case 14: setLEDs(0b111000); rotate(50, LEFT, 90, false);
break;
case 15: setLEDs(0b011011); move(75, BWD, DIST_MM(1400), false);
break;
case 16: setLEDs(0b000111); rotate(50, RIGHT, 90, false);
break;
case 17: setLEDs(0b011011); move(75, BWD, DIST_MM(500), false);
break;
case 18: setLEDs(0b111000); rotate(50, LEFT, 90, false);
break;
case 19: setLEDs(0b011011); move(75, BWD, DIST_MM(900), false);
break;
case 20: while(1) // Ende der Tour mit blinken
{setLEDs(0b111000); mSleep(200); setLEDs(0b000111); mSleep(200);}
break;
}
switch(move_state) // Fahren bis Etappenziel oder Ausweichen bei Bumper oder ACS
{
case status_fahren:
do
{
task_ACS();
task_Bumpers();
task_motionControl();
// erst ACS und dann Bumpers prüfen,
if(obstacle_left && obstacle_right) move_state=status_ACS_beide;
else if(obstacle_left) move_state=status_ACS_links;
else if(obstacle_right) move_state=status_ACS_rechts;
// weil Bumper eine höhere Priorität haben!
if(bumper_left && bumper_right) move_state=status_angestossen_beide;
else if(bumper_left) move_state=status_angestossen_links;
else if(bumper_right) move_state=status_angestossen_rechts;
}while((move_state==status_fahren) && !isMovementComplete());
if(move_state==status_fahren)
{
tour++; // Etappenziel erreicht, weiterschalten zu nächstem Ziel
// if(tour>19) tour=1 // Neustart der Tour (bei 20 ist Ende!)
}
else // oder bremsen weil ein Bumper betätigt ist
{
setLEDs(0);
stop(); // sofort anhalten und nochmals Bumpers prüfen
if(bumper_left && bumper_right) move_state=status_angestossen_beide;
if(move_state < status_ACS_links) // bei Bumper doppelte Ausweichwerte
{
ausweich_weg = ausweich_weg*2; // (0 bleibt 0 :)
ausweich_winkel = ausweich_winkel*2; // Winkel ist nur uint8_t!
}
if(ausweich_weg) // nur wenn zurückfahren nötig ist
move(150,BWD,DIST_MM(ausweich_weg),1); // zurückfahren
}
break;
case status_angestossen_links: // drehen wenn nötig (lang)
setLEDs(0b011000);
if(ausweich_winkel) // nur wenn ein Winkel angegeben ist
rotate(100,RIGHT,ausweich_winkel,1); // wird auch wirklich gedreht
move_state=status_fahren;
break;
case status_angestossen_rechts:
setLEDs(0b000011);
if(ausweich_winkel)
rotate(100,LEFT,ausweich_winkel,1);
move_state=status_fahren;
break;
case status_angestossen_beide: // zweimal ausweichen! (lang)
setLEDs(0b011011);
if(ausweich_winkel)
rotate(100,RIGHT,ausweich_winkel,1);
if(ausweich_weg) // wenn beide Seiten gedrückt sind flüchten wir
move(150,BWD,DIST_MM(ausweich_weg),1);
if(ausweich_winkel)
rotate(100,LEFT,ausweich_winkel,1);
move_state=status_fahren;
break;
case status_ACS_links: // drehen wenn nötig (kurz)
setLEDs(0b010000);
if(ausweich_winkel)
rotate(100,RIGHT,ausweich_winkel,1);
move_state=status_fahren;
break;
case status_ACS_rechts: // drehen wenn nötig
setLEDs(0b000010);
if(ausweich_winkel)
rotate(100,LEFT,ausweich_winkel,1);
move_state=status_fahren;
break;
case status_ACS_beide: // zweimal ausweichen! (kurz)
setLEDs(0b010010);
if(ausweich_winkel)
rotate(100,RIGHT,ausweich_winkel,1);
if(ausweich_weg)
move(150,BWD,DIST_MM(ausweich_weg),1);
if(ausweich_winkel)
rotate(100,LEFT,ausweich_winkel,1);
move_state=status_fahren;
break;
}
}
return 0;
}
Kommentare sollten möglichst sinnvoll sein, wenn sich die Aktion durch den Befehl selbst erklärt, kann man ihn auch einsparen. Wenn möglich sollten sie aber in der Codebox (Vorschau) nicht über das Zeilenende hinausragen, denn dann kann man den Code nicht mehr richtig kopieren. Deshalb, und weil ich den Code noch besser kenne, habe ich die Änderungen in meiner Programmversion eingefügt.
Gruß
mic
[Edit]
Nachdem nun mein RP6 auch wieder läuft habe ich a: den move()-Befehl beim Zurückstossen korrigiert, b: die etappenabhängigen Ausweichmanöver "weicher" und kleiner gemacht und c: festgestellt, dass es unmöglich ist, ACS oder Bumper auf beiden Seiten gleichzeitig zu betätigen, und letztlich d: die Abfrage von ACS und Bumpers getauscht. Der Code oben wurde deshalb entsprechend angepasst.
Morginzez
14.10.2009, 09:02
Okay.. Danke... Ich schreibe erstmal diese kleine Antwort. Das mit den Selbsterklärenden Anmerkungen ist natürlich ein wenig "unglücklich" aber die brauche ich, weil ich das so viel leichter verstehen kann. Mach ich im Englischunterricht ja auch so. Wenn ich was nicht weiss, dann guck ich es nach und schreibs an den Rand daneben, falls ich das Wort beim nächsten mal lesen immer noch nicht weiss :D Aber ich kann ja versuchen, eine kommentierte und eine unkommentierte Fassung zu machen, so wie die in der Anleitung.
Wieder: Danke für das Programm, dass ich zwar noch nicht ausprobiert habe, aber dass du ja freundlicherweise geschrieben hast, obwohl ich das ja gar nicht verlangt habe. Du scheinst ziemlich viel Zeit in meine "Anfangsprobleme" zu investieren, wofür ich äusserst dankbar bin. In so einer Nachricht hier kann ich natürlich nicht richtig ausdrücken, dass mich das wirklich unglaublich freut, dass jemand so auf meine Fragen eingeht, wie ich es in kaum einem anderen Forum erlebt habe. Hier sind keine sinnloses "Post-Counter-Hoch-Push-Antworten" ständig drin und deine Hilfe ist wirklich SEHR zielgerichtet und verständlich formuliert.
Danke nochmal.
MfG Tim, der jetzt Programme lesen geht :D
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.