- Labornetzteil AliExpress         
Ergebnis 1 bis 10 von 45

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

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    HaWe
    Gast

    pthread-Task als Methode einer C++ Klasse?

    hallo,
    ist es möglich, einen pthread-Task als Methode eines C++ Objekts zu implementieren, um mehrere solcher Tasks über mehrere Instanzen des Objekts unabhängig und pseudo-parallel starten zu können ?
    Es geht um kompliziertere PID-Regler für Motoren mit Quadraturencodern, jeder Motor soll über eigene PID-Task-Instanzen (endlos oder selbstterminierend) gesteuert werden. Der Aufruf der Motor-PID-Tasks wird sehr häufig gebraucht und nötig sein, und zwar für jede einzelne Motorstellung, die die einzelnen Motoren jeweils einzeln und unabhängig / asynchron immer wieder neu und mit veränderten Zielwerten und Abbruchbedingungen anfahren müssen (Zielstellung anfahren, dann coasten oder dann bremsen, oder dann dauerhaft gegen Widerstand oder passive externe Verstellkräfte bis zum gesonderten Abbruchbefehl approximiert halten), teilweise werden auch 2 Motoren paarweise miteinander per PID z.B für "perfekten" Geradeauslauf zu synchronisieren sein.

    Als Einzel-Tasks mit Einzel-Routinen gibt es bereits eine Lösung, ich möchte nur nicht alle Methoden für 8 oder 10 Motoren 8 oder 10x bandwurmartig immer einzeln neu schreiben.

  2. #2
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.08.2008
    Ort
    DE
    Beiträge
    523
    Du willst ein Objekt der Klasse A erstellen, welches beim Aufruf von Methode B einen Task mit PID-Regler startet?

    mfg

  3. #3
    HaWe
    Gast
    hm, vlt doch nicht ganz so.... ich glaube soooo könnte man es vlt ausdrücken....:

    ich habe mir vorgestellt, ein Objekt PID zu entwerfen mit verschiedenen Variablen (für kP, kI, kD u.a.m.) und einer Methode
    PID.startPIDtask();

    dieser soll dann einen spezifischen pthread task starten

    pthread_t threadID;
    pthread_create(&threadID, NULL, threadName, NULL);

    jede Instanz
    new PID PID_A;
    new PID PID_B;
    new PID PID_C;
    ...

    soll dann in der Lage sein, ihren eigenen task zu starten und nach dessen Beendigung wieder zu "joinen",
    pthread_join(threadID, NULL);
    um ihn bei Bedarf jederzeit erneut starten zu können.

    Um das Konzepz etwas konkreter zu zeigen, hier wäre ein Setup ohne diese Objekte, wo für jeden Motor eine eigene globale statische Task-Methode programmiert werden musste (mit "NXC" für lego NXT, mangels OOP und Funktionspointer nicht anders möglich):

    http://www.mindstormsforum.de/viewto...p=61935#p61930

    ich habe 3 feste (Motor-spezifische) task Routinen plus eine (Motor-spezifische) PID-Struktur, für jeden Motor eine eigene,die über reichlich komplizierte und umständliche Hilfs-Funktions-Aufrufe immerhin selektiv asynchron gestartet und beendet werden können (start task / stop task).
    So kompliziert und "ungelenk" wollte ich es jetzt für 8 -10 Motoren nicht wieder machen müssen, daher die Idee mit dem PID-Objekt statt der PID-Struktur.

    Ich hoffe, das könnte das Problem vlt ein wenig erhellen..... :-/

  4. #4
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    04.09.2011
    Ort
    Hessen
    Beiträge
    707
    Ich habs auch noch nicht ganz verstanden.

    Hier nur mal ein Beispiel in normalem C++ (11 oder 14), nur erstmal um zu verstehen, wie die Klasse aussehen soll
    Code:
    #include <cstdio>
    #include <thread>
    
    class PidClass
    {
    public:
    
      void Control(unsigned int n)
      {
        for (unsigned int i = 0; i < n; i++)
        {
          printf("Controlling ...\n");
        }
      }
    
      std::thread MakeTask()
      {
        return std::thread([this] { Control(3); });
      }
    };
    
    int main()
    {
      PidClass pid;
    
      auto t1 = pid.MakeTask();
    
      // ...
    
      t1.join();
    
      auto t2 = pid.MakeTask();
    
      // ...
    
      t2.join();
    
      return 0;
    }
    Da passiert nicht viel, es gibt nur sechs mal "Controlling ..." aus.

    Ist das so gemeint ? Die Klasse hat eine Methode die was tut (mit Parametern) und eine zweite, die einen Thread erzeugt der die erste irgendwie verwendet ?

    ---
    Achso vergessen.

    Ja, kann man auch zu Fuss machen, wird aber unschön
    http://stackoverflow.com/questions/1...n-from-a-class
    Geändert von Mxt (19.09.2016 um 16:56 Uhr) Grund: Link hinzugefügt

  5. #5
    HaWe
    Gast
    die Methode soll im Prinzip diesen Task als pthread-Task als "Muster" beinhalten - allerdings müssen später die Instanzen des Objekts für die pthread-Tasks natürlich eigene IDs und Namen bekommen, wenn sie von den Instanzen "erschaffen" und gestartet werden. C11-Tasks will ich nicht verwenden, sondern nur pthread Tasks:

    Code:
     // "Pseudocode"-Vorlage aus NXC:
    
    task task_PID_A() {
      float aspeed, damp, PWMpwr, readold, errorold, tprop;
      long  readstart, cmax, cmin;                         // for monitoring
      long  starttime, runtime, clock, dtime;              // timer
      char  regloop;
    
      PID_A.runstate = 0x10;                               // reg state: RAMPUP
      PID_A.read     = (MotorRotationCount(OUT_A));        // get current encoder reading
      PID_A.err      = PID_A.target - PID_A.read;          // error to target
    
      readstart      = PID_A.read;
      regloop        = 1;
    
    
    
    
    
      damp=0;                                 // damp the integral memory
    
      starttime= CurrentTick();
    
    
      // appoach target
      _Astart:
      PID_A.runstate = 0x10;                  // run state: RUNNING
    
      do {
    
        dtime    = CurrentTick() - clock;
        clock    = CurrentTick();
        runtime  = clock - starttime;
        tprop    = dtime/20.0;
    
        if ((PID_A.err==errorold)&& (abs(PID_A.err)>PID_A.precis)) damp=1;    // stalling
        else
        damp=PID_A.damp;
    
        PID_A.integr = (damp * PID_A.integr) + PID_A.err;
    
        if((PID_A.integr) > 3*PID_A.maxout) PID_A.integr = 3*PID_A.maxout; // cut away
        else
        if((PID_A.integr) <-3*PID_A.maxout) PID_A.integr =-3*PID_A.maxout;
    
        PWMpwr= (PID_A.P*PID_A.err) + (PID_A.I*PID_A.integr)*tprop + (PID_A.D*(PID_A.err-errorold))/tprop;
    
    
        if(PWMpwr >  PID_A.maxout) PWMpwr=  PID_A.maxout;   // forward maxout
        else
        if(PWMpwr < -PID_A.maxout) PWMpwr= -PID_A.maxout;   // reverse maxout
    
    
        PID_A.speed= (PID_A.read-readold)*100/dtime;  // rotat speed [degrees/100ms]
    
        aspeed = abs(PID_A.speed) ;
    
        if (aspeed > PID_A.tarpwm)  {
            PWMpwr = sign(PWMpwr)*PID_A.tarpwm;
        }
    
        PID_A.outp = round(PWMpwr);
    
    
    
    
        //**************************************************************************
                                                       // PID regulation !
        OnFwd(OUT_A, (PID_A.outp));                         // action !
        Wait(PID_A.regtime);                                // wait regulation time
    
        //**************************************************************************
    
        readold     = PID_A.read;                           // save old sensor
        errorold    = PID_A.err;                            // save old error
    
        PID_A.read  = (MotorRotationCount(OUT_A));          // get new encoder value
        PID_A.err   = PID_A.target-PID_A.read;              // new error to target
    
        if (PID_A.read>cmax) cmax=PID_A.read;               // monitor overshooting
        else
        if (PID_A.read<cmin) cmin=PID_A.read;               // monitor overshooting
    
        if ((PID_A.cont)&& (abs(PID_A.err)<=PID_A.precis)) PID_A.runstate = 0x60;
        else PID_A.runstate = 0x20;
    
    
        if (PID_A.cont) continue;
        if (abs(PID_A.err)<=PID_A.precis) { regloop +=1 ; PID_A.runstate = 0x40; }
    
      } while ((abs(PID_A.err)>=PID_A.precis) && (regloop<=5));  // target reached
    
      Off(OUT_A);                                      // finished - brake motor
      PID_A.runstate = 0x40;                           // run state: RAMPDOWN
      PID_A.outp=0;
    
      Wait(50);
      PID_A.read = MotorRotationCount(OUT_A);
      regloop=1;
    
      if (PID_A.read>cmax) cmax=PID_A.read;            // detect overshooting
      if (PID_A.read<cmin) cmin=PID_A.read;            // detect overshooting
      PID_A.err = PID_A.target-PID_A.read;
    
    
      if ((abs(PID_A.err)>PID_A.precis))  {goto _Astart;}
    
    
      PID_A.runstate=0;
      Wait(1);                                //runstate = IDLE
    
    }
    aufgerufen werden soll das Objekt bzw. seine Instanz mit seinem Task von so einer Funktion
    (port == "Motornummer" oder auch A, B, C, D, E,.... ):
    Code:
    void RotatePIDtoTarget (char port, long Target, float RotatSpeed); // approach absolute target once
    void RotatePIDdegrees  (char port, long Target, float RotatSpeed); // turn relative degrees
    void RotatePIDcontinue (char port, long Target, float RotatSpeed); // approach target continuously
    void StopPIDcontrol    (char port);                                // stop PIDummer):


    Das Objekt soll wie diese Struktur aussehen plus alle notwendigen Hilfs-Funktionen und pthread-tasks enthalten, damit sie von allen Instanzen benutzt werden können (kann eigentlich alles public sein):

    Code:
    struct PIDstruct {
                     // custom target values
      long  target;                  // set target
      int   tarpwm;                  // motor target speed
                     // custom regulation parameters
      float P;                       // P: proportional to error
      float I;                       // I: integral: avoid perish
      float D;                       // D: derivative: avoid oscillating
      float precis;                  // error precision to target
      int   regtime;                 // PID loop time
      float damp;                    // damp the integral memory
      char  cont;                    // target: continue or hit once
                     // internal control variables
      char  runstate;                // monitors runstate
      int   outp;                    // PID control output value
      int   maxout;                  // max output (max motor pwr)
      long  read;                    // current sensor reading
      float err;                     // current error
      float integr;                  // integral of errors
      float speed;                   // current speed
    
    
    } ;
    - - - Aktualisiert - - -

    edit:
    ich muss auch sagen, die Erklärungen in http://stackoverflow.com/questions/1...n-from-a-class sind mir erheblich zu schwierig - ich habe bisher nie selber Klassen erstellt - mein Code ist fast immer nur ANSI C. Wahrscheinlich muss ich das aufgeben, wenn es wirklich so kompliziert sein muss.

  6. #6
    shedepe
    Gast
    Gibt es einen Grund warum es pthread direkt sein muss und das C++ 11 frontend nicht? (Btw. du redest über Tasks meinst aber Threads. Das ist ein ziemlicher Unterschied)
    Mit C++ 11 ist es super einfach einen Thread in einer klasse laufen zulassen (Siehe Post von Mxt - Wobei der Code meiner Ansicht nach so nicht funktionieren wird
    Ich finde das Beispiel auf Stackoverflow ganz gut: https://stackoverflow.com/questions/...ethod-of-class
    Wenn du unbedingt direkt auf die pthread API programmieren willst wirst du um eine kompliziertere Lösung wie hier ( https://stackoverflow.com/questions/...start-function ) nicht drumherumkommen.

Ähnliche Themen

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

Berechtigungen

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

12V Akku bauen