Software-Modellierung, UML-Klassendiagramme usw.

cadaver

Moderator
Hallo,

da die Aufgaben der Steuerung immer weiter zunehmen, ist wohl an der Zeit die Software besser zu strukturieren, typischerweise in Form von (C++)-Klassen. Bevor allerdings losprogrammiert wird, ist es ratsam die Ideen einmal grafisch in Form von UML-Klassendiagrammen darzustellen.

Hier also meine Ideen für das zukünftige Klassen-Layout einer modularen Mähroboter-Software (UML-Klassendiagramm Anhang).

Erklärung der einzelnen Klassen im angefügten Diagramm:

Robot: C++ Oberklasse für alle Roboter. Enthält keine Zugriffe auf die konkrete Hardware, definiert aber Methoden hierfür.

int readSensor(...) = 0; // abstrakt
void setActuator(...) = 0; // abstrakt

Konkrete Roboter leiten von dieser C++ Klasse ab um diese Methoden mit Leben zu füllen. Die Klasse implementiert den gesamten Roboter-Code welcher allen Mährobotern gemeinsam ist. Die Klasse Robot enthält Zugriff auf "Behavior-Klassen" welche die "Subsumption"-Architektur umsetzen. Mit Hilfe dieser Architektur kann das Verhalten des Roboters flexibel angepaßt werden. In den Beavior-Klassen erfolgt der Zugriff auf den Roboter über die Roboter-Klasse ( polymorph ).

Mower: Abgeleitete C++ Klasse. Implementiert den konkreten Ardumower. Hier erfolgen Zugriffe auf die Hardware.

int readSensor(...);
void setActuator(...);

Simulator: Abgeleitete C++ Klasse. Implementiert den Ardumower als Simulator. Hier erfolgen Zugriffe auf die spätere Simulator-Umgebung anstatt auf Hardware.

Behavior: Oberklasse für ein Verhalten. Definiert Methoden für die Subsumption-Architektur.

ObstacleBehavior: Abgeleitete C++ Klasse. Implementiert das Verhalten bei Hindernissen.

MowBehavoir: Abgeleitete C++ Klasse. Implementiert das normale Mähverhalten (typischerweise geradeausfahren).

ManualBehavor: Abgeleitete C++ Klasse. Implementiert das Verhalten für manuelle Steuerung.

TrackBeahvor: Abgeleitete C++ Klasse. Implementiert das Abfahren der Schleife.



Die Ideen dieser Software-Architektur sind diversen Roboterplattformen entnommen worden...

Weitere Ideen/Anregungen sind willkommen :)
 
Hallo Alexander,


die Aufteilung macht bestimmt Sinn. Es dürfte damit wesentlich einfacher werden, neue Hardware zu Implentieren und übersichtlicher wird es bestimmt auch.

Könnte man dafür sich nicht einem Projekt wie ros.org bedienen ?

Wenn ich das richtig verstanden hab wird dort viel in der Richtung gemacht. Ich hab allerdings von Roboter Programmierung noch keine Erfahrung.

Stefan
 
Evtl noch folgende Klasse

- Kommunikation (BT, Wlan)


Das ganze hört sich ja nach völliger Neuprogrammierung an. Gewaltige Aufgabe!

Da ihr ja auch Programmierer sucht, möchte ich vorschlagen das ganze dann nicht schnell sondern gründlich umzusetzen.
Mit viel mehr Dokumentation über die Schnittstellen zwischen den Klassen, Vor allem mehr und ausführlichere Kommentare im Code.

Das erleichtert es sicher zusätzliche Progammierer zu finden weil die Einarbeitung schneller zu erledigen ist.
Außerdem ist es vieleicht besser das Fehlermeldesystem vom SVN zu nutzen und alle die Testen dafür freizuschalten.
 
Wichtig ist sicherlich, dass die Schnittstellen frühzeitig klar definiert werden.
Gibt es da schon etwas für die Schnittstelle zwischen Robot und Behavoir? Ich habe
mich in letzter Zeit etwas mit Roboter-Simulatoren (Stage/Gazebo, MRPT) beschäftigt.
Falls gewünscht könnte ich mich da tiefer einlesen und Vorschläge für die
Schnittstelle machen.
 
In der aktuellen R66 stehen Behaviours zu verschiedenen States, was mir da noch fehlt, ist das Timer-Behaviour, mit dem zwischen verschiedenen Staates gewechselt werden kann.
"GoHome" Behaviors
1. OFF
2. Error
3. Charging
4. Avoidance
5. TrackPerimeter
6. FindPerimeter


"StartMow" Behaviors
1. OFF
2. Error
3. Avoidance
4. FindStartPosition
5. Mow


"RemoteControl" Behaviors
1. OFF
2. Error
3. RemoteControl

Das Timerbehaviour müsste nun bei bei Gohome den Startmow anschalten können. Und umgekehrt aus dem Startmow in den Gohome wechseln. Oder wie ist ein Wechsel der States angedacht?

Gruß,
Jem
 
@Jem: ja, ein Timer-Behavior o.ä. muss da noch hinein - Roboter-Verhaltens-Programmierung (Aritifical Intelligence etc.) ist für mich völliges Neuland, also schaut man erstmal wie andere das so umsetzen. Es gibt noch weitere Ansätze wie z.B.

-Hierarchische Zustandsautomaten (hierachy state machines) http://www.eventhelix.com/realtimemantra/hierarchicalstatemachine.htm#.U9PUU1fy2So
-Behavior Trees http://www.pirobot.org/blog/0030/
Grob betrachtet will man denke ich folgendes erreichen:
-Verhalten soll als ganzes und auch einzeln austauschbar sein (also nicht festverdrahtet alles in einer Datei wie bisher)
-bestimmtes Verhalten darf Reflex-artig ablaufen (wie z.B. Hindernißvermeidung), d.h. das aktuelle Verhalten unterbrechen

Desweiteren ist zu überlegen, ob es evtl. sinnvoll ist, ein RTOS (FreeRTOS) zu benutzen. Ein Vorteil wäre, dass Verhaltenscode lesbarer ist (Befehle dürfen Ablauf blockieren: rotate90degree, moveForward20cm,... ). Weiterer Vorteil ist dass man später Dinge wie z.B. Kalman-Filter für die Positionsermittlung mit hoher Frequenz (100 Hz) ablaufen lassen kann. FreeRTOS gibt es für Mega und Due - ist glaube ich mal einen Versuch Wert..
 
Zu dem FreeRTOS gab es in einer der letzten c't-Hacks einen ausführlichen Artikel mit einem Programm-Beispiel.

Wäre auf jeden Fall einen Versuch wert, hatte mich schon gefragt, wie du das Problem mit dem Arbitrator lösen willst. Ich hätte wahrscheinlich versucht, den Arbitrator in einen Interrupt zu packen, nur war mir jetzt auf Anhieb nicht klar, wie man dann vom Arbitrator auf die einzelnen Behaviours wieder zurück springt, bzw. einzelne Behaviours über Supress in ihre geregelte Stop-Teile bekommt, um dann in das neue Behaviour zu springen.

Ich lass mich von dir als Profi da gerne überraschen :)

Gruß,
Jem
 
@Jem: Ich habe mit RTOS bisher nichts zu tun gehabt.

Ich habe spaßeshalber mal die IMU als 100 Hz Task über FreeRTOS in einem Mini-Programm laufen lassen (Anhang). Leider stürtzt der Mega ab sobald die IMU-Klasse die AHRS-Klasse für die Berechnungen aufruft. Die Berechnungen sind harmloser Code. Es muss evtl. etwas mit der C++ Maschinerie des Compilers zu tun haben... Stack-Größe der Task vergrößern hat nichts gebracht.

Nachteilig scheint mir auch:
-RTOS ist nicht für C++ konzipiert worden
-Arduino ist nicht für RTOS konzipiert worden (die meisten Libs werden wohl nicht funktionieren)

Vielleicht hat jemand eine Idee warum der Mega in der Klasse IMU::getQ() abstützt...

Anhang:
FreeRTOS_AVR -> nach Programme/Arduino/Libraries kopieren
Attachment: https://forum.ardumower.de/data/media/kunena/attachments/905/freertos.zip/
 
Zuletzt bearbeitet von einem Moderator:
Wie ich mal in einem Thread gepostet habe, brauche ich beruflich nur C programmieren, bei C++ tue ich mich noch ein bissel schwer (nach DIN EN 13849 sind viele Merkmale von C++ in sicherheitsrelevanten Funktionen nicht erlaubt ...).

Ich schaue mal, ob ich den Artikel aus der c't finde, dann kann ich den mal abfotografieren ...

Gruß,
Jem
 
Ich hab ihn nicht gefunden, vielleicht war es auch nur ein kurzer "Info"-Artikel, denn ich habe einen anderen Artikel gefunden, der was mit Multitasking auf dem Arduino zu hat. Habe ich bestimmt verwechselt.

Hier sind die Seiten, am Besten die Bilder runterladen und dann drehen/bearbeiten. Sind jeweils 5 MB groß ... müsste also gut gehen.

DSC02455.JPG

DSC02456.JPG

DSC02458.JPG
 
@Jem: Danke für die Seiten. Dort wird der Timer-Interrupt verwendet.

Beim Konzept mit Timer-Interrupt muss man kurze Code-Abschnitte verwenden. Während der Timer aktiv ist, kann kein anderer Interrupt (z.B. von einem Sensor) aktiviert werden. Daher muss der Code im Timer sehr schnell ablaufen.

Das Konzept ist für komplexere Dinge wie z.B. den IMU-Algorithmus etc. nicht wirklich geeignet. Während dieser "langen" Zeit (z.B. 5ms) würde alles blockiert (AFAIK kennt der Mega keine verschachtelten Interrupts). Es könnte kein Odometrie-Interrupt auftreten oder ein Hall-Sensor Interrupt (beide kommen mit hoher Frequenz daher).

Es bleibt also nur preemptives Multitasking (à la Windows/RTOS) oder kooperatives Multitasking (à la Windows 3.1). Letzteres haben wir ja bereits im jetztigen Code drin, d.h. es wird immer alles durchlaufen ("Eventschleife") und bei jedem Durchlauf entschieden was zu tun ist. Hierbei darf natürlich kein Code den Ablauf blockieren (Stichwort Automaten). Interrupts können jederzeit auftreten und werden schnell abgearbeitet.
 
Deswegen hatte ich ja gedacht, nur den Arbitrator im Interrupt zu nutzen, da der ja recht übersichtlich gestaltet werden kann.

Und die IMU würde ich im Nano lassen, um den Mega nicht noch zusätzlich zu belasten. In meinen Mobilcontrollern im Beruf werden die rechenintensiven Funktionen auf verschiedene Hardware aufgeteilt, und dann mit recht hoher Frequenz über den 250kBit/s-CAN-Bus verteilt, dort laufen also über 20 CAN-Knoten, die im 10-100 ms-Takt ihre Daten melden oder Befehle entgegen nehmen. Der I2C-Bus hier ist sogar schneller und wir haben ja nur recht wenig Bus-Teilnehmer.

Oder hast du Leistungseinbußen durch die Kommunikation mit den Nanos bemerkt?
 
@Jem: Mich hat an der Multi-Controller Architektur gestört, dass man immer alles synchron halten muss (Updates, Bugfixes etc.). Gerade wenn dann neue Perimeter-Lösungen oder neue Schnittstellen zur Kalibrierung über Handy etc. hineinkommen, die sich hin- und wieder ändern, wird's richtig unübersichtlich (welche Version paßt nochmal wozu...)

Generell ist Multi-Controller ein interessanter Ansatz, dann müsste es m.E. aber konsequenter umgesetzt werden (Code für alle Controller in einem Projekt, Controller per Knopfdruck alle flashen)

Parallax (http://www.parallax.com) hat das mit seinen "Propellern" glaube ich so umgesetzt.

Und dann ist noch die Frage, ob z.B. die 84 Mhz eines Arduino Due nicht doch ausreichen (auch für den zukünftigen rechenintensive Kalman). 300-600 Mhz wären natürlich besser (je mehr, umso eindeutiger kann man die Frage mich ja beantworten).
 
Nachtrag: Den IMU-Code habe ich mit FreeRTOS nun zum Laufen bekommen. Ich habe die Ergebnis-Variable der IMU-Berechnung nun als "volatile" deklariert - glaube daran hatte es gelegen...
 
Ist der neue code schon Testbar?

Oder seid ihr noch in einer so frühen Phase der Umstellung, dass sich Testen auf dem Mower noch nicht lohnt?
 
@Dietmar: der "neue" Code (Ordner "ardumower1") ist komplett unvollständig - es sind noch zu viele Dinge umzusetzen die nicht vollständig geklärt sind und erstmal für sich prototypisch umgesetzt werden müssen (wie schaffen wir es, dass IMU und später Kalman mit 100 Hz laufen können, FreeRTOS ja/nein, Subsumption, BehaviorTree oder hierarchischer Automat, reicht der Mega dafür noch oder besser gleich Due usw.)
 
@Dietmar: Nachtrag: der Code ist nun testbar - ich habe alle Neuerungen (hps. C++ Klassendesign) in das SVN-Hauptprojekt übertragen. Das Roboter-Verhalten wird erstmal nach wie vor über einen Zustandsautomaten abgewickelt. Einige Bugs wurden bereits gefixt. Wir sollten jetzt nach und nach alle Bugs sammeln und die dann abarbeiten...

https://code.google.com/p/ardumower/issues/list
 
Hallo Alexander,

dann lösche doch die alten Einträge in der Issues List. Das ist also jetzt die Basis mit der wir weitermachen ?

Ich war vor ein paar Tagen Überrascht zu sehen, das du alles umgeworfen hast und ganze alte Code weg war.

Hast du noch andere Änderungen gemacht, auf die wir achten sollten ?

Stefan
 
@StefanM:

Die alten Einträge sind da, damit man Bugs an diese anheften kann wenn diese erneut auftreten (und so auch nicht doppelte Einträge hineinwandern). Soll ja nicht selten vorkommen ;) - Es steht ja dabei wenn etwas gelöst wurde.

Es ist alles auf C++ umgestellt und wie gesagt, sind einige Bugs gefixt worden (Details sieht man ja im Tracker).
 
Hallo,
hat den neuen Code schon jemand getestet?
Wenn ich den Code richtig deute sollte da IMU ja wieder umgesetzt sein. Wäre klasse, dann könnte mein Ardumower auch wieder den oberen Teil des Grundstücks richtig mähen. Im Moment schafft er es kaum nach oben zu kommen. Er fällt immer irgendwann nach rechts oder links ab. Ich nutze zZ. die Version r35 die bis auf den Geradeauslauf auch spitze läuft.
Ich habe auch irgendwo gesehen das der GPS nun zur Zeiteinstellung genutzt wird. Wenn ich den allerdings an den RX/TX anschließe, wo auch mein Bluetooth angeschlossen ist, dann geht dieses nicht mehr.
Gruß
Stephan
 
Oben