Design Problem



  • Hallo,

    seit längerem arbeite ich schon an einem Projekt, um einen Hexapoden (6-beiniger Roboter) zu bauen.
    Die Klassenstruktur ist ungefähr folgender:

    Hexapod -> besitzt sechs Beine -> jedes Bein besitzt 3 Servos -> Jeder Servo hat ist einem von zwei Servocontrollern zugeordnet.
    Wichtig zu erwähnen ist noch, dass jeder Servo individuell ist. Bedeutet er hat mehrere Attribute, die dem Konstruktor übergeben werden, die sich unterscheiden.
    Dementsprechend stellt sich natürlich die Frage, wie initialisiere ich diese ganzen Objekte.
    Bisher bin ich so gefahren:

    Hexapod Konstruktor: Zwei Servocontroller erzeugen + alle 6 Beine erzeugen (und in den {} auch die Servos erzeugen und den Servocontroller als Referenz direkt den Servos übergeben).
    Sieht so aus in der initializer list.

    servocontroller1 { Servocontroller {0x40}}, servocontroller2 {Servocontroller {0x41}},
      legs {
        // Left (Front - Middle - Rear)
        Leg { Servo {servocontroller1,  0, 105, 465}, Servo {servocontroller1,  1, 100, 470}, Servo {servocontroller1,  2, 110, 467}, Point<int16_t> {0, 75, -150}, 85,  62},
        Leg { Servo {servocontroller1,  5, 130, 400}, Servo {servocontroller1,  6, 100, 475}, Servo {servocontroller1,  7,  85, 445}, Point<int16_t> {0, 75, -150}, 65,   0},
        Leg { Servo {servocontroller1, 13,  85, 435}, Servo {servocontroller1, 14, 132, 492}, Servo {servocontroller1, 15, 100, 470}, Point<int16_t> {0, 75, -150}, 85, 298},
        // Right(Front - Middle - Rear)
        Leg { Servo {servocontroller2, 13, 120, 450}, Servo {servocontroller2, 14,  85, 455}, Servo {servocontroller2, 15,  95, 380}, Point<int16_t> {0, 75, -150}, 85, 118},
        Leg { Servo {servocontroller2,  5, 130, 415}, Servo {servocontroller2,  6, 100, 445}, Servo {servocontroller2,  7,  89, 460}, Point<int16_t> {0, 75, -150}, 65, 180},
        Leg { Servo {servocontroller2,  0,  85, 445}, Servo {servocontroller2,  1, 105, 458}, Servo {servocontroller2,  2,  80, 370}, Point<int16_t> {0, 75, -150}, 85, 242}
      }
    

    Ob das so toll gelöst ist, da zweifle ich schon länger dran, aber es hat seinen Zweck erstmal erfüllt. Wichtig zu wissen ist noch, dass es ein avr ist ... keine C++ Standardbibliothek verfügbar ... legs ist dementsprechend ein reines C Array.

    Nun hat sich folgendes noch ergeben. Um Interrupts mehr objektorientiert zu integrieren, benötige ich eine weitere Klasse ServoManager, das ein Array mit allen Servos hat. Jetzt bin ich zugeben etwas ratlos wie ich das ganze am Geschicktesten anstelle.
    Mitterweile steht aber immerhin ein CArray Wrapper zur Verfügung, der ähnlich wie std::array funktionieren soll (nur als Hinweis).

    Meine Idee war jetzt, die Servo Erzeugung in den Konstruktor des ServoManagers zu legen. Der ServoManager würde ich als Attribut der Klasse Hexapod machen und dort erzeugen und per Referenz an die Beine weitergeben inklusive einer Nummer (0-5). In dem Konstruktor der Leg Klasse, kann man dann mit Hilfe des ServoManagers und einer Methode z.B: getServo(index), die entsprechenden drei Servos bekommen. Eben als Index die übergebene Nummer +0, +1, +2.
    In dem Fall würde mich interessieren:
    Sollten die drei Servos, die in der Klasse Leg gespeichert werden Referenzen oder Pointer sein?

    Oder ist der Ansatz sowieso kompletter Müll und man sollte es anders machen? Meine aller erste Idee (die ich auch umgesetzt hatte) war den ServoManager als Singelton in einem anonymen Namespace zu machen. So konnten die Servos auf ihn zugreifen (aber sonst niemand) und sich quasi selbst registrieren. Da das Array statisch ist, musste man per static int allerdings speichern, wie viele Servos sich schon registriert haben. Das war für mich irgendwie ein Anzeichen, dass es ein falscher Ansatz ist. Dynamisches Array möchte ich auf einem avr vermeiden.

    Vielen Dank 🙂


Log in to reply