PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Labyrinth_programm



µcFlo
28.04.2012, 23:22
Hi,
ich will mit meinem Freund eine Asuro so programieren, dass er durch ein Labyrinth findet. Das Labyrinth hat mehrere Wege und die Rechte-hand-Methode kann nicht angewand werden, da es passieren kann,dass er nurnoch im Kreis fährt.

Der Freund hatte die Idee, dass man den Robo ein Koordinatensystem anlegen lassen soll. Doch dies ist führ zwei absolute C anfänger sehr schwer, auserdem kann der Robo keine Strecken messen und der Speicher ist nicht groß genug.

Vieleicht könntet ihr mir ein Paar Anregungen geben.

Danke

Hubert.G
29.04.2012, 10:36
Die einfachste Methode ist, das Rechtsabbiegen mitzählen. Nach vier mal rechts kommt man wahrscheinlich wieder zum ersten mal rechts. Dann entweder gerade aus fahren oder links. Sollte sich programmtechnisch leicht lösen lassen.

PICture
29.04.2012, 18:00
Hallo!

@ µcFlo

Am einfachsten ist sich immer entlang einer Wand zu bewegen (siehe dazu: http://de.wikipedia.org/wiki/L%C3%B6sungsalgorithmen_f%C3%BCr_Irrg%C3%A4rten#Al gorithmus_von_Gaston_Tarry . ;)

Gonzo22
30.04.2012, 02:19
Hier gibt es was :
http://ornella.iwr.uni-heidelberg.de/ROBOTICSLAB/ROBPROJECTS/COMPLETED/ASURO_LABY/D/index.html

Könnte genau das sein was Du suchst

danimath
30.04.2012, 08:53
Moin µcFlo,

Hi,
...
Der Freund hatte die Idee, dass man den Robo ein Koordinatensystem anlegen lassen soll. Doch dies ist führ zwei absolute C anfänger sehr schwer, auserdem kann der Robo keine Strecken messen und der Speicher ist nicht groß genug.
...


Ein Koordinatensystem ist für ein Labyrinth zu viel. I.Allg. braucht man das nicht, weil Du nur den Zusammenhang zwischen zwei Punkten im Labyrinth brauchst; also z.B. von Kruezung 12 geht's zu Kreuzung 14 und Kreuzung 23, etc. Such mal mit der Suchmaschine Deines Vertrauens (meine ist nicht google :twisted:) nach "Backtracking" oder "Tiefensuche".

viele Grüße
Andreas

µcFlo
30.04.2012, 11:11
Danke an alle die geantwortet haben, ich werde mir die verschieden Tipps mal zu Gemüte führen.


Danke

Virtuelx
05.05.2012, 11:55
Du kannst einen rekursiven Labyrinthalgorithmus verwenden, der ist relativ leicht zu implementieren, sofern du weisst wie Rekursion funktioniert. Da du sagst dass du dich in C wenig auskennst, nehme ich an dass du auch nicht weisst wie man Rekursionen verwenden kann. Also informiere dich vielleicht erstmal was Rekursion bedeutet und wo/wie man es einsetzt.
Kurz zur Erklärung: Die Idee ist es das Labyrinth als Spielfeld(2D-Array) anzulegen und alle möglichen Wege(Nord/Süd/Ost/West) durchzulaufen und auf jedem Feld eine Markierung(im 2D-Array) zu hinterlassen, das solange bis du dein gewünschtes Ziel erreicht hast.
Allerdings weiss ich nicht ob Rekursionen auf deinem µC erlaubt/möglich sind und ob der Speicherplatz dafür reicht. Sollte das nicht der Fall sein könntest du z.B.: alle Berechnungen auf einem PC durchführen lassen und beide über eine Schnittstelle(WLAN, etc.) kommunizieren lassen.
Hier noch ein Link der dir vielleicht hilft: http://www.cs.bu.edu/teaching/alg/maze/

Philipp2195
25.07.2012, 17:35
Hi,

Ich will den ASURO mithilfe der Taster durch ein einfaches Labyrinth führen. Dazu will ich ihn so programmieren, dass er zunächst immer gerade aus fährt bis er gegen eine Wand fährt und die Taster gedrückt werden. Anschließend soll er dann ein kleines Stück rückwärts fahren und sich um 90 grad in die eine Richtung drehen. Stößt er dann nicht erneut gegen eine Wand soll er gerade aus weiterfahren; andernfalls soll er sich wieder um 180 grad zurück drehen und seine fahrt fortsetzen. Da ich aber im Programmieren ein Anfänger bin, fällt mir das sehr schwer. Kann mir jemand von euch vielleicht einen grundsätzlichen Ansatz für diese Problematik nennen. Mir geht es dabei weniger um die exakte Drehung um 90 grad, sondern vielmehr um die Umsetzung dieses Algorithmus programmtechnisch

Liebe Grüße Philipp

Virtuelx
28.07.2012, 11:48
Hallo,

kenne mich leider nicht mit dem ASURO aus aber ein einfacher algorithmischer Ansatz in Pseudocode könnte etwa so aussehen:



Fahren(vorwärts, 999); //fahre vorwärts für 999 sekunden
while(1){ //tue das unendlich (bzw hier könnte die Bedingung reinkommen wann er das Zeil erreicht hat)
if(Taster == 1){ //Wand entdeckt!
Fahren(rückwärts,1); //fahre rückwärts für 1 sekunde
Drehen(90); //90° drehung
Fahren(vorwärts, 1); //fahre vorwärts für 1 sekunde (um zu prüfen ob noch eine wand da ist)
if(Taster == 1){ //2. wand entdeckt! -> umdrehen
Fahren(rückwärts,1);
Drehen(180);
Fahren(vorwärts, 999);
}
}
}


Was für einen Sensor zum entdecken der Wand benutzt du genau, ich nehme an sowas in der Art (http://www.rn-wissen.de/index.php/Sensorarten#Bumpers) ?

radbruch
05.09.2012, 16:38
Hallo

Das return() befindet sich innerhalb der deshalb nicht mehr endlosen while-Schleife:

#include "asuro.h"

int grad=0;

int main(void)
{

Init();
while(1)
{

if(PollSwitch()==0)
{
MotorDir(FWD,FWD);
MotorSpeed(100,100);
}
else if(PollSwitch()!=0)
{
if(grad==0)
{
MotorDir(FWD,FWD);
MotorSpeed(100,0);
Msleep(200);
grad = 1 ;
}
}
else if(PollSwitch()!=0 && grad==1)
{
if(grad==1)
{
MotorDir(FWD,FWD);
MotorSpeed(0,100);
Msleep(400);
grad = 0 ;
}
}

return 0;
}
}

Ich würde es vielleicht so formulieren:

#include "asuro.h"

int grad=0;

int main(void)
{
Init();
while(1)
{
if(PollSwitch()==0)
{
StatusLED(GREEN);
MotorSpeed(100,100);
}
else
{
if(grad==0)
{
StatusLED(RED);
MotorSpeed(100,0);
Msleep(200);
grad = 1;
}
else
{
StatusLED(YELLOW);
MotorSpeed(0,100);
Msleep(400);
grad = 0;
}
}
}
return 0;
}(ungetestet)

Der Ansatz erscheint mir etwas zu einfach.

Gruß

mic

Philipp2195
13.10.2012, 15:30
Hallo danke für eure Antworten!

Ich habe mittlerweile ein eigenes Programm geschrieben, dass prinzipiell funktioniert.

Mein Programm sieht folgendermaßen aus:


#include "asuro.h"

int main(void) {
Init();
int i;
int grad=0;
while(1) {

if(PollSwitch()==0) {
MotorDir(FWD,FWD);
MotorSpeed(130,117);

}

else if(PollSwitch()!=0) {

if (grad==0){

MotorDir(BREAK,BREAK);
MotorDir(RWD,RWD);
MotorSpeed(100,100);
for ( i=0 ; i<=220 ; i++)
{ Sleep (5000); }
MotorDir(RWD,FWD);
MotorSpeed(110,110);

for ( i=0 ; i<=150 ; i++ )
{ Sleep ( 5000 ); }
grad = 1;
}


else if (grad==1) {
MotorDir(BREAK,BREAK);
MotorDir(RWD,RWD);
MotorSpeed(100,100);
for ( i=0 ; i<=220 ; i++)
{ Sleep (5000); }
MotorDir(FWD,RWD);
MotorSpeed(110,110);

for ( i=0 ; i<=340 ; i++ )
{ Sleep ( 5000 ); }
grad = 0;
}

}




}
return 0;
}


Ich bin aber noch nicht ganz zufrieden mit dem Programm. Mir wäre es am liebsten, dass sich ASURO sozusagen nicht abwechselnd(wie bei diesem Programm) dreht, sondern dass er an Jeder ecke wieder mit dem linksdrehen anfängt. denn bei dem jetztigem programm kommt es öfters vor, dass der ASURO wieder durch den Beginn des Labyrinths herausfährt. Ist mein Anliegen einigermaßen verständlich?

Kann mir von euch jemand weiter helfen. hab schon einiges probiert aber bin auf kein ergebnis gekommen.

Gruß Philipp

P.S im anhang befindet sich das programm in besserer Form

Philipp2195
13.10.2012, 15:56
ASURO soll also geradeausfahren solange er gegen keine wand fährt. ist dies dann doch der fall, soll er zunächst 90 ° links drehen und schauen ob dort auch eine wand ist. ist dort keine wand soll er seine fahrt fortsetzten und bei der nächsten wand das selbe tun. ist dort aber eine wand soll er sich um 180 ° in die andere Richtung drehen, seine Fahrt fortsetzten und bei der nächsten wand aber wieder mit dem linksdrehen beginnen.

radbruch
14.10.2012, 13:20
Hallo

Nur zeitgesteuert (und ungetestet!) ist das eine echte Herausforderung:


#include "asuro.h"

#define BWD RWD // Rückwards bedeutet Backwards
#define pwm_links 130
#define pwm_rechts 117

void Msleep_(uint16_t pause) // Funktion muss bei Libs mit 36kHz entfernt werden!
{
if(pause) while(pause--) Sleep(72);
}

uint8_t taste(void)
{
uint8_t t1, t2;
t1=PollSwitch();
t2=PollSwitch();
if(t1==t2) return(t1); // Wert gültig
return(0);
}

void vorwaerts(void)
{
StatusLED(GREEN);
MotorSpeed(pwm_links, pwm_rechts);
MotorDir(FWD,FWD);
}

void bremsen(void)
{
StatusLED(RED);
BackLED(OFF, OFF);
MotorSpeed(0,0);
MotorDir(BREAK, BREAK);
Msleep(50); // Bremszeit bis zum Stillstand
}

void rueckwaerts(void)
{
BackLED(ON, ON);
MotorSpeed(pwm_links, pwm_rechts);
MotorDir(BWD,BWD);
Msleep(500);
}

void linksdrehen(void)
{
BackLED(ON, OFF);
MotorSpeed(pwm_links, pwm_rechts);
MotorDir(BWD,FWD);
Msleep(300); // Zeit für 90°
bremsen();
}

void rechtsdrehen(void)
{
BackLED(OFF, ON);
MotorSpeed(pwm_links, pwm_rechts);
MotorDir(FWD,BWD);
Msleep(300); // ditto
bremsen();
}

uint8_t testen(void)
{
uint8_t temp=10; // Anzahl der Versuche

vorwaerts();
FrontLED(ON);
while(--temp && !taste()) Msleep(20); // 20ms pro Versuch weiterfahren
if(temp) bremsen();
FrontLED(OFF);
return(temp); // Wenn temp != null wurde eine Taste gedrückt = Wand erkannt
}

int main(void)
{
uint8_t schritt=0;

Init();

while(1)
{
vorwaerts(); // Vorwärts bis Hinderniss erkannt wird
while(!taste());
bremsen();
rueckwaerts();
bremsen();

if(schritt++<3) // dreimal zuerst links abbiegen...
{
linksdrehen();
if(testen())
{
rechtsdrehen();
rechtsdrehen();
if(testen()) rechtsdrehen();
}
}
else
{
rechtsdrehen();
if(testen())
{
linksdrehen();
linksdrehen();
if(testen()) linksdrehen();
}
schritt=0;
}
}
return 0;
}Wenn beim Kompilieren die Funktion Msleep() angemotzt wird, dann muss man diese umbenennen oder entfernen. Die Zeiten für die Drehungen, das Zurücksetzen und das Bremsen muss man anpassen. Das gilt auch für die PWM-Werte der Motoren.

Keine Ahnung ob das halbwegs funktioniert...

Gruß

mic

Philipp2195
17.10.2012, 17:27
danke für deine Antwort! Habe selbst mein ursprüngliches Programm mit deinen anregungen erweitert und es funktioniert jetzt eigentlich doch ziemlich gut. Perfekt wäre es, könnte ich auch noch ein programm zum geradeausfahren miteinbeziehen, aber das überschreitet mal wieder meine fähigkeiten

Ich bin im Internet auf ein Odometrieprogramm gestoßen was eigentlich sehr gut funktioniert. Nur fällt es mir schwer dieses mit meinem zu ,,verbinden´´
Ich hab mal die beiden Programme(das 2. befindet sich unter dem 1.) gestellt. habt ihr Ideen wie man diese verbinden könnte?

Gruß Philipp