PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Fehler bei Winkelberechnungen [gelöst]



damfino
24.02.2010, 19:15
Hallo,

Ich steh bei meiner Positionsberechnung über Odometrie vor einem Rätsel, und zwar kommt am Anfang der richtige Winkel und Weg raus, mit der Zeit sind die Ergebnisse aber falsch.
Die Winkeleinteilung entspricht einem Kompass, 0°=Norden, 90=Osten, etc. x = positiv nach Osten, y positiv nach Norden.
Am Anfang passt es, bei zB 50° wird pos_x und pos_y größer. Aber auf einmal ist zB pos_x negativ, und bleibt negativ (wird in negativ immer größer), egal ob bei Fahrtrichtung 50° oder 300°. Bei Zahlenwerten um 1000 habe ich da sicher keinen Variablenüberlauf. Hab schon alles mögliche mit anderen Definitionen, Casten, etc probiert, ändert nichts.


Hier der Auszug vom Code, vielleicht findet jemand einen Fehler.


static inline void Pos_odo()
{
short odo_li_temp, odo_re_temp, richtung_temp;
long weg,pos_x_temp, pos_y_temp;
double si, co;

odo_li_temp=(short)odo_li; odo_re_temp=(short)odo_re;
odo_li_temp=odo_li_temp*48;odo_re_temp=odo_re_temp *48;

weg= (long)((odo_li_temp+odo_re_temp)/20);
richtung_temp=((odo_li_temp-odo_re_temp)*3); //*1000/320


if (richtung_temp>6282) richtung_temp=richtung_temp-6282; // ^2*pi*1000
if (richtung_temp<0) richtung_temp=richtung_temp+6283;

richtung=richtung+richtung_temp;

if (richtung>6282) richtung=richtung-6282; // ^2*pi*1000
if (richtung<0) richtung=richtung+6283;
// 0° = N 90° = O 180° = S 270° = W
// 0=2*pi pi/2 pi 3*pi/4



odo_li=0; odo_re=0;


si=128*sin((double)(richtung)/1000);
co=128*cos((double)(richtung)/1000);

pos_x_temp=weg*((long)(si));
pos_y_temp=weg*((long)(co)); // sin+cos in x,y vertauscht damit +y=Norden=0°, +x=Osten

pos_x_temp=pos_x_temp/128; // die 128von weg wieder rausrechnen
pos_y_temp=pos_y_temp/128;


pos_x=pos_x+pos_x_temp;
pos_y=pos_y+pos_y_temp;
}


Alle anderen Variablen sind global.

LG

XBert
24.02.2010, 22:19
Hi, ich habe zwar beim schnellen drüberschauen noch nichts gefunden, aber es wäre bestimmt hilfreich wenn du zeigen würdest wie oft (bzw. wo) die Funktion aufgerufen wird und wie deine globalen Variablen definiert sind.

Warum du allerdings vorher multiplizierst und dannach wieder dividierst ist mir nicht ganz klar.
Wenn du versuchst mit Integer-Rechnungen Performance rauszuholen dann ist das die falsche Stelle ;)
die Sinus/Cosinus Berechnungen dauern vermutlich länger als der Rest der Funktion.
Also entweder alles Fixkomma oder alles Gleitkomma ;)

LG

Edit: versuche globale variablen möglichst zu vermeiden (außer wenn es nicht anders möglich ist, z.b bei Interrupts) und verwende wenn du die Variablen selbst verändern willst lieber Zeiger.

damfino
25.02.2010, 19:08
Hi!
Die Mischung aus Gleit und Fixkomma kommt aus den vielen Versuchen ein vernünftiges Ergebnis zu bekommen, es war ursprünglich alles mit Integer, und ich dachte dass dort der Fehler liegt. Das wird wieder vereinheitlicht, Ziel ist Fixkomma.

Vorher multiplizieren und nachher dividieren bringt bei Fixkomma eine höhere Genauigkeit, ohne dem wären mit Fixkomma die Winkelfunktionen nur 0 oder 1, und damit ist die Positionsberechnung hinfällig.

Bin aber jetzt draufgekommen dass die Funktion passt, der Fehler kommt aus der Umrechnung Rad in Grad und itoa.
Ich musste ein Variable von unsigned auf signed ändern, und habe damit eine Berechnung richtiggestellt, aber dafür in der nächsten einen Überlauf produziert....](*,) ](*,)


Mir ist klar das globale Variablen nicht ideal sind, aber mit den Pointern stehe ich noch auf Kriegsfuß, ich kapier noch nicht wie ich mit zB 6 verschiedenen arbeiten kann, bzw welchen Vorteil der Pointer gegenüber einer 8Bit Variable hat.

LG