PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Erweitertes M32 Beispiel "Example_10_Move2"-Progra



ion
15.10.2010, 18:15
Hallo, hab auch seit einiger Zeit einen RP6 und auch schon viel mit den Beispielprogrammen rumexperimentiert. Und weil ich C noch nicht gut kann hab ich zur Übung zwei Abyss-sensoren an ADC0 und ADC1 gelötet mit dem Ziel die Schreibtischkante zu erkennen. Die Sensoren sind zwei Sharp GP2D120 die vorne links und rechts außen auf der Base montiert und „Gucken“ schräg nach vorne auf den Boden. Dann hab ich in das Beispielprogramm RP6Base_Move_05 zwischen „Escape“ und „Avoid“ mein neues „Abyss-verhalten“ reingebastelt und nach einigen versuchen ist er auch wie gewollt beim erkennen eines Abgrundes angehalten, ein Stück zurück gefahren und dann etwas vom Abgrund weggedreht und hat dann mit „Cruise“ weitergemacht, **freu** \:D/ . Das Problem was ich habe ist nun das das Programm nach dem Starten immer mit dem Verhalten „ABYSS_FRONT“ anfängt obwohl gar kein Abgrund da ist. Das ist zwar nicht schlimm aber warum ist das so? Hab das ganze jetzt auch mit der M32 und "Example_10_Move2" hingekriegt aber da startet er auch mit "ABYSS-FRONT" und nicht wie erwartet mit "Cruise".

Hier mein Code für das Abyss-verhalten (M32):



// Abyss Behaviour:
#define ABYSS_MAX 200 // Sensor value for maximum depth= 200
// .... flat ground= 280
// traversable obstacle= 400

#define ABYSS_SPEED_BWD 80
#define ABYSS_SPEED_ROTATE 60
#define ABYSS_SPEED_SLOW 60

#define ABYSS_FRONT 1
#define ABYSS_FRONT_WAIT 2
#define ABYSS_LEFT 3
#define ABYSS_LEFT_WAIT 4
#define ABYSS_RIGHT 5
#define ABYSS_RIGHT_WAIT 6
#define ABYSS_WAIT_END 7


behaviour_command_t abyss = {0, 0, FWD, false, false, 0, IDLE};

void behaviour_abyss(void)
{

switch(abyss.state)
{
case IDLE:
if(adc0 <= ABYSS_MAX && adc1 <= ABYSS_MAX)
{
abyss.state = ABYSS_FRONT; //hier startet er immer?
}

else if(adc1 <= ABYSS_MAX)
{
abyss.state = ABYSS_RIGHT;
}
else if(adc0 <= ABYSS_MAX)
{
abyss.state = ABYSS_LEFT;
}
break;
case ABYSS_FRONT:
{
abyss.speed_left = ABYSS_SPEED_BWD;
abyss.dir = BWD;
abyss.move = true;
abyss.move_value = 140;
abyss.state = ABYSS_FRONT_WAIT;
}
break;
case ABYSS_FRONT_WAIT:
if(!abyss.move)
{
abyss.speed_left = ABYSS_SPEED_ROTATE;
abyss.move_value = 100;
abyss.dir = LEFT;
abyss.rotate = true;
abyss.state = ABYSS_WAIT_END;
}
break;
case ABYSS_LEFT:
{
abyss.speed_left = ABYSS_SPEED_BWD;
abyss.dir = BWD;
abyss.move = true;
abyss.move_value = 100;
abyss.state = ABYSS_LEFT_WAIT;
}
break;
case ABYSS_LEFT_WAIT:
if(!abyss.move)
{
abyss.speed_left = ABYSS_SPEED_ROTATE;
abyss.dir = RIGHT;
abyss.rotate = true;
abyss.move_value = 50;
abyss.state = ABYSS_WAIT_END;
}
break;
case ABYSS_RIGHT:
{
abyss.speed_left = ABYSS_SPEED_BWD ;
abyss.dir = BWD;
abyss.move = true;
abyss.move_value = 100;
abyss.state = ABYSS_RIGHT_WAIT;
}
break;
case ABYSS_RIGHT_WAIT:
if(!abyss.move)
{
abyss.speed_left = ABYSS_SPEED_ROTATE;
abyss.dir = LEFT;
abyss.rotate = true;
abyss.move_value = 50;
abyss.state = ABYSS_WAIT_END;
}
break;
case ABYSS_WAIT_END:
if(!(abyss.move || abyss.rotate))
{
abyss.state = IDLE;
}
break;
}
}

...und der geänderte Code für den behavior controller:


void behaviourController(void)
{
// Call all the behaviour tasks:
behaviour_checkLowBattery();
behaviour_waitForStart();
behaviour_cruise();
behaviour_avoid();
behaviour_abyss();
behaviour_escape();

// Execute the commands depending on priority levels:
if(checkLowBattery.state != IDLE) // Highest priority - 7
{
displayBehaviour(7);
moveCommand(&checkLowBattery);
}
else if(waitForStart.state != IDLE) // Priority - 6
{
displayBehaviour(6);
moveCommand(&waitForStart);
}
else if(escape.state != IDLE) // Priority - 5
{
displayBehaviour(5);
moveCommand(&escape);
}
else if(abyss.state != IDLE) // Priority - 4
{
displayBehaviour(4);
moveCommand(&abyss);
}
else if(avoid.state != IDLE) // Priority - 3
{
displayBehaviour(3);
moveCommand(&avoid);
}

else if(cruise.state != IDLE) // Priority - 1
{
displayBehaviour(2);
moveCommand(&cruise);
}
else // Lowest priority - 0
{
displayBehaviour(1);
moveCommand(&STOP); // Default command - do nothing!
// In the current implementation this never
// happens.
}
}



vielleicht kann mir ja hier einer der Experten weiterhelfen...

Gruß aus Hamburg
ion

Carry
15.10.2010, 22:09
Hallo,

es dauert ein wenig bis die Variablen adc0, adc1 vernünftige Werte haben. Solange sind sie 0 und deine Bedingung für 'ABYSS_FRONT' ist sofort beim ersten Aufruf erfüllt.



Carsten

ion
16.10.2010, 13:51
Hallo,
...das habe ich mir auch schon gedacht, aber die Werte für die ADCs müßten doch schon da sein, denn die werden ja,glaube ich zumindest, in der Funktion "printAllSensorValues" bzw genauer mit "getAllSensors" gelesen.
Also wenn der roboter noch im "wait-behavior" ist werden schon korrekte Werte übers Terminal ausgegeben und ich verwende doch gleiche Variable?

ion

Carry
16.10.2010, 15:14
Stimmt, meine Begründung ist nicht ganz vollständig. (Ist mir auch erst jetzt aufgefallen.)

Die Funktionen "printAllSensorValues" bzw. "getAllSensors" werden in "task_LCDHeartbeat" aufgerufen, d. h. nur einmmal pro Sekunde. Beim ersten Aufruf sind "adc0", "adc1" also noch 0 und der "abyss.state" wird sofort geändert. Der Zustand wird aber nicht zurück auf "IDLE" geändert, sobald die Werte korrekt sind. Dies geht nur über den Zustand "ABYSS_WAIT_END". Dieser wird aber nie erreicht, da die Bewegung nicht abgearbeitet wird, solange "WaitForStart" noch aktiv ist.

Erst wenn "WaitForStart" verlassen wird, kommt der "Abyss"-Zustand ("ABYSS_FRONT") zum tragen, die Bewegung wird ausgeführt und "abyss.state" wird wieder "IDLE" zugewiesen.

Eine Lösung wäre beim Verlassen von "WaitForStart" "abyss.state" nochmal explizit auf "IDLE" zu setzen.


Solche Gedankengänge in Worte zu fassen ist irgendwie schwierig :)

Carsten[/code]

ion
16.10.2010, 17:21
aha, jetzt hab ich´s kapiert. Werde deine Lösung mal testen.

Danke für die bemühung der Gehirnwindungen

ion

ion
17.10.2010, 15:58
jo, hat funktioniert...