PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Odometriewerte - Geradeausfahrt



harry3
03.07.2007, 22:58
Hallo!

Das ist mein erster Beitrag hier. Kurz zu meiner Person: Bin 20J., habe mich zwar schon längers für Elektronik, Computer usw. interessiert, asuro ist aber mein erster Roboter. Dieser ist nun 5 Tage alt.

Mein erstes Ziel war es, dem asuro das Geradeausfahren beizubringen. Gar nicht so einfach, wie ich anfangs dachte. Inzwischen klappts relativ gut. Allerdings hat er manchmal einen kurzzeitigen Ausrutscher was die Geradeausfahrt betrifft, scheinbar misst er falsche Geschwindigkeiten, sprich, da hats was mit der Odometrie. Soweit ich es testen konnte sind meine Funktionen aber OK, also scheints an der Hardware zu liegen. Kann es sein dass hin und herutschende Zahnräder mit dem Hell Dunkel Muster zu dem Problem führen?
Oder bringt es was wenn man mit schwarzem Stift den Außenrand des Zahnrades anmalt, welches nicht mit dem Aufkleber bedeckt ist. Oder gibt es sonst irgendwelche Tricks wie man die Odometrie verbessern könnte?

Andere Frage: Wie genau habt ihr mit Euren Programmen das Geradeausfahren hinbekommen? Also ich mein jetzt nicht empirisch den Unterschied von linken und rechtem Motor messen und dann als Korrekturwert eintragen, sondern richtig mit Odometriemesswerten und dementsprechender Regelung?
Bei mir klappts ein paar Meter lang ganz gut, aber ich möchte nicht wissen wo er landet wenn man ihn 1min oder länger fahren lässt.

Anbei noch der zugehörige Programmcode(verwende Asurolib 2.70).

Grüße,
Harri




/*
Erste Experimente mit Asuro.
3.7.2007
von harry3
*/

#define MAX_DIFF 5
#define KORREKTUR 10
#define MSTART_L 140
#define MSTART_R 140
#define ZEITKONST 500
#define TASTER(x) (unsigned char)(1<<(x-1))


#include "asuro.h"


void odometrie_auswertung(int,int*,int*);


int main(void)
{

unsigned char mspeed_l=MSTART_L,mspeed_r=MSTART_R,temp=0;
unsigned int array_l[3]={0},array_r[3]={0},odata[2]={0},timer=0;
signed int counter_l=0,counter_r=0;

Init();


while(temp<5)
{
temp++;
PollSwitch();
}

while(1)
{

temp=PollSwitch();

if(temp==TASTER(2) || temp==TASTER(5))
break;

else
{
MotorDir(FWD,FWD);
MotorSpeed(mspeed_l,mspeed_r);
OdometrieData(odata);
odometrie_auswertung(odata[0],array_l,&counter_l);
odometrie_auswertung(odata[1],array_r,&counter_r);

if(timer>ZEITKONST)
{
if( (counter_l-counter_r) > MAX_DIFF && mspeed_r<=(255-KORREKTUR))
mspeed_r=mspeed_r+KORREKTUR;

else if( (counter_r-counter_l) > MAX_DIFF && mspeed_r>KORREKTUR)
mspeed_r=mspeed_r-KORREKTUR;

counter_l=0;
counter_r=0;
timer=0;
}
timer++;
Msleep(1);
}

}

MotorDir(BREAK,BREAK);

//In Endlosschleife verbleiben
while(1);
return 0;
}


void odometrie_auswertung(int eingabe,int* zwsp,int* counter)
{

zwsp[2]=zwsp[1];
zwsp[1]=zwsp[0];
zwsp[0]=eingabe;

if(zwsp[1]>zwsp[0] && zwsp[1]>zwsp[2])
(*counter)++;


else if(zwsp[1]<zwsp[0] && zwsp[1]<zwsp[2])
(*counter)++;

return;
}

Sternthaler
04.07.2007, 00:36
Hallo harry3,
erst einmal herzlich willkommen im Forum.

Stark, endlich einmal eine andere Art der Odometrieauswertung.
Du schaust ja auf eine Historie der ODO-Messwerte und suchst nach Steigung und Gefälle in den Daten. In dieser Form habe ich das im Forum bisher noch nicht gesehen.
Aber leider, leider hat dein Programm einen Schönheitsfehler. Unten ist ein Bildchen, um mal die Messrate bei verschiedenen Geschwindigkeiten darzustellen.
Fährst du langsam (linke Seite), kannst du die Steigung mehrfach sehen.
Fährst du schnell (rechte Seite), kannst du die Steigung übersehen.


Zu deinen Fragen: Die Suche hier im Forum ist eigendlich ganz gut. Wenn du in der Auswahl zu "Forum:" auf Asuro einschränkst, findet man eigendlich alles.

Hier mal zum Thema Odometrie:
Klemmring für die Zahnradbefestigung (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=282782#282782) und von da auch weiter nach:
Sensor-Abdeckung (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=169199#169199)
Grundsätzlich gleiches Problem (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=30706)
Und noch ein Versuch zum ODO-Thema (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=27081)

Den Rest suchst du mal selber ;-)
Bei Fragen natürlich jederzeit wieder Einträge produzieren.

harry3
04.07.2007, 13:56
Hallo,

danke für die AW.

Ich schaue nicht auf die Steigung, sondern auf die Spitzen der Sinuswelle:
if(zwsp[1]>zwsp[0] && zwsp[1]>zwsp[2])
Ich schaue also ob der mittlere Wert (zwsp[1]) größer als die beiden äußeren Werte (zwsp[0] und zwsp[2]) ist. Wenn dies der Fall ist, dann kann man davon ausgehen, dass man gerade ein Maximum durchlaufen hat. Das gleiche geschieht bei den Tälern.

Das von dir angesprochene Problem mit der richtigen Abtastrate habe ich bedacht: Es müssen zumindest soviele Messwerte selbst bei Vollgas vorhanden sein, dass man die Berge/Täler der Sinuswelle klar erkennen kann - denn nichts anderes tut meine Funktion odometrie_auswertung(...).

Im Anhang sieht man sehr gut dass selbst bei Vollgas noch genug Odometriewerte vorhanden sind um einen eindeutigen Berg/Tal der Sinuswelle feststellen zu können. Übrigens: Die anfangs langgezogene Sinuswelle ist kein Messfehler, sondern es handelt sich dabei um die Beschleunigungsphase.

Danke für die Links, ich werd sie mir heute nachmittag mal "hineinziehen".


Grüße,
Harri

Sternthaler
05.07.2007, 01:01
Hallo harry3,
upps, das habe ich tatsächlich übersehen, dass du Berg und Tal suchst.
Bei deinen im Bild angegeben Messwerten sollte dies aber dann auch keine Probleme geben.
Deshalb habe ich mal aus meinem 'Fundus' von ODO-Messreihen mal ein echt hässliches Beispiel ausgesucht und angehängt.
Eventuell bekommst du ja auch solche 'Mini'-Berge / -Täler wie bei mir.

Jetzt habe ich aber nochmal auf dein Programm geblickt. (Hoffentlich nicht schon wieder mit zugeklappten Augen.)
Mir fällt nun auf, dass du zwar in deiner Schleife immer die OdometrieData()-Funktion aufrufst, die Messwert durch deine Berg-/Tal-Suche laufen läßt, aber nur alle ca. 500 ms (ZEITKONST * Msleep(1)) nachsiehst, ob an den Geschwindigkeiten der Motoren nachgeregelt werden muss.
Dann löschst du auch noch die counter_[l|r]-Werte und verlierst damit die bis dahin aufgetretenen Differenzinformationen.
--> Ich tippe darauf, dass hier das Problem liegt.

P.S.: Ich habe noch so im Hinterkopf, das waste hier im Forum im Thread Asuro: Linienfolger mit PD-Regler (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=11818) seine Reglung für 2 ms ausgelegt hat. (Der Grund war, glaube ich, die Zeit zum ADC-Daten ermitteln).
2 ms und 500 ms sind ein kleiner Unterschied. (Ohne Wertung, da es ja eventuell ausreichen kann.)

harry3
05.07.2007, 12:50
Hallo!

Anscheinend hats an den herumrutschenden Musterscheiben gelegen. Diese hab ich nun mit einen kleinen Drahtring am Ende der Achse fixiert.
Jetzt fährt Asuro auf einmal recht gut geradeaus(max. 20cm seitlicher Versatz auf 3m Fahrstrecke ... damit kann man leben).

Die 500ms verwende ich, damit genug Messwerte vorhanden sind um eindeutig sagen zu können welcher Motor zu langsam dreht.
Außerdem braucht ein Motor sowieso etwas Zeit, um auf die "befohlene" Geschwindigkeit zu beschleunigen, von daher sind 2ms für mein Programm zu kurz. Ich werde aber trotzdem noch ein bisschen mit diesem Wert herumspielen.

Die Zählerwerte lösche ich aus 2 Gründen:
Erstmal möchte ich vermeiden dass ich irgendwann den unsigned int Bereich überschreite(ca. 65000)==>der Zähler würde unverhofft wieder bei 0 zu zählen beginnen.
Außerdem wird die Motordrehzahl ja verändert=>dadurch ergeben sich neue Drehgeschwindigkeiten=>daher auch eine neue Messung.

Bei einer so verbogenen Sinuswelle wie in deinem Bild würde meine Funktion falsche Daten liefern. Da ist die einzige Möglichkeit wohl mit Hell/Dunkel Werten zu arbeiten(also die "klassische" Odometrie Auswertung).


Grüße,
Harri

harry3
05.07.2007, 17:47
Hab nun noch ein bisschen herumprobiert und hab mir schließlich noch den Zusammenhang zwischen MotorSpeed Änderung und der Geschwindigkeit (gemessen anhand der Odometrie) angesehen.

Interessanterweise gibt Asuro bei einer Odometrieabtastzeit von weniger als 1ms falsche Werte zurück, siehe Bildanhang, blaue Linie. Je höher die Motorgeschwindigkeit, desto geringer die gemessene Geschwindigkeit!!! Da ist was faul. Anscheinend ist die Odometriefunktion bei so hoher Abtastrate unbrauchbar!? Wie auch immer...

Bei einer Abtastzeit von 2ms(rote Linie) hat man einen fast linearen Zusammenhang zwischen MotorSpeed und gemessener Geschwindigkeit.

Mit den neuen Erkenntnissen habe ich mein Programm überarbeitet und siehe da - Asuro fährt fast immer geradeaus. Das ganze funktioniert quasi wie ein P-Regler.



/*
Erste Experimente mit Asuro.
3.7.2007
von harry3
*/

#define MAX_DIFF 0
#define MSTART_L 140
#define MSTART_R 140
#define ZEITKONST 250
#define ABTASTZEIT 2
#define KP 3
#define KORR_MAX 36
#define TASTER(x) (unsigned char)(1<<(x-1))


#include "asuro.h"


void odometrie_auswertung(int,int*,int*);


int main(void)
{

unsigned char mspeed_l=MSTART_L,mspeed_r=MSTART_R,temp=0;
unsigned int array_l[3]={0},array_r[3]={0},odata[2]={0},timer=0;
signed int counter_l=0,counter_r=0,korr=0;


Init();



while(1)
{

temp=PollSwitch();
if(temp==PollSwitch() && temp!=0)
break;

else
{
MotorDir(FWD,FWD);
MotorSpeed(mspeed_l,mspeed_r);
OdometrieData(odata);
odometrie_auswertung(odata[0],array_l,&counter_l);
odometrie_auswertung(odata[1],array_r,&counter_r);

if(timer>ZEITKONST)
{
if( (counter_l-counter_r) > MAX_DIFF)
{
korr=(counter_l-counter_r)*KP;

if(korr>KORR_MAX)
korr=KORR_MAX;

if(mspeed_r<=(255-korr))
mspeed_r=mspeed_r+korr;
}

else if( (counter_r-counter_l) > MAX_DIFF)
{
korr=(counter_r-counter_l)*KP;

if(korr>KORR_MAX)
korr=KORR_MAX;

if(mspeed_r>=korr)
mspeed_r=mspeed_r-korr;

}

counter_l=0;
counter_r=0;
timer=0;
}
timer++;
Msleep(ABTASTZEIT);
}

}

MotorDir(BREAK,BREAK);

//In Endlosschleife verbleiben
while(1);
return 0;
}


void odometrie_auswertung(int eingabe,int* zwsp,int* counter)
{

zwsp[2]=zwsp[1];
zwsp[1]=zwsp[0];
zwsp[0]=eingabe;

if(zwsp[1]>zwsp[0] && zwsp[1]>zwsp[2])
(*counter)++;


else if(zwsp[1]<zwsp[0] && zwsp[1]<zwsp[2])
(*counter)++;

return;
}




Grüße,
Harri