- Labornetzteil AliExpress         
Seite 2 von 15 ErsteErste 123412 ... LetzteLetzte
Ergebnis 11 bis 20 von 144

Thema: Algorithmen zur Bahnplanung

  1. #11
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    Anzeige

    Powerstation Test
    @Sternthaler,

    freut mich sehr, dass Dir meine Rechnerei verständlich ist! Deine Fragen bestätigen das. Hier sind die Antworten:

    Formel (1): Nee, Rr und Rl müssen nicht gleich gross sein. Das ist einer der Vorteile dieses Algorithmus, das man damit auch Asuros lenken kann, die unterschiedlich grosse Räder und unterschiedlich starke Motoren haben. Man kann den Algorithmus praktisch an jeden Dreirad-Roboter anpassen.

    Einheiten: Können ganz nach Belieben gewählt werden, müssen dann aber durchgängig eingehalten werden. Wegen der üblichen Dimensionen heutiger Wohnzimmer oder Küchentische würde ich für die Längen Zentimeter und für die Zeiten Sekunden verwenden. Aber wie gesagt, Meter und Minuten geht auch.

    Formel 7: Vektoren in der x-y-Ebene kann man um 90° drehen, indem man x- und y-Komponente vertauscht und dann das Vorzeichen der neuen x-Komponente umkehrt. Diesen Trick verwende ich hier, um aus der Längs- (sprich: der Fahrtrichtung ep) die Querrichtung eq auszurechnen. Die Drehung der Fahrtrichtung durch die unterschiedlich schnell laufenden Räder stelle ich dar, indem ich zum Einheitsvektor in Längsrichtung ein bisschen vom Einheitsvekor in Querrichtung dazuzähle. Das dreht den Längsvektor, macht ihn aber auch ein bisschen zu lang. Deshalb muss er anschliessend wieder neu normiert werden.

    Doppelte Formelnummern: Ächz! Es war schon spät. Hab sie in Version V02 korrigiert.

    Zielpositions-Abweichung: Ja, in der Formel (jetzt Nr. 12) wird der Zielort immer mit denselben Koordinaten xs und ys eingesetzt. Was sich verändert , sind die Koordinaten xi und yi des Roboters und seine Fahrtrichtung, ausgedrückt durch px und py. Formel (12) verwendet das Kreuzprodukt zwischen der Fahrtrichtung und dem Differenzvektor vom Ort des Roboters zum Zielort.

    Schneckentempo: Ja, Du hast recht. Es ist so wie mit Achilles und der Schildkröte: Je näher der Roboter dem Ziel kommt, desto langsamer wird er und er wird wegen der Reibung auch vor Erreichen des Zielorts zum Stehen kommen. Man kann diese Restdistanz in Grenzen mit dem P-Parameter des Fahrtgeschwindigkeits-Reglers einstellen. Oder aber man lässt den Regler die Fahrtgeschwindigkeit nur bis zu einem Minimalwert absenken und schaltet dann bei Erreichen des Ziels die Motoren ganz ab. Hängt ganz davon ab, ob man danach noch weitere Ziele anfahren will oder sonst noch was vor hat.

    Ich habe die korrigierte Version 02 wieder angehängt. Darin präzisiere ich auch die Impulszählung (nr und nl) besser: Es dürfen ja immer nur die Impulse in die Berechnung eingehen, die seit der letzten Ablesung dazugekommen sind.

    Jetzt ist nur noch die Frage, wie sich sowas mit dem Reglungskonzept eines Asuro verträgt.

    Ciao,

    mare_crisium

    Edit: Anhang gelöscht wg. Upload-Quota

  2. #12
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    Hallo mare_crisium,
    oh kopfschüttel,
    klar einen senkrechten Vektor kann man ja genau so ausrechnen. (Ist ganz einfach, wenn man einen gut erkläten Tritt in den Hintern bekommt.)

    Mit den Einheiten bin ich einverstanden. Auch bei uns läßt sich der Küchentisch noch locker in cm ausdrücken, ohne den "unsigned char"-Bereich zu verlassen.

    Mit den Rr und Rl bzw. N(rl) und n(rl) komme ich zu dieser Uhrzeit noch nicht klar. Im Moment sehe ich in (1) nur, dass du (PI * Rr / Nr) ausklammerst aus den beiden Geschwindigkeiten vr und vl. Weiters Grübeln ist da bei mir angesagt.

    Zielpositions-Abweichung: Gut gebrüllt Löve. Ähh, gut erklärt. Ist mir nun auch klar geworden. Danke.

    Zum Reglungskonzept im Asuro kann ich nur auf den Beitrag von waste hier hinweisen. Den von waste erstellten Code kann man sehr schön als allround-Code nutzen. Das Geheimnis bleibt natürlich in den PID-Parametern für die entsprechende Aufgabe.

    Hier ist mal meine aktuelle Version vom Regelcode:
    Code:
    /*****************************************************************************
       FUNKTION:   MotorPID
       Aufgabe:    Funktion zur Reglung der Motoren.
                   Diese Funktion bzw. die eigendliche Berechnung fuer die
                   Reglung wurde im Forum unter www.roboternetz.de von waste
                   entwickelt.
                   Von Sternthaler ist die Moeglichkeit hinzugefuegt, die
                   Reglerberechnung fuer unterschiedliche Regelaufgaben zu
                   nutzen.
                   Die Parameter steuern, welche Sensoren zur Reglung benutzt
                   werden sollen. Zum einen koennen es die Liniensensoren sein
                   um eine Linienverfolgung zu realisieren, zum anderen kann
                   der Regler zur Ueberwachung der Raddecoder genutzt werden.
       Parameter:  
    *****************************************************************************/
             unsigned char  MotorPID (
             unsigned char  regler,
                      char  speed,
                      int   links,
                      int   rechts)
    {
                      int   LWert = 0, RWert = 0;
                      int   absLinks = 0, absRechts = 0;
                      float faktor;
    static            int   x, x1, x2, x3, x4;
    static            int   xalt, drest, isum;
                      int   kp = 0, kd = 0, ki = 0;
                      int   yp, yd, yi, y, y2;
                      int   LSpeed,	RSpeed;
             unsigned char  LDir,   RDir;
             unsigned char  use_regler = TRUE;
    
       switch (regler)
       {
       case PID_LINIE:
          links = rechts = 1;                 // erzwingt vorwaertsfahrt
          LineData ();                        // Liniensensoren
          LWert = sens.linie [LINKS_DUNKEL] - sens.linie [RECHTS_DUNKEL];
          RWert = sens.linie [LINKS_HELL]   - sens.linie [RECHTS_HELL];
          /* DIESE PARAMETER WURDEN VON waste IM FORUM UNTER
             https://www.roboternetz.de
             ENTWICKELT.
          */
          kp = 5;              // Parameter kd enthält bereits Division durch dt
          ki = 5;
          kd = 70;
          break;
       case PID_ODOMETRIE:
          if (links == 0 || rechts == 0)
             use_regler = FALSE;
          else
          {
             absLinks  = abs (links);
             absRechts = abs (rechts);
             /* Odometrie-Zaehler so justieren, dass fuer eine Kurvenfahrt
                die Tic-Anzahl auf beiden Seiten identisch aussehen.
                Die Seite auf der weniger Tic's zu fahren sind wird auf die
                hoehere Anzahl 'hochgerechnet'.
             */
             if (absLinks < absRechts)
             {
                faktor = (float)absRechts / (float)absLinks;
                LWert = sens.rad_tik [LINKS] * faktor;
                RWert = sens.rad_tik [RECHTS];
             }
             else
             {
                faktor = (float)absLinks / (float)absRechts;
                LWert = sens.rad_tik [LINKS];
                RWert = sens.rad_tik [RECHTS] * faktor;
             }
             /* Diese Parameter wurden von Sternthaler durch probieren ermittelt.
             */
             kp = 65;
             ki = 6;
             kd = 90;
          }
          break;
       }
    
       LSpeed = (int)(speed - hw.motor_diff / 2);   //Wunschgeschwindigkeit vorgeben
       RSpeed = (int)(speed + hw.motor_diff / 2);   //Hardware beruecksichtigen
    
       if (use_regler == TRUE)
       {
          /* AB HIER IST DIE BERECHNUNG VON waste IM FORUM UNTER
             https://www.roboternetz.de
             ENTWICKELT WORDEN.
          */
          x1 = RWert - LWert;                 // Regelabweichung
    
          x = (x1 + x2 + x3 + x4) / 4;        // Filtert die 4 letzten Werte
          x4 = x3; x3 = x2; x2 = x1;          // Pipe ueber die letzten 4 Werte
    
          isum += x;                          // I-Anteil berechnen
          if (isum >  16000) isum =  16000;   // Begrenzung: Überlauf vermeiden
          if (isum < -16000) isum = -16000;
          yi = isum / 625 * ki;
    
          yd = (x - xalt) * kd;               // D-Anteil berechnen und mit nicht
          yd += drest;                        // berücksichtigtem Rest addieren
          if (yd > 255) drest = yd - 255;     // Eventuellen D-Rest merken
          else if (yd < -255) drest = yd + 255;
          else drest = 0;
    
          yp = x * kp;                        // P-Anteil berechnen
    
          y = yp + yi + yd;                   // Gesamtkorrektur
          y2 = y / 2;                         // Aufteilung auf beide Motoren
          xalt = x;                           // x merken
    
          if (y > 0)                          // Abweichung nach rechts
          {
             LSpeed += y2;                    // links beschleunigen
             if (LSpeed > 255)                // wenn Wertebereich ueberschritten
             {
                y2 += (LSpeed - 255);         // dann Rest rechts berücksichtigen
                LSpeed = 255;                 // und Begrenzen
             }
             RSpeed -= y2;                    // rechts abbremsen
             if (RSpeed < 0)                  // Auch hier Wertebereich
             {
                RSpeed = 0;                   // beruecksichtigen
             }
          }
          if (y < 0)                          // Abweichung nach links
          {
             RSpeed -= y2;                    // rechts beschleunigen
             if (RSpeed > 255)                // wenn Wertebereich ueberschritten
             {
                y2 -= (RSpeed - 255);         // dann Rest links berücksichtigen
                RSpeed = 255;                 // und Begrenzen
             }
             LSpeed += y2;                    // links abbremsen
             if (LSpeed < 0)                  // Auch hier Wertebereich
             {
                LSpeed = 0;                   // beruecksichtigen
             }
          }
       }
    
       /* Und wieder (fast) waste
       */
       if (links >0) LDir = FWD; else if (links <0) LDir = RWD; else LDir = BREAK;
       if (rechts>0) RDir = FWD; else if (rechts<0) RDir = RWD; else RDir = BREAK;
    
       if (LSpeed < 20) LDir = BREAK;         // richtig bremsen
       if (RSpeed < 20) RDir = BREAK; 
       MotorDir   (     LDir,         RDir);
       MotorSpeed (abs (LSpeed), abs (RSpeed));
    
       return 0;
    }
    Ist so angepasst, dass sowohl der ehemalige von waste programmierte Zweck zur Linienverfolgung, als auch eine Reglung für ein Geradeausfahren, nun möglich sind. Klar, der Aufrufer muss ein abgestimmtes Timing haben, sonst stimmen die zeitabhängigen PID-Parameter nicht zur Regelungsaufgabe. Da waste im 2ms-Raster rechnete, sollte das Ding halt alle 2ms aufgerufen werden.
    Aktuell geht es in dieser Version nicht, dass beide Regler gleichzeitig nutzbar sind, da innerhalb der Funktion die genuzten static-Variablen nur einmal vorhanden sind. Erzeugt man ein Array für die Variablen mit Variable/Parameter regler als Index, sollte das auch erledigt sein.
    Ich sehe gerade, dass noch ein bisschen 'Beiwerk' fehlt.
    - Variable hw.motor_diff kann mit 0 ersetzt werden.
    - Variablen sens.linie[0-3] sind die automatisch im Interrupt ermittelten Messwerte der Liniensensoren für links/Rechts Hell-/Dunkelmessung
    - Variablen sens.rad_tik[0-1] sind die, auch im Interrupt, ermittelten Hell-/Dunkelwechsel an den Odometriescheiben.
    (Bei Bedarf poste ich den kompletten Code)


    Mal sehen, wann wir google mit einem Asuro auf dem Mond überraschen

    Eine Gute Nacht wünscht Sternthaler
    Lieber Asuro programieren als arbeiten gehen.

  3. #13
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    Guten Abend (diesmal nicht Nacht!!), Sternthaler,

    danke für Deine Anmerkungen zu meinem Algorithmus! Oh, Mann, hätte ich Deine erste Mail gleich richtig gelesen, dann hätte mir der Fehler schon gestern auffallen müssen! Natürlich kann man die Radien nur vor die Klammer ziehen, wenn sie gleich sind. -

    Ich habe den Fehler in der angehängten Version 03 verbessert und auch die Erklärung für das Vertauschen der Komponenten eingefügt. Als Goodie habe ich noch eine Erweiterung angefügt, mit der man den Roboter dazu kriegt, einen Zielort anzusteuern und ihn in einer vorbestimmten Richtung zu durchfahren.

    - Dein Programm kann ich nicht so gut lesen, weil ich mich bisher immer geweigert habe, C auch nur mit spitzen Fingern anzufassen. Ich mache auf dem AVR alles in Assembler und auf dem PC mit Delphi oder Lazaraus. Aber ich versuch's mal.

    Ciao und schönen Abende,

    mare_crisium

    Edit: Anhang gelöscht, wg. Upload-Quota

  4. #14
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    Hallo mare_crisium, irgendwie schwächeln wir so mitten in der Arbeitswoche. Auch bei mir wird es immer früher.

    Deine Erklärung mit dem Jadhund ist für mich total einleuchtend. So stelle ich mir angewande Mathematik vor \/

    Bei der Ermittlung der Regelabweichung, bzw. welche benutzt werden soll, in Formel (14) könnte es eventuell ein Problem geben, wenn beide Abweichungen genau den gleichen Betrag haben, aber die Vorzeichen unterschiedlich sind. Dann liefert die Funktion doch eine Abweichung von 0.
    Mach dies Sinn, oder ist dieser Zustand nur kurzfristig zu erwarten, da die Maschine ja noch fährt und alles im Fluß ist?

    Sonst kann ich nur sagen: Das ist endlich mal etwas handfestes.

    Ich glaube, ich muss demnächst ein paar Regler mit Parametern füttern.
    Bei mir dauert so was aber immer etwas.

    Noch einen schönen Abend wünscht Sternthaler

    P.S.: Heißt das wirklich Lazaraus und nicht Lazarus? Unter Lazarus kenne ich eine IDE für Pascal, glaube ich.
    Lieber Asuro programieren als arbeiten gehen.

  5. #15
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    Nur um die Nachteulen-Ehre zu retten: Buona notte, Sternthaler,

    es freut mich richtig, dass Du was damit anfangen kannst! - Der Zustand, in dem sich in Formel (14) beide Stellsignale kompensieren, ist nur vorübergehend. Es wäre ein grosser Zufall, wenn bei der nächsten Berechnungsrunde, nachdem sich der Roboter weiterbewegt hat, wieder eine Null herauskommt.

    Ja, natürlich hätte es Lazarus heissen müssen und es ist eine IDE für Free Pascal. Ich habe mal in der Schweiz gearbeitet und seither habe ich eine Schwäche für die Sprachen von Herrn Wirth .

    Mit dem Einstellen von Reglerparametern habe ich ziemlich viel Erfahrung. Wenn Du so weit bist, meld' Dich nochmal!

    Ciao,

    mare_crisium

  6. #16
    So, erstmal danke für die vielen Antworten. War ein paar Tage weg und hab sie erst jetzt gesehen. Der A* Pathfinding for Beginners Artikel und die Webseite davon sehen vielversprechend aus, der Rest etwas kompliziert. Aber ich werde mir jetzt erstmal alles genauer anschauen.

    Nochmal zu meiner Frage. Der Roboter soll:
    1. einzelne Punkte im Raum anfahren können
    2. den ganzen Raum möglichst vollständig abfahren

    So wie ich das bis jetzt sehe ist der A* ist für Punkt 1 gut. Was gibt es für Punkt 2?

  7. #17
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    @JackBauer,

    schön, dass Du noch dabei bist! Einen Vorschlag für Deinen Punkt 2 habe ich noch nicht, weil ich dazu mehr Details über Deine Aufgabenstellung wissen müsste. Meld' Dich mal, wenn Du Dir alles genauer angesehen hast. -

    Übrigens: Der A*-Algorithmus allein wird Dir nicht helfen, denn um den zur Navigation anzuwenden zu können, muss Dein Roboter wissen, in welchem Planquadrat er sich gerade aufhält und was seine augenblickliche Fahrtrichtung ist. Das kann er nur, wenn Du in Dein Projekt auch etwas "Kompliziertes", mindestens eine Koppelnavigation, einbaust.

    Ciao,

    mare_crisium

  8. #18
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    @Sternthaler,

    bin heute morgen aus dem Bett gefallen und hatte dann Zeit genug, mir was zu Deiner Programmstruktur auszudenken . Ich hänge das kommentierte Programm als pdf-Datei an.

    Ciao,

    mare_crisium

    Edit: Anhang gelöscht wg. Upload-Quota

  9. #19
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    @mare_crisium,
    ach du Ärmster. Am Wochenende um 6:33 schon am PC hocken? Mir würde man dann eher nachsagen, dass ich durchgemacht hätte. Hatte ich eigendlich auch von dir angenommen
    Jedenfalls hast du die Zeit gut genutzt und dich in C perfekt eingearbeitet um dann so viel Mathe und Vorschläge in das Programm zu bringen, dass mir die Ohren flattern.

    Ja, das mit dem Datenrecorder wäre schon genau das Richtige. Nur würde ich diese Möglichkeit keinesfalls auslagern, sondern bewußt in der MotorPID()-Funktion integrieren. Dann kann auch auch nicht vergessen werden diese Datenrecorder-Funktion aufzurufen.
    Etwa folgendermaßen:
    Code:
           unsigned char  MotorPID (
             unsigned char  regler,
                      char  speed,
                      int   links,
                      int   rechts)
    {
    /* Speicher für den Datenrecorder */
    static            int   x  [ANZ_REGLER], xalt [ANZ_REGLER];
    static            int   x1 [ANZ_REGLER], x2 [ANZ_REGLER];
    static            int   x3 [ANZ_REGLER], x4 [ANZ_REGLER];
    static            int   drest [ANZ_REGLER];
    static            int   isum [ANZ_REGLER];
    
    /* Die lokalen Arbeitsvariablen */
                      int   x,                 xalt;
                      int   x1,                x2;
                      int   x3,                x4;
                      int   drest;
                      int   isum;
      .
      .
    
       /* Die lokalen Arbeitsvariablen mit den 'Recorderdaten' füttern. */
       x     = x [regler];
       xalt  = xalt [regler];
       x1    = x1 [regler];
       x2    = x2 [regler];
       x3    = x3 [regler];
       x4    = x4 [regler];
       drest = drest [regler];
       isum  = isum [regler];
    
       switch (regler)
       {
       case PID_LINIE:
          .
          .
          break;
       case PID_xxxx:
          .
          .
          break;
       case PID_yyyy:
          .
          .
          break;
       }
       .
       .
    
       /* Die lokalen Arbeitsvariablen in den 'Recorderdaten' sichern. */
       x [regler]     = x;
       xalt [regler]  = xalt;
       x1 [regler]    = x1;
       x2 [regler]    = x2;
       x3 [regler]    = x3;
       x4 [regler]    = x4;
       drest [regler] = drest;
       isum [regler]  = isum;
    }
    Das ist aber nur technischer Schnickschnack.

    Zu den anderen Anmerkungen kann ich leider nichts sagen. Da ist mir die Mathematik zu weit weg, von meinem Hausgebrauch-Rechnen.
    Ein Hinweis evl. zu der Halbierung des berechneten y-Korrekturwertes. Waste teilt hier, so wie ich es Verstanden hatte, ja den Gesamt-Korrekturwert doch nur auf beide Motoren auf. Da mir dies bei der 'Verfolgung der Zusammenhänge' in seinem Thread eigendlich recht einleuchtend vorkam, ist das doch dann die logische Konsequenz daraus. Warum also den Weg zur Ermittlung der Parameter schon so gestalten, dass man hinterher nicht mehr 'nur' durch 2 teilen muss?

    Auch hätte ich Probleme beim Auslagern der endgültigen 'Einstellerei' der Motor-Leistung und den Motor-Richtungen. Wobei die Berechnung der linken/rechten Motorwerte wieder über 'Summen', 'Quotienten' und 'sonstig kompliziertem' ausserhalb erfolgen muss.
    Das halte ich für kritisch, da ich es eher sehen würde, dass sich eine Funktion (von mir aus auch mit Hilfsfunktionen, die ich aber nie in meinem Hauptprogramm aufrufe) um ihren Kram komplett alleine kümmern soll.
    Ich selbst würde die Parameter so halten, dass meine Wünsche da rein gehen. Hier also etwa: 'Mittlere Geschwindigkeit'; 'Absolute Anzahl Tiks links+Absolute Anzahl Tiks rechts'; oder 'Zielkoordinate X+Zielkoordinate Y'. Das Ganze sollte dann die Funktion 'von alleine' auflösen und sich dann die benötigten Messwerte holen, berechnen und irgendwie sinnvolle 'Summen' und 'Quotienten' bilden.

    Natürlich kann man deinen Vorschlag ja auch in einer Funktion 'verpacken' und hätte dann meine Vorstellung erhalten. (Wie viel Wege führten nochmal nach Rom?)


    Ob die Mittelwertbildung durch eine Anpassung an dem P-Regelwert überflüßig ist kann ich nicht beurteilen. Allerdings würde ich nicht so pauschal sagen, dass nur die Liniensensoren streuen. Auch die Odometriedaten sind nicht so richtig sauber.
    Aber wenn ein neuer P-Wert das alles ausbügeln kann, dann nichts wie weg mit dem Mittelwert.

    Tja, und bei dem Rest kann ich nur sagen: Der "Alzheimer"-Faktor ist bei mir auf alle Fälle > 1, wenn es um die ehemals im Studium gelernte Mathematik geht.

    Einen schönen Rest-Sonntag wünsche ich noch.
    Gruß Sternthaler
    Lieber Asuro programieren als arbeiten gehen.

  10. #20
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    Sternthaler,

    oh, je! So heftig wollte ich am heiligen Sonntag Morgen Deine Ohren nicht misshandeln ! - Mir kamen die paar Kommentare, die ich Dir ins Programm geschrieben habe, viel einfacher vor, als das Vektor-Jonglieren bei dem Du voher so tapfer mitgehalten hattest.

    Es gibt nichts Schlimmeres, als ein gut laufendes Programm zu "verbessern". Deshalb habe ich vollstes Verständnis für Deinen Entschluss, es so zu lassen wie's jetzt ist. Hauptsache ist, die Beschäftigung mit dem Thema macht Spass!

    Ciao,

    mare_crisium

Seite 2 von 15 ErsteErste 123412 ... LetzteLetzte

Berechtigungen

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

fchao-Sinus-Wechselrichter AliExpress