- LiFePO4 Speicher Test         
Seite 2 von 5 ErsteErste 1234 ... LetzteLetzte
Ergebnis 11 bis 20 von 45

Thema: pthread-Task als Methode einer C++ Klasse?

  1. #11
    HaWe
    Gast
    Anzeige

    Powerstation Test
    ".... und was das für mein PID Problem jetzt eigentlich bedeutet.... "

  2. #12
    shedepe
    Gast
    Ohne dir zu nahe treten zu wollen, du schimpfst auf OOP ohne dich damit genau beschäftigt zu haben. Das C++ nunmal anders programmiert wird als C, auch wenn C eine Untermenge von C++ ist, ist nunmal dem geschuldet, dass es eine andere Programmiersprache ist. Und eine andere Programmiersprache muss man eben auch erst mal lernen. Zu einer Programmiersprache gehören eben nicht nur die keywords und die Syntax sondern eben auch Konzepte und Hintergrundwissen bezüglich dem was unter dem Oberfläche passiert.

    Mein Vorschlag wäre nimm std::threads in deiner Klasse. Ein std::thread ist unter Linux genau das selbe wie ein thread der über Posix (pthread) gestartet wurde. Wenn du sachen machen willst wie thread abbrechen oder priority ändern. Lässt du dir von dem std::thread sein native handle (Das auch nur ein Verweis auf einen pthread ist) geben und kannst das ganz normal den pthread funktionen übergeben. Der Vorteil dabei ist, du sparst dir eben das etwas komplizierte Aufrufen eines pthreads auf eine Klassenfunktion.

  3. #13
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    04.09.2011
    Ort
    Hessen
    Beiträge
    707
    Zitat Zitat von HaWe Beitrag anzeigen
    ".... und was das für mein PID Problem jetzt eigentlich bedeutet.... "
    Es beantwortet die Frage.

    Statt im obigen Beispiel
    Code:
      std::thread MakeTask()
      {
        return std::thread([this] { Control(3); });
      }
    müsste man etwas in der Art

    Code:
      static void MakeTask(void* this_instance)
      {
    	((PidClass*) this_instance)->Control(3);
      }
    schreiben. Dann könnte man
    Code:
    int main()
    {
      PidClass pid;
      pthread_t t;
      pthread_create(&t, NULL, &PidClass::MakeTask, &pid);
    Ungetestet und aus dem Kopf geschrieben, zeigt nur das Prinzip.
    Geändert von Mxt (20.09.2016 um 08:38 Uhr)

  4. #14
    HaWe
    Gast
    ich will doch gar nichts "returnen"...?
    ich will doch nur eine Funktion einfügen, die was ausführt, aber nur eben als task-Funktion, nicht als "normale" Funktion...

    return ((PidClass*) this_instance)->Control(3);

    das hier ist mir allerdings schon wieder komplett unverständlich:
    pthread_create(&t, NULL, &PidClass::MakeTask, &pid);


    nee, ich gebe es auf, hat keinen Sinn, OOP mit C++ ist wirklich nicht mein Ding.

  5. #15
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    04.09.2011
    Ort
    Hessen
    Beiträge
    707
    Ja, da war ein return zu viel.

  6. #16
    Benutzer Stammmitglied
    Registriert seit
    19.05.2015
    Beiträge
    69
    Hallo HaWe,

    also nachdem ich mir dein Mindstrom Code angesehen habe, wäre wohl der erste Schritt Deine Berechnungsroutinen "task_PID_[ABC]" so umzuscheiben, das sie als Parameter einen Zeiger auf eine struct eines PIDs bekommen. Ansonsten landest Du wieder bei der Code-Redundanz, wie Du sie im Mindstorm-Projekt hast.

    Code:
    #include <stdio.h>
    #include <pthread.h>
    
    struct PID {
      pthread_t tid;
      char* name;
    
      float p;
      float i;
      float d;
    };
    
    struct PID pids[] = { 
      {0, "Task A", 0.015, 0.2, 0.7 },
      {0, "Task B", 0.3, 0.5, 0.80 }
    };;
    
    /* thread main */
    void *calc_pid(void *arg) {
      struct pid* PID = (struct pid*)arg;
      int idx = 0;
    
      for(idx = 0; idx < 8; idx++) {
        pid->p += .03;
        printf("[%d]: %s, p=%f, i=%f, d=%f\n", idx, pid->name, pid->p, 
    	   pid->i, pid->d);
      }
    
      return 0;
    }
    
    int main(int argc, char** argv) {
      int idx  = 0;
      int size = sizeof(pids)/sizeof(struct pid);
    
      /* Konfig fuer eine Aktion beider Motoren,
         wie immer die aussehen mag */
    
      for(idx = 0; idx < size; idx++)
        if(pthread_create(&pids[idx].tid, 0, calc_pid, &pids[idx])) {
          perror("pthread not creatable ");
          return 1;
        }
    
      for(idx = size - 1; idx >= 0; idx--) {
        if(pthread_join(pids[idx].tid, 0)) {
          fprintf(stderr, "Couldn't join thread for task %s ", pids[idx].name);
          perror(" ");
          continue;
        }
        pids[idx].tid = 0;
      }
    
      return 0;
    }
    Das was in dem einfachen Beispiel in der main() steht würdest du halt für jede Motoraktion (Rotate, Continue etc...) durchimplementieren müssen. Auch müßtest Du den Zeiger auf die einzelne struct ordentlich an die anderen Funktionen weiterreichen, damit diese immer nur auf dieser einen Variable operieren und so keine Wettbewerbsbedingungen entstehen.
    Der Nachteil ist IHMO, dass Threads erzeugt und wieder vernichtet werden, was Resourcen kostet.

    Ein anderer Ansatz wäre, für jeden PID einmal einen Thread anzulegen, der aus einer synchronisierten Schlange für einen Motor Kommandos liest, ausführt und zurück meldet das es fertig ist. Dann gäbe es einen Thread der den anderen sagt was zu tun ist - quasi das Kommando über sie hat.
    Nachteil hier ist, das Du einen Synchronisationsmechanismus implementieren müßtest.

    Auch könntest du dir vielleicht mal die OMP Threading-Variante anschauen, dann hättest du weniger mit Synchronisationsaufwand zu tun und ist möglicher Weise der übersichtlichere Weg für dich.

    Das sind so meine Ideen zu deinem Problem.

    Gruß
    botty

  7. #17
    HaWe
    Gast
    ach ja, gerade erst gecheckt - vlt war es doch noch auch ein Kommunikationsproblem und ich hatte es nicht ausreichend erläutert:

    das pid-task create soll nicht von main oder einer anderen Funktion aus, sondern automatisch innerhalb der PID Klasse selber gestartet werden.
    Die PID Klasse sollte dafür dann (mindestens) 3 Methoden enthalten,
    zum einen eine für den Funktionsaufruf selber ähnlich wie
    PID.start(double p, double i, double d, char mode);

    PID.start initialisiert damit die p,i,d Konstanten und die Variable Modus (erreichen und dann abschalten oder kontinuierlich halten)
    und dann wird damit anschließend ebenfalls die 2. Methode, nämlich
    PID.thread
    quasi lokal gestartet, nicht global.

    später, nach
    new PID PID_A;

    soll dann alles automatisch laufen durch
    Code:
    PID_A.start(0.5,  10.0,  0.1,  true);
    Nun läuft der damit intern creierte pthread-Task bis zur Selbstterminierung oder bis zur Beendigung durch einen externen Befehl.

    die dritte Methode muss dafür lauten
    PID.stop();

    nach externem Aufruf per
    Code:
    PID_A.stop();
    soll dann der momentan laufende PID_A-Task mit seiner momentan vergebenen PID-ID gestoppt und dann gejoint werden (falls er tatsächlich läuft, ansonsten wirkungslos).


    analog das ganze für jede andere erzeugte und dann bei Bedarf gestartete PID-Instanz
    new PID PID_B;
    new PID PID_C;
    new PID PID_D;
    new PID PID_E;
    usw.

  8. #18
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    04.09.2011
    Ort
    Hessen
    Beiträge
    707
    Wo der Thread gestartet wird macht keinen großen Unterschied. Bei std::thread würde sich am eigentlichen Code nichts ändern.

    Beim Beispiel mit dem static member nur zwei Dinge:
    Code:
    class PidClass
    {
    private:
      pthread_t t;  // Ist jetzt in der Klasse, statt in main
    und
    Code:
    pthread_create(&t, NULL, MakeTask, this);  // Wenn in einem Member der Klasse verwendet
    Geändert von Mxt (20.09.2016 um 15:19 Uhr) Grund: & kann auch weg

  9. #19
    HaWe
    Gast
    hmmm .
    Interessant...

  10. #20
    Benutzer Stammmitglied
    Registriert seit
    19.05.2015
    Beiträge
    69
    Oder wenn man in der reinen C Welt bleiben möchte - ist jetzt keine Kritik @Mxt - kann man's halt so machen:

    Code:
    #include <stdio.h>
    #include <pthread.h>
    
    struct PID {
      pthread_t tid;
      char* name;
    
      float p;
      float i;
      float d;
    };
    
    struct PID PID_A = {0, "Task A", 0.015, 0.2, 0.7 };
    struct PID PID_B = {0, "Task B", 0.3, 0.5, 0.80 };
    
    /* thread main */
    void *pid_task(void *arg) {
      struct pid* PID = (struct pid*)arg;
      int idx = 0;
    
      for(idx = 0; idx < 8; idx++) {
        pid->p += .03;
        printf("[%d]: %s, p=%f, i=%f, d=%f\n", idx, pid->name, pid->p, 
    	   pid->i, pid->d);
      }
    
      return 0;
    }
    
    int pid_start(struct pid* pid, float p, float i, float d, int flag) {
      pid->p = p;
      pid->i = i;
      pid->d = d;
    
      if(flag){
        ; /* Whatever */
      }
    
      return pthread_create(&pid->tid, 0, pid_task, pid);
    }
    
    int pid_stop(struct pid* pid, int cancel) {
      int rc = 0;
    
      if(cancel)
        pthread_cancel(pid->tid);
    
      rc = pthread_join(pid->tid, 0);
      pid->tid = 0;
    
      return rc;
    }
    
    int main(int argc, char** argv) {
    
      pid_start(&PID_A, .5, .3, .1, 0);
      pid_start(&PID_B, .2, 1.2, .3, 1);
    
      pid_stop(&PID_A, 0);
      pid_stop(&PID_B, 0);
    
      printf("Snd start:\n");
    
      pid_start(&PID_B, .2, 1.2, .3, 1);
      pid_start(&PID_A, .5, .3, .1, 0);
    
      pid_stop(&PID_A, 1);
      pid_stop(&PID_B, 0);
      return 0;
    }

Seite 2 von 5 ErsteErste 1234 ... LetzteLetzte

Ähnliche Themen

  1. Abgeleitete Klasse = konkrete Klasse?
    Von vixo im Forum Software, Algorithmen und KI
    Antworten: 4
    Letzter Beitrag: 15.09.2016, 16:02
  2. Antworten: 4
    Letzter Beitrag: 02.04.2016, 14:23
  3. Task motionControl() mit der M32
    Von inka im Forum Robby RP6
    Antworten: 8
    Letzter Beitrag: 10.04.2013, 06:40
  4. Gegen-EMK-Methode
    Von MatlStg im Forum Motoren
    Antworten: 7
    Letzter Beitrag: 11.02.2008, 17:07
  5. Was ist die besser Methode? (ADC auswerten)
    Von quantum im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 28.01.2007, 12:57

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress