RelSysSS15 P3

Aus Verteilte Systeme - Wiki
Wechseln zu: Navigation, Suche

Ziel dieses Projektes ist es, eine dezentrale Entscheidungsfindung über einem Netz von Sensorknoten zu entwerfen und implementieren. Dabei soll jeder Sensorknoten die selbe Eigenschaft (physikalische Größe an der gleichen Stelle zur gleichen Zeit) messen. Das Sensornetz als verteiltes System soll in der Lage sein, dezentral eine Entscheidung zu treffen, welchen Wert die gemessene Eigenschaft tatsächlich hat. Insbesondere ist darauf zu achten, dass Sensoren falsche bzw. gar keine Werte liefern können. Auch kann es sein, dass die Kommunikation zwischen einzelnen Sensorknoten bzw. Gruppen von Sensorknoten ausfällt. Die Kommunikation der Sensorknoten untereinander soll mithilfe eines Data Distribution Service (DDS) realisiert werden. [1]

Hardware-Umgebung, Programmierschnittstellen und Werkzeuge

In diesem Abschnitt wird kurz umrissen, welche Hardware verwendet wurde. Zudem wird erläutert, welche Softwareumgebung nötig ist und wie man diese aufsetzt.

RaspberryPi B+

RaspberryPI B+

Der RaspberryPi B+ ist ein kreditkartengroßer Computer auf einer Platine. Er verfügt über 512MB Arbeitsspeicher und einen 700MHz ARM Prozessor und somit über genug Rechenleistung, um mit Betriebssystem als Sensorknoten zu fungieren.

5 RaspberryPIs auf 2 Stacks

Um die Handhabung der Sensorknoten zu verbessern und trotzdem noch alle möglichen Fehlerfälle einfach produzieren zu könnnen, sind die 5 RaspberryPIs mit Zusatzboard auf zwei Stacks verteilt worden

XTRINSIC-SENSE-BOARD

XTRINSIC-SENSE-BOARD

Das XTRINSIC-SENSE-BOARD ist ein Zusatzboard, das mit dem Raspberry Pi kompatibel ist und folgende Sensoren enthält:

  • Prazisions Drucksensor
  • 3D Magnetsensor
  • 3-Achsen Beschleunigungssensor

Die Kommunikation zwischen Sensorboard und Raspberry Pi wird über einen I2C Bus abgewickelt. Deshalb müssen die I2C Treiber in Raspbian zunächst aktiviert werden. Das grafische Konfigurationstool raspi-config bietet eine sehr komfortable Möglichkeit dazu.

Erstellen eines ersten lauffähigen RTI DDS Beispiels

Hier wird davon ausgegangen, dass RTI DDS bereits installiert ist. RTI stellt dazu eine sehr gute Anleitung zur Verfügung.

Zunächst müssen alle Datenstrukturen definiert werden. Diese Datenstrukturen definieren den Aufbau der versendeten Samples. Eine einfache Datenstruktur sieht wie folgt aus und wird in einer Datei mit der Endung *.idl gespeichter:

struct hello_message {
    string name; //@key
    long count;
};

Ein Datasample besteht also aus einem string und einem long.

Das mitgelieferte Tool rtiddsgen generiert einen Beispielcode plus Makefile aus einem idl-file:

$NDDSHOME/scripts/rtiddsgen -example armv6vfphLinux3.xgcc4.7.2 -language C++ hello.idl

Durch ausführen des generierten Makefiles werden ausführbare Dateien für publisher und subscriber gebaut:

make -f makefile_hello_armv6vfphLinux3.xgcc4.7.2

Konfiguration des Sensornetzes

Es werden zunächst drei (später fünf) RaspberryPis konfiguriert, mit Sensoren (Sensorboards) ausgestattet und untereinander vernetzt. Dabei wird in erster Instanz eine Sterntopologie verfolgen (andere Topologien können später ausprobiert werden).

Betriebssystem

Um möglichst schnell einen ersten funktionierenden RaspberryPi zu konfigurieren, wurde in erster Iteration das gängigste RaspberryPi Betriebssystem Raspbian aufgesetzt. Dazu wurde die Imagedatei von http://downloads.raspberrypi.org/ heruntergeladen, entpackt und mit folgendem Befehl auf die SD-Karte des RaspberryPi überspielt:

sudo dd if=/tmp/2015-05-05-raspbian-wheezy.img of=/dev/mmcblk0 bs=1M

Netzwerktopologie

Vernetzte RaspberryPIs

Die hier gewählte Netzwerktopologie wurde ausgewählt, um die angestrebte Funktionalität, die im Rahmen dieses Projektes entwickelt werden soll, zu testen. Ziel ist es nicht, das Netzwerk robust gegen Ausfälle von Verbindungen oder Netzwerkknotenpunkten zu gestalten. Vielmehr soll der Totalausfall von einzelnen Kommunikationswegen, sowie Partitionierung des Netzes durch das Lösen einzelner Netzwerkstecker leicht herbeigeführt werden können. RelSys2015SSP03 Netzwerktopologie.svg

Analyse des DDS Standards[1][2]

Der Data Distribution Service ist ein Standard der Object Management Group zur datenzentrierten Kommunikation in Verteilten Systemen. Die Kommunikation wird über ein Publisher-Subscriber Modell realisiert. Publisher können Daten unter Topics publizieren, sodass alle Subscriber dieses Topics die Daten lesen können. Die Struktur der Datenpakete wird dabei statisch konfiguriert. Jedes Datenpaket enthält einen Key der spezifiziert, um welches Datum es sich handelt (z.B.: TemperaturSensor01). Näheres zum DDS-Standard findet sich in der offiziellen Spezifikation.

Quality of Service (QoS)

DDS bietet die Möglichkeit, unterschiedliche QoS Parameter für jede einzlne Einheit (Topic, Reader, Writer) festzulegen. In diesem Abschnitt werden für dieses Projekt relevante QoS Parameter herausgearbeitet.

Deadline

Spezifiziert die Rate, mit der ein Writer mindestens Werte liefert (z.B.: alle 100ms). Wird diese Deadline verletzt, wird die Applikation darüber benachrichtigt.

Destination Order

Spezifiziert, ob die einzelnen Samples in der Reihenfolge gelesen werden, in der sie empfangen wurden, oder in der Reihenfolge, in der sie gesendet wurden.

Liveliness

Spezifiziert, wie bestimmt wird, ob eine Einheit noch lebt und wie häufig dazu ein Lebenszeichen gesendet werden muss.

Ownership/Ownership Strength

Spezifiziert, ob mehrere Writer eine data instance aktualisieren dürfen. Falls nicht, entscheidet der Ownership Strength Parameter darüber, wer schreiben darf.

Lifespan

Spezifiziert, wie lange ein Sample gültig ist. Nach Ablauf dieser Zeit kann das Sample nicht mehr gelesen werden.

History

Spezifiziert, wieviele Samples zwischengespeichert werden. Dadurch bleiben immer die letzten N Samples abrufbar.

Konzept zur verteilten Entscheidungsfindung

Im Optimalfall können alle Sensorknoten über einen internen Kommunikationskanal die Sensordaten aller Knoten empfangen. Jeder Sensorknoten kann auf Basis dieser Daten eine subjektive Entscheidung fällen, die seiner Meinung nach die globale Situation wiederspiegelt. Diese subjektiv-globalen Entscheidungen werden - zusammen mit einem Maß der Güte dieser - einer Entscheidungslogik übergeben, die auf Basis der Güte entscheidet, welche subjektiv-globale Entscheidung als globale Entscheidung publiziert wird.

RelSys2015SSP03 Konzept.svg

In diesem Fall bedeutet das, dass jedem Sensorknoten der aktuelle Sensorwert jedes einzelnen (oder auch nur einiger) Sensorknoten bekannt ist. Der Sensorknoten sucht in der Menge dieser Sensorwerte nach Übereinstimmungen[A 1]. Sind ausreichend viele übereinstimmende Sensorwerte vorhanden (mehr als die Hälfte aller Sensoren), wird dieser Wert als subjektiv-globale Entscheidung an die Entscheidungslogik übergeben. Als Maß der Güte wird zu dieser Entscheidung die Anzahl übereinstimmender Sensorwerte übergeben. Die Entscheidungslogik wählt dann aus allen eingegangenen subjektiv-globalen Entscheidungen diejenige aus, deren Entscheidung auf den meisten übereinstimmenden Sensorwerten basiert. Gibt es noch andere Entscheidungen, die genau so gut sind, ist egal, welche davon ausgewählt wird. Die ausgewählte subjektiv-globale Entscheidung wird dann als globale Entscheidung publiziert.

Umsetzung des Konzeptes mit DDS

Der interne Kommunikationskanal des Konzeptes wird durch das SensorDataTopic konkretisiert. Jeder SensorDataPublisher publiziert unter einem eigenen Key die Sensordaten des eigenen Sensorknotens unter diesem Topic. Der Decider eines jeden Sensorknotens kann so die Sensorwerte jedes Knotens lesen. Aus der Menge der Sensorwerte aller Knoten sucht jeder Decider übereinstimmende Werte. Sind ausreichend viele überseinstimmende Werte gefunden, wird die Ownership Strength des DataWriters auf die Anzahl übereinstimmender Sensorwerte gesetzt und die getroffene Entscheidung unter dem DecisionTopic publiziert. Da das DecisionTopic mit der Exclusive Ownership Eigenschaft versehen wurde, wird nur eine der Entscheidungen mit der höchsten Ownership Strength an die DataReader publiziert. Dadurch wird die finale Entscheidungsfindung umgesetzt und jeder Client bekommt höchstens eine Entscheidung mitgeteilt. Findet kein Decider hinreichend viele übereinstimmende Sensorwerte, wird keiner unter dem DecisionTopic publizieren. Anhand einer festgelegten Deadline kann ein DecisionSubscriber dann feststellen, dass ein nicht maskierbarer Fehler aufgetreten ist.

RelSys2015SSP03 KonzeptDDS.svg

Um dieses Konzept umsetzen zu können, sind die Quality of Service Eigenschaften der einzelnen DataReader und DataWriter von großer Bedeutung.

Der DataWriter des SensorDataPublishers ist mit einer History von 1 konfiguriert, damit immer nur der zuletzt publizierte Sensorwert gelesen werden kann. Zudem wird der Lifespan festgelegt, damit keine veralteten Daten gelesen werden können, wenn ein Knoten ausgefallen ist.

Die Ownership des DataWriters des Deciders muss als exklusiv festgelegt werden, damit nur eine der subjektiv-globale Entscheidung publiziert wird. Auch hier wird die History auf 1 gesetzt, damit immer nur die neuste Entscheidung gelesen werden kann. Das Festlegen des Lifespan sorgt dafür, dass keine veralteten Entscheidungen gelesen werden, da die Letzte Entscheidung nicht überschrieben wird, wenn ein nicht maskierbarer Fehler auftritt. Dann würde ohne Festlegen des Lifespan immer die letzte gültige globale Entscheidung von Clients gelesen.

  1. Auf exakte Übereinstimmung von Sensorwerten zu prüfen macht meist keinen Sinn. Vielmehr wird hier nach ähnlichen Werten gesucht, die dann gemittelt werden.

Implementierung

Hier werden Besonderheiten und Probleme bei der Implementierung hervorgehoben und genauer betrachtet.

SensorDataPublisher

Der SensorDataPublisher ist so implementiert, dass er alle 20ms den überwachten Sensorwert ausliest und mit der MAC-Adresse des Sensorknotens als Schlüssel unter dem SensorDataTopic publiziert wird. Die Lebensdauer eines publizierten Sensorwertes wurde auf 100ms gesetzt, damit keine veralteten Sensorwerte gelesen werden können, wenn der Knoten ausfällt. Zudem wurde die History auf 1 gesetzt, sodass nur der aktuellste Sensorwert gelesen werden kann:

<datawriter_qos>
    <publication_name>
        <name>sensorDataDataWriter</name>
    </publication_name>
    <lifespan>
        <duration>
            <sec>0</sec>
            <nanosec>100000000</nanosec>
        </duration>
    </lifespan>
    <history>
        <kind>KEEP_LAST_HISTORY_QOS</kind>
        <depth>1</depth>
    </history>
</datawriter_qos>

Decider

Der Decider ist dafür zuständig, die Sensorwerte aller Knoten entgegenzunehmen, nach übereinstimmenden Werten zu suchen, und bei hinreichend übereinstimmenden Werten deren Mittelwert zu bilden und diesen Mittelwert als subjektiv-globale Entscheidung unter dem Decision Topic zu publizieren.

Da die Sensorwerte unterschiedlicher Knoten nicht absolut identisch sind (selbst nicht wenn sie korrekt sind), muss ein Verfahren gefunden werden, um ähnliche Werte zu finden und Ausreißer zu eliminieren. Um die Komplexität dieses Verfahrens zu minimieren, wird der Sensorwert des eigenen Knotens als Ausgangswert genutzt. Ähnliche Werte liegen in einem Toleranzbereich um diesen Wert, alle anderen werden ignoriert. Gehört der Knoten selbst zu denen, die einen falschen Wert gesendet haben, wird von diesem deshalb keine subjektiv-globale Entscheidung publiziert. Sind hinreichend viele ähnliche Werte gefunden worden, wird deren Mittelwert publiziert.

Falls einzelne SensorDataPublisher sporadisch nicht rechtzeitig einen Sensorwert publizieren können, wird das kompensiert, indem nur alle 40ms eine subjektiv-globale Entscheidung getroffen wird.

Die Deadline des DataWriters wird auf 100ms festgelegt, da ohne Überschreitung der Deadline die Ownership des DecisionTopic nicht an einen andern DataWriter übergeben wird.

<datawriter_qos>
    <lifespan>
        <duration>
            <sec>0</sec>
            <nanosec>100000000</nanosec>
        </duration>
    </lifespan>
    <ownership>
        <kind>EXCLUSIVE_OWNERSHIP_QOS</kind>
    </ownership>
    <ownership_strength>
        <value>0</value>
    </ownership_strength>
    <history>
        <kind>KEEP_LAST_HISTORY_QOS</kind>
        <depth>1</depth>
    </history>
    <deadline>
        <period>
            <sec>0</sec>
            <nanosec>100000000</nanosec>
        </period>
    </deadline>
</datawriter_qos>

Auslesen der Sensoren

Das XTRINSIC-SENSE-BOARD liefert eine vorkompilierte .so Datei, die verwendet werden kann, um die Sensoren auszulesen. Die Dokumentation sowie Implementierung dieser ist allerdings sehr schlecht. Beim Benutzen dieser Schnittstelle stellt man fest, dass mmap() irgendwann keinen Speicher mehr allokieren kann. Das liegt daran, dass in der Library für jede Abfrage ein mmap() aufgerufen wird, allerdings niemals ein munmap(). Nachdem dieser Bug behoben war, konnte die Library problemlos verwendet werden.

Literatur

  1. G. Pardo-Castellote, B. Farabaugh, R. Warren - An Introduction to DDS and Data-Centric Communications
  2. RTI Connext — Comprehensive Summary of QoS Policies