kramann.info
© Guido Kramann

Login: Passwort:










COACH2
1 Planung
2 Architektur
3 Anzeige
4 EEPROM
5 I2C
..5.1 MasterSendByte
..5.2 MasterSend2Bytes
..5.3 MasterReceiveByte
..5.4 MasterReceive2Bytes
6 UART
7 DFT
8 FFT
9 Planung2
10 Klassen
..10.1 AnzeigeTaster
..10.2 RS232
..10.3 MotorServo
..10.4 Drehgeber
..10.5 Sensor
..10.6 Funk
11 Adaption
..11.1 Programmiertechnik
..11.2 Evoopt
12 Fuzzy
..12.1 Uebungsaufgabe
..12.2 Fuzzygroesse
..12.3 Fuzzyset
..12.4 Lookuptable
13 Skript
..13.1 Funkkorrektur
..13.2 Skriptsprachen
..13.3 Anforderungen
..13.4 Agentensysteme
..13.5 Implementierung
..13.6 Experimente
14 Gesamtkonzept
..14.1 Skripterweiterung
..14.2 Makroverhalten
67 Echtzeitsysteme
..67.1 Einfuehrung
....67.1.1 Echtzeit
....67.1.2 Korrektheit
....67.1.3 Hardware
....67.1.4 Ziele
....67.1.5 Synchronprogramm
..67.2 Threads
....67.2.1 Java
....67.2.2 Synchronisierung
..67.3 COACH
....67.3.1 Kaskadenregler
....67.3.2 Zeitebene1
....67.3.3 Zeitebene2
....67.3.4 Zeitebene3
....67.3.5 Puck
....67.3.6 Puckschwarm
..67.4 RTAIlab
....67.4.1 Slax
....67.4.1 USB_Stick
....67.4.2 Sinus
..67.5 Semaphor
....67.5.1 Laufkatze
....67.5.2 Java
....67.5.3 Semaphor
..67.6 Audio
....67.6.1 wav
....67.6.2 Linux
..67.7 Lookup
....67.7.1 Fuzzy
....67.7.2 PWM
..67.8 NeuronaleNetze
....67.8.1 Neuron
....67.8.2 Backpropagation
....67.8.3 Umsetzung
....67.8.4 Winkelerkennung
..67.9 Internetprogrammierung
....67.9.1 Codegenerierung
....67.9.2 PHP_Programmierung
....67.9.3 PHP_OOP
....67.9.4 Java
....67.9.5 UDP
..67.10 DFT
..67.11 FFT
..67.12 Zustandsmaschine
..67.13 Fuzzy
....67.13.1 Fuzzylogik
....67.13.2 FuzzyRegler
....67.13.3 Uebung9
....67.13.5 Softwareentwicklung
......67.13.5.1 AgileSoftwareentwicklung
......67.13.5.2 FuzzyRegler
......67.13.5.3 Uebung
....67.13.6 Umsetzung
......67.13.6.1 FuzzyRegler
......67.13.6.2 Simulation
......67.13.6.3 Optimierung
......67.13.6.4 Uebung
....67.13.7 Haengependel
......67.13.7.1 Haengependel
......67.13.7.2 Simulation
......67.13.7.3 FuzzyRegler
......67.13.7.4 Optimierer
......67.13.7.5 Genetisch
....67.13.8 Information
....67.13.9 Energie

13.5 Ideen zu einer Implementierung einer Skriptsprache für das COACH-Vehikel

  • Nach den ganzen Vorüberlegungen, sollen nun einige ganz konkrete Ansätze zur Umsetzung einer Skriptsprache und des zugehörigen Interpreters dargestellt werden.

Konfiguration eines Fuzzy-Systems

  • Ein Fuzzy-System wird durch die Lage der Maxima der Zugehörigkeitsfunktionen und eine Liste an Regeln beschrieben.
  • Beides ließe sich auch in Array bzw. Matrix-Form über Funk als eine Art Skript auf ein Vehikel übertragen.
  • Erinnern Sie sich an Kapitel 10.3 Regelungssysteme, dass die Regeln als eine einfache Matrix von Indices für den Einachser umgesetzt werden konnten:
...
int indices[25]  = {
                                    0,0,1,2,2,
                                    0,1,2,2,3,
                                    0,1,2,3,4,
                                    1,2,2,3,4,
                                    2,2,3,4,4
                                };
...

Code 13.5-1: Ausschnitt aus der Klasse Fuzzysystem für den Einachser.

  • Natürlich können die übertragenen Arrays und Matrizen nicht direkt als "Skript" bezeichnet werden.
  • Bei entsprechender Anlage mehrerer Fuzzy-Systeme zur Gestaltung des Verhaltens des Vehikels, entspricht der resultierende Effekt jedoch durchaus dem, bei dem das Verhaltensmuster über ein gewöhnliche(re)s Skript beschrieben wird.

Interpretation einer Liste von Befehlen

  • In unserem Fall kommt es nicht sehr darauf an, dass die Skriptbefehle von einem Menschen direkt gelesen und verstanden werden.
  • Der Verzicht hierauf erübrigt jedenfalls die Notwendigkeit eines komplizierteren Befehlsinterpreters, der die Wörter im Skript mit einer Liste mit den erlaubten Befehlen vergleicht.
  • Statt dessen wäre eine Nummer für eine aufzurufende Funktion auch ausreichend.
  • Angenommen, die verfügbaren Funktionen benötigten keine Übergabeparameter und lieferten auch keine Rückgabewerte, dann könnte ein sehr simpler Interpreter in folgender Weise mit einer switch-Anweisung realisiert werden:
for(int i=0;i<ANZAHL_BEFEHLE;i++)
{
     switch(befehls_liste[i])
     {
         case 0:
             antriebs_regelung.setzteSollwert(20);
         break;
         case 1:
             servo.links();
         break;
         case 2:
             wert[k++] = sensor.hole_wert();
             k%=10;
         break;
             ...
     }
}

Code 13.5-2: Denkbarer Programmabschnitt des Skript-Interpreters mittels switch-Anweisung

  • An dem Beispiel wird ersichtlich:
  • Auch wenn die Befehlsliste keine Parameter enthält, kann dies realisiert werden, indem unterschiedliche Befehlsnummern, die gleiche Funktion, jedoch mit unterschiedlichen Parametern aufrufen.
  • Ebenso können Rückgabewerte von Funktionen gespeichert werden, wenn die entsprechende Zuweisung direkt in einer der auswählbaren Anweisungen steht.
  • Ähnlich der Trennung zwischen Regeln und Zugehörigkeitspositionen bei Fuzzy-Systemen, können Parameter auch unabhängig zum Skript auf das Vehikel übertragen werden.

Verzicht auf "switch" und vergleichbare Kontrollstrukturen durch Einsatz von Funktionszeigern

  • C/C++ bietet die Möglichkeit neben Variablen auch Funktionen in Zeigern zu speichern.
  • Indem man die Zeiger aller verfügbaren Methoden in einem Array speichert und das "Skript" aus der Angabe der Indices dieses Arrays, kann auf die switsch-Anweisung verzichtet werden.
  • In C++ können Funktionszeiger aber nur folgendermaßen (testweise auf einem PC) umgesetzt werden:
#include<iostream>
using namespace std;
class Befehle
{
  public:      
     void tudies()
     {
         cout<<"dies"<<endl;          
     }
     void tudas()
     {
         cout<<"das"<<endl;          
     }
     void tujenes()
     {
         cout<<"jenes"<<endl;          
     }
};
int main()
{
    Befehle befehle;
    void (Befehle::*zeiger[3])(void) = {
                                         &Befehle::tudies,  
                                         &Befehle::tudas,
                                         &Befehle::tujenes,
                                     };    
    int skript[4] = {0,1,0,2};
    for(int i=0;i<4;i++)
        (befehle.*(zeiger[skript[i]]))();
}

Code 13.5-3: Verwendung von Funktionszeigern, um auf einen Teil der Kontrollstrukturen bei der Skriptinterpretation verzichten zu können

  • Erläuterungen:
  • void (Befehle::*zeiger[3])(void) ist ein Array von 3 Funktionszeigern mit dem Namen "zeiger".
  • Es hat als Übergabeparameter und Rückgabewert "void".
  • &Befehle::tudies wählt den Zeiger auf die Methode "tudies" der Klasse "Befehle" aus.
  • Da Funktionen in C++ an Objekte gebunden sind und nur über eine Syntax "OBJEKTNAME.FUNKTION()" aufgerufen werden können, wäre ein Aufruf, um die nullte Funktion in zeiger anzusprechen der Art *(zeiger[0]))(); in C++ unzulässig.
  • Mit (befehle.*(zeiger[skript[i]]))(); wird die im Zeiger gespeicherte Funktion an ein Objekt gebunden.
  • Diskussion:
  • Die Verwendung von Funktionszeigern führ sicher zu einem performanteren Programm.
  • Sie setzt aber voraus, dass alle möglichen Methoden in einer Klasse gesammelt werden.
  • Dies zu bewerkstelligen kann wiederum einen recht hohen Programmieraufwand bedeuten.