home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AMIGA PD 1
/
AMIGA-PD-1.iso
/
Meeting_Pearls_II
/
html
/
sw
/
nbsd
/
FuzzyPendel
/
design.txt
< prev
next >
Wrap
Text File
|
1994-06-28
|
8KB
|
256 lines
<HEAD>
<TITLE>Fuzzy Pendel - Infos zur Implementierung</TITLE>
</HEAD>
<BODY>
<H1>Das Design des Fuzzy-gesteuerten Pendels</H1>
<!------------------------------------------------------->
<H2>Das Berechnungsschema</H2>
<!--------------------------->
Prinzipiell handelt es sich bei der Steuerung des Pendels um ein
rückgekoppeltes System, bei dem zuerst die eigentliche, ungesteuerte
Bewegung des Pendels berechnet wird. Aus dieser Pendelbewegung -
charakterisiert durch Winkel und Winkelgeschwindigkeit - wird dann
berechnet, wie stark gegengesteuert werden muss, um das Pendel wieder
aufzurichten.
<P>
Diese aufrichtende Kraft beeinflusst dann im nächsten
Iterationsschritt wiederum Winkel und -geschwindigkeit:
<P>
________________<IMG SRC="rueckkopplung.gif">
<P>
Die Funktion f1 entspricht dabei der Simulation der Pendelbewegungen,
f2 ist für das Ausbalancieren derselben zuständig. Diese Schleife
kann auch im
<A HREF="pendel.c">C-Quellcode der Curses-Version</A>
des Programmes gefunden werden:
<P>
<PRE>
while (alpha>=0.0 && alpha<=pi){
...
/* f1: Pendel-Verhalten nach Ch. Ziegaus */
Fres = sqrt(sqr(Fg) + sqr(Fa));
rho = alpha - arccos(Fa/Fres);
Fz = sin(rho) * Fres;
deltaAlpha = Fz/(2.0*m*l)*sqr(deltaT) + alphaDot*deltaT;
alphaDot = Fz/(m*l)*deltaT + alphaDot;
alpha = alpha + deltaAlpha;
/* f2: Ausgleichen der Pendelbewegung */
Fa = m*balance(alpha,alphaDot)*a0;
...
}
</PRE>
Hier werden zuerst Winkel (<CODE>alpha</CODE>) und
Winkelgeschwindigkeit (<CODE>alphaDot</CODE>) berechnet, anschliessend
wird mit Hilfe der Funktion <CODE>balance()</CODE> die Balancier-Kraft
<CODE>Fa</CODE> errechnet, mit der der Wagen am Fußpunkt des Pendels
beschleunigt wird.
<H2>Der eigentliche Fuzzy-Algorithmus</H2>
<!--------------------------------------->
Die Funktion <CODE>balance()</CODE> ist also für das eigentliche
Balancieren verantwortlich, sie bewerkstelligt dies anhand einer
Fuzzy-Steuerung. Diese besteht aus den folgenden Teilen:
<P>
<OL>
<LI> Bestimmen, zu welchem Grad der <A
HREF="#WinkelGrad">Auslenkwinkel</A> in einem
bestimmten Bereich (groß/mittle/klein Negativ, ...) liegt.
<LI> Bestimmen, zu welchem Grad die <A
HREF="#WinkelgeschwindigkeitGrad">
Winkelgeschwindigkeit </A> in einem bestimmten Bereich liegt.
<LI> <A HREF="#RegelnAnwenden">Anwenden der Regeln</A>:
Wenn Winkel im Bereich ... und Winkelgeschwindigkeit in ..., dann
steuere mit ... Kraft nach.
<LI> <A HREF="#Defuzzifizierung">Defuzzifizierung</A>: Im
vorhergehenden Schritt wurde berechnet, zu welchem Grad(en)
(gross/mittel/klein, positiv und/oder negativ) beschleunigt werden
soll. Aus diesen Werten wird nun der Mittelwert gebildet.
</OL>
<A NAME="WinkelGrad">
<H3> Grad der Auslenkung des Winkels <CODE>alpha</CODE></H3>
<!--------------------------------------------------------->
Als erstes soll bestimmt werden, in welchem Bereich(en) sich der
Winkel <CODE>alpha</CODE> befindet. Dazu wird für jeden der möglichen
Bereiche (NB, NS, NM, ZE, PS, PM, PB) abgeprüft, zu welchem Grad der
Winkel in diesem Bereich liegt. Dieser Grad kann zwischen 0.0 und 1.0
liegen, er wird im Array <CODE>b_alpha[]</CODE> für jeden Bereich
festgehalten.
<P>
Die folgende Grafik soll dies verdeutlichen:
<P>
<IMG SRC="impl_alpha.gif">
<P>
Da sich die Bereich überschneiden können, kann <CODE>alpha</CODE>
in mehreren Bereichen einen Grad >0 haben.
Der oben beschriebene Berechnungsvorgang wird im
<A HREF="pendel.c">C-Quellcode der Curses-Version</A>
durch das folgende Code-Fragment abgedeckt:
<P>
<PRE>
/* Gewichte von alpha ausrechnen */
for(i=0;i<NRANGES;i++){
if((b_alpha_u[i] > alpha) && (alpha > b_alpha_l[i])){
mid = (b_alpha_u[i]+b_alpha_l[i])/2.0;
if(alpha>mid){
/* linke Haelfte */
b_alpha[i] = 1.0-(alpha-mid)/(b_alpha_u[i]-mid);
}else{
/* rechte Haelfte */
b_alpha[i] = (alpha-b_alpha_l[i])/(mid-b_alpha_l[i]);
}
}else{
b_alpha[i] = 0.0;
}
}
</PRE>
<CODE>i</CODE> wird dabei über alle Bereiche von 0=NB bis
7=PS(=<CODE>NRANGES</CODE>) iteriert. Liegt der Winkel <CODE>alpha</CODE>
im jeweiligen Bereich (dessen untere und obere Grenze in
<CODE>b_alpha_l[]</CODE> bzw. <CODE>b_alpha_u[]</CODE> stehen), so wird
in <CODE>b_alpha[i]</CODE> festgehalten, wie stark sich der Winkel in
der Mitte des jeweiligen Bereichs <CODEi</CODE> befindet. Liegt er
ausserhalb des Bereiches, so wird <CODE>b_alpha[i]</CODE> auf
0.0 gesetzt.
<P>
Während der Simulation werden die so berechneten Werte sowohl in
<A HREF="06_alpha_values.html">tabellarischer</A>
als auch in
<A HREF="09_alpha_ranges.html">grafischer</A>
Form angezeigt.
<P>
<A NAME="WinkelgeschwindigkeitGrad">
<H3> Grad der Auslenkung der Winkelgeschwindigkeit <CODE>alphaDot</CODE></H3>
<!-------------------------------------------------------------------------->
Hier wird analog zur Berechnung der Winkel-Grade vorgegangen, die
Grenzen der einzelnen Bereiche stehen in den Arrays
<CODE>b_alphaDot_l[]</CODE> und <CODE>b_alphaDot_u[]</CODE>. Die
berechneten Grade der einzelnen Bereiche werden im Array
<CODE>b_alphaDot[]</CODE> gespeichert und während der Simulation
ebenfalls in
<A HREF="07_alphaDot_values.html">tabellarischer</A> und
<A HREF="10_alphaDot_ranges.html">grafischer</A> Form angezeigt.
<P>
<A NAME="RegelnAnwenden">
<H3> Anwenden der Fuzzy-Regeln</H3>
<!-------------------------------->
Nachdem nun die Grade von <CODE>alpha</CODE> und <CODE>alphaDot</CODE>
bestimmt sind ist es möglich, die Regeln zur Aussteuerung des Pendels
anzuwenden. Diese treffen für Kombinationen von Winkel und
Winkelgeschwindigkeit Aussagen darüber, wie die Ausgleichkraft
<CODE>Fa</CODE> beschaffen sein muß, um das Pendel aufzurichten, z. B.:
<P>
Wenn <CODE>alpha</CODE>=PS und <CODE>alphaDot</CODE>=NS, dann setze
<CODE>Fa</CODE>=ZE.
<P>
Aufgrund der "und"-Verknüpfung der beiden Bedingungen wird
<CODE>Fa</CODE>gleich dem kleineren der beiden Werte <CODE>alpha</CODE>
und <CODE>alphaDot</CODE> gesetzt. Dies soll auch nochmal in der
folgenden Grafik veranschaulicht werden:
<P>
<IMG SRC="impl_regel.gif">
<P>
Im <A HREF="pendel.c">C-Quellcode der Curses-Version</A>
sieht dies so aus:
<P>
<PRE>
/* Regeln anwenden */
for(i=0;i<NRANGES;i++){
b_Fa[i] = 0.0;
}
for(i=0;i<NRULES;i++){
b_Fa[b_rule_a[i]] = Max(b_Fa[b_rule_a[i]],
Min(b_alpha[b_rule_alpha[i]],
b_alphaDot[b_rule_alphaDot[i]]));
}
</PRE>
Dabei wird <CODE>Fa</CODE> zuerst für alle Bereiche von 0 (=NB) bis
NRULES (=7=PB) auf 0 gesetzt, d. h. es soll keine Kraft wirken.
<P>
Dann werden nacheinander sämtliche Regeln angewandt.
<CODE>b_rule_a[]</CODE> enthält dabei die Aussage, wie stark und in
welche Richtung die Kraft wirken soll, <CODE>b_rule_alpha[]</CODE>
und <CODE>b_rule_alphaDot[]</CODE> bestimmen, unter welchen Bedingungen
diese Kraft angewandt werden soll.
<P>
Wie oben erwähnt wird der Betrag der Kraft aus dem Minimum der Grade
von Winkel und Winkelgeschwindigkeit ermittelt (aufgrund der
"und"-Verknüpfung). Falls bereits eine Regel auf den angesprochenen
Bereich gewirkt hat, so wird die maximale Kraft der beiden zur Berechnung
der Ausgleichskraft verwendet.
<P>
<A NAME="Defuzzifizierung">
<H3> Defuzzifizierung</H3>
<!----------------------->
Nachdem durch das Anwenden der Regeln ein oder meist sogar mehrere
Aussagen über die Stärke der Ausgleichskraft <CODE>Fa</CODE> getroffen
wurden, soll nun in einem letzten Schritt <I>ein</I> Zahlenwert
(<CODE>max</CODE>) aus den gesamten Aussagen errechnet werden.
<P>
Im vorliegenden Fall wurden dabei die einzelnen Bereiche mit Gewichten
versehen, mit denen die einzelnen Grade Multipliziert und anschliessend
aufaddiert wurden:
<P>
<PRE>
/* Mittelwert ausrechnen */
max=0.0;
for(i=0;i<NRANGES;i++){
max =max + (i-(NRANGES/2))*b_Fa[i];
}
</PRE>
<HR><!----------------------------------------------------------------->
<A HREF="index.html">Hier</A> geht's zur Einführung zum Fuzzy-Pendel
zurück, und <A HREF="implement.html">hier</A> gibt's Informationen
über die Implementierung.
<HR><!----------------------------------------------------------------->
Hubert Feyrer, <A HREF="http://dusk.rz.uni-regensburg.de/Personal/hubert/hubert_feyrer.html">hubert.feyrer@rz.uni-regensburg.de</A>