Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

projektesose2015:loeschbot_clean:start

LöschBot

Unsere Gruppe zwei Monate lang intensiv damit beschäftigt, einen möglichst autonomen Roboter zu entwickeln, der zugleich eine nützliche Funktion hat. Deshalb haben wir, das sind Max, Jan, Christopher und Nicolai, es uns zur Aufgabe gemacht, einen Roboter zu bauen, der in der Lage ist, selbstständig Brandherde zu erkennen, anzusteuern und schließlich zu löschen. Ein Projekt mit Potenzial. Doch wie wir das Problem gelöst haben und ob der Roboter am Ende wirklich Kerzen löschen konnte, erfahrt ihr hier…

Unser Projekt


Der Roboter muss eine Kerze erkennen und löschen können. Dazu muss er zuerst einmal die Kerze finden und ihre Position bestimmen. Das erreicht er mit einer Kamera und durch drehen auf der Stelle. Wenn er den Standort ermittelt hat, muss er entsprechend darauf reagieren und die Motoren so ansteuern, dass er zu der Kerze fährt. Dort angekommen muss er erkennen, dass diese Lichtquelle auch warm ist, da die Kamera nur die Helligkeit messen kann. Dies wird durch eine Thermalkamera ermöglicht, die anschließend dazu dient, die Spritze genau in Richtung Kerze auszurichten. Ist die Spritze einmal ausgerichtet, kann die Pumpe aktiviert und die Kerze gelöscht werden. Danach fängt der Roboter seine Suche von vorne an.

Umsetzung


Aufbau

Teilprobleme

Priorität Planung Durchführung
muss eigenständig durch den Raum bewegen wurde erreicht
muss Brandherde erkennen über zwei Kamera
muss Brandherde exakt ansteuern nicht exakt agesteuert, aber Zielgenauigkeit mithilfe der IR-Kamera
muss gegenüber Wasser geschützt sein Elektronik auf der Unterseite
sollte Hindernisse erkennen und ausweichen aus Zeitgründen weggelassen
sollte entscheiden, welcher Brandherd näher ist und diesen zuerst löschen in Planung
sollte den optimalen Winkel für die Spritze zum Löschen bestimmen nicht mehr benötigt, da Spritze von der Höhe nicht mehr verstellbar ist
„nice to have“ Steigungen mit dem Spritzenwinkel ausgleichen aus Zeitgründen weggelassen
„nice to have“ erkennen, wenn er auf einen Abgrund zusteuert aus Zeitgründen weggelassen
„nice to have“ eine Sirene und flotte Lakierung Sirene vorhanden, Lakierung aus Zeitgründen weggelassen

Programmablauf

Feuer suchen

  • Die Bildauswertung wird auf dem Surface gestartet.
  • Der Roboter dreht sich auf der Stelle und sucht nach dem hellsten Punkt.
  • Wenn er einen hellsten Punkt findet und dieser über einem Schwellenwert liegt, fährt er dorthin.
  • Nachdem er nah genung an der Kerze steht, übergeht er in nächste Phase.

Feuer löschen

  • Mit der Thermokamera wird bestätigt, dass dieser Punkt heiß ist und es sich somit um eine Kerze handelt.
  • Die Sirene wird einschalten.
  • Die Spritze wird nun so gedreht, dass sie auf die Feuerquelle zielt.
  • Die Pumpe wird anschließend immer mit 30% - 100% Leistung aktiviert und die Spritze gleichzeitig in einem kleinen Radius gedreht.
  • Wenn die Kerze aus ist, werden Pumpe und Sirene wieder deaktiviert und die Suche nach Kerzen fortgesetzt.

Die genauen Schritte des Programmablaufes

Das Surface

Der Teensy

Bau des Roboters

Während der Zeit, in der wir den Roboter gebaut haben, stellte sich heraus, dass viele erste Ideen nicht in der Art und Weise umsetzbar waren, wie wir geplant hatten. So haben wir uns schnell dafür entschieden, den Turm zu fixieren und den gesamten Roboter sich drehen zu lassen, um nach dem Brandherd zu suchen. So mussten wir auch Abstriche machen, was unsere Anfangsplanung betraf. Angefangen haben wir damit, das Holzbrett zuzuschneiden und das Blech zu kürzen und mithilfe einer soliden Tischkante zu biegen. Viele Löcher mussten wir vorbohren, so zum Beispiel am Blech und an den Fixierungspunkten der hinteren Motoren. Das Plastikrohr mussten wir kürzen und zurecht schleifen. Außerdem kamen noch mehrere Einschlüsse dazu, um Kamera und Drähte durch das Rohr führen zu können. Anschließend befestigten wir das Rohr über einem dafür vorgesehenen Loch mit Heißkleber, nachdem wir uns dafür entschieden hatten, den gesamten Roboter zu drehen und nicht nur den Turm. Mithilfe von verschiedenen Bleistiftmarkierungen konnten wir dann sorgfältig bestimmen, wo die anderen Bauteile befestigt werden sollten, so zum Beispiel der Wassertank und die Elektronik, die wir zum Großteil unter der Holzplatte befestigten, um diese beiden Gefahrenpotenziale möglichst effektiv voneinander zu trennen.

Für den Tank wollten wir zuerst einen kleinen Käfig aus Holz basteln, kamen aber dann schnell darauf, dass die Winkel ein deutlich einfacheres Mittel für unseren Zweck waren. Die Elektronik haben wir mit Hilfe von Klettverschlüssen auf der Unterseite befestigt. Fehlte nur noch, den Stepper-Motor zusammen mit der Wärmebildkamera vorne zu befestigen. Als letztes wurde der Wassertank in Kombination mit der Aquarienpumpe befestigt und fixiert.

Für das Programm haben wir damit angefangen, dem Roboter fahren beizubringen, damit er in der Lage ist, durch das Drehen auf der Stelle eine mögliche Hitzequelle (Kerze) zu finden, und diese dann ansteuern zu können. Danach mussten wir mithilfe der beiden Kameras eine Erkennungsroutine programmieren, um Licht- und Hitzequellen zu erkennen.

Im vornherein hatten wir bereits gemessen, welche Distanzen wir mit der Aquarienpumpe bei verschiedenen Stromstärken abdecken konnten und kamen zum Ergebnis, dass wir mit der möglichen Leistung ausreichend weit kommen.

Am Ende mussten wir nur noch diese Teile zusammensetzen und letzte kleine Fehler ausarbeiten.

Vorbereitung

Kameras

Zu Beginn unserer Projektarbeit haben wir bereits eine kleine Schaltung gebaut, um Messungen mit der IR-Kamera durchzuführen und anschließend in Processing bildlich darstellen zu können. Anschließend haben wir getestet, auf welche Entfernung eine Kerze zu erkennen ist. War die Kerze weiter als 75cm von der IR-Kamera entfernt, konnte sie nicht mehr eindeutig erkannt werden. Also haben wir die PS3-Kamera probeweise auf die Höhe gehalten, in der sie später zum Einsatz kommen sollte und haben die Kerze, welche wir auf 75cm Entfernung positioniert haben, eindeutig erkannt.

Um eine höhere Präzision zu erreichen, haben wir allerdings im Nachhinein die PS3-Kamera angeschrägt, damit wir auch Kerzen auf kürzere Distanzen erkennen können.

Aquariumpumpe

Um die Leistung der Aquariumpumpe bewerten zu können, haben wir die Entfernung gemessen, welche das Wasser bei unterschiedlichen Spannungen der Pumpe aus einem Meter Höhe in einem Winkel von 0° erreicht hat. Wir haben zwei Messungen durchgeführt:

Spannung in V Messung 1: Entfernung in cm Messung 2: Entfernung in cm
6 40 43
7 50 50
8 55 55
9 68 62
10 70 68
11 78 76
12 83 80

Aus den Messwerten konnten wir eine lineare Steigung bei Erhöhung der Spannung schließen. Doch eine Entfernung von 80cm war uns zu unsicher, da die Spritze später auch tiefer montiert werden sollte.

Um höhere Entfernungen zu erreichen, haben wir also an das Ende des Schlauches die Spitze eines Kugelschreibers als Spritze angebracht. Damit erreichten wir Spitzenwerte von bis zu zwei Meter. Alle Mal ausreichend für unsere Zwecke.

Materialliste

Elektronik

Weitere Materialien

  • Holzbrett (Länge: 40cm x Breite: 25cm)
  • Plastikrohr (Durchmesser: 4,5cm x Höhe: 30cm)
  • Dünnes gebogenes Metall (Länge: 30cm x Höhe: 10cm)
  • Wassertank
  • Zwei Räder
  • Stützrad
  • Kabelbinder, Klebeband, Kleber, Schrauben, Nägel, Winkelbefestigungen, usw. zur Befestigung aller Komponenten
  • Werkzeug zum Zusammenbau

Schaltungen

Motoren

Anschluss der Motoren an einen Pololu TReX Dual Motor Controller DMC01. Pinbelegung siehe unten.

Pumpe

Stepper

Infrarotkamera (IR-Kamera)

Systembestandteile

Aufbau der Kamera

Das größte Problem währed der Arbeit mit der Kamera waren andere Lichtquellen. Diese Störeinflüsse konnte man auch durch die Software kaum eindämmen. Also mussten wir uns etwas einfallen lassen, um alles Licht außer das der Kerzen herauszufiltern. Dazu wollten wir zunächst eine Infrarotlinse auf der Kamera montieren. Um diese dort anbringen zu können, mussten wir allerdings das Gewinde der Kamera ändern und somit auch das komplette Gehäuse demontieren. Als die Linse montiert war, wurde nicht leuchtende Gegenstände zwar dunkler angezeigt, was schon deutlich besser als vorher war, aber andere Lichtquellen waren weiterhin hell. Also haben wir ein Loch in den Deckel der Linse geschnitten, um so rote und blaue Folie vor der Linse anzubringen. Diese filterte auch das Kunstlicht aus dem Bild und die Kerzen wurden optimal erkannt, nachdem wir die Lichtempfindlichkeit der Kamera sehr niedrig eingestellt haben. Nur das Tageslicht der Sonne ist weiterhin heller als jedes andere Licht, weshalb wir den Roboter auch nur drinnen nutzen können.

Hier sieht man den Löschvorgang aus Sicht des Roboters. Das linke Bild im Video zeigt die Sicht der PS3-Kamera und das rechte das unbearbeitete und ungefilterte Bild der Surface-Frontkamera:

Aufbau der Spritze

Um mit der Spritze exakt zielen zu können, haben wir die Infrarotkamera zusammen mit der Spritze fest auf dem Stepper montiert. Hierbei sind Spritze und Kamera genau gleich ausgerichtet. Mithilfe von Muttern konnten wir den Winkel der Spritze verändern und so über einige Tests den richtigen Winkel bestimmen. Um die Kontakte der IR-Kamera zu schützen, haben wir die Verbindung von Schlauch und Spritze mit einem Schrumpfschlauch abgedichtet und die Spritze so positioniert, dass das Wasser vorne aus der Spritze weder auf die Kamera, noch auf den Stepper tropfen kann.

Bestimmung des hellsten Punktes

Die Helligkeit eines Punktes berechnet sich durch den Durchschnitt, bzw. die Summe seiner RGB-Werte. Jeder Pixel der Kamera wird in einem Array gespeichert, wobei jeweils drei Werte hintereinander der R-, G-, bzw. B-Wert eines jeweiligen Pixels darstellen. Um den hellsten Punkt im Bild zu finden, muss man jeden Pixel im Array einzeln durchgehen und die Helligkeit mit dem bisherigen hellsten Punkt vergleichen.

for (aktuellerPunkt.y = startzeile ; aktuellerPunkt.y < camHeight; aktuellerPunkt.y++)
{
	for (aktuellerPunkt.x = 0 ; aktuellerPunkt.x < camWidth; aktuellerPunkt.x++)
	{
		aktuellerPunkt.helligkeit = pixels[position] + pixels[position + 1] + pixels[position + 2];
		if (aktuellerPunkt.helligkeit > hellsterPunkt.helligkeit)
		{
			hellsterPunkt.x = aktuellerPunkt.x;
			hellsterPunkt.y = aktuellerPunkt.y;
			hellsterPunkt.helligkeit = aktuellerPunkt.helligkeit;
		}
		position += 3;
		}
	}
}

Umrechnung auf die Motorsteuerung

Die Motoren können nur ein Byte an Daten empfangen, das sind also Zahlen von 0-127. Deshalb müssen die Daten der Bildverarbeitung auf Werte umrechnen, die für die Motoren verständlich sind. Dazu wird das Bild erstmal in der Mitte aufgeteilt, sodass der Punkt in der Mitte den X-Wert Null erhält, der ganz links -127 und der ganz rechts 127. Auch der Y-Wert wird auf Werte von 0-127 umgerechnet.

motor.x = (int)((double)hellsterPunkt.x / 640.0 * 254.0 - 127);
motor.y = (int)((double)hellsterPunkt.y / 480.0 * 127.0);

Nun werden Richtungen für die beiden Motoren, sowie die Geschwindigkeit definiert. Die Richtung der Motoren richtet sich danach, ob die Kerze links, rechts oder mittig liegt. Die Geschwindigkeit berechnet sich beim Drehen nach der Entfernung der Kerze zur Mitte und beim Zur Kerze fahren nach der Entfernung, also dem Y-Wert der Kerze, der vorher noch invertiert werden noch.

if (motor.x < -25)
{
	motorLinksRichtung = 0;
	motorRechtsRichtung = 1;
	motorGeschwindigkeit = (unsigned char)((double)(abs (motor.x)) / 3.0 + 20.0);
}
else if (motor.x > 25)
{
	motorLinksRichtung = 1;
	motorRechtsRichtung = 0;
	motorGeschwindigkeit = (unsigned char)((double)(abs (motor.x)) / 3.0 + 20.0);
}
else
{
	motorLinksRichtung = 1;
	motorRechtsRichtung = 1;
	motorGeschwindigkeit = (unsigned char)((127.0 - (double)motor.y) / 2.0 + 10.0);	
}

Übertragung der Daten

Die berechneten Motordaten müssen von dem Surface auf den Teensy übertragen werden. Dafür ist das Surface genau wie mit der PS3-Kamera über USB verbunden. Diese Verbindung muss allerdings vorher auf beiden Seiten initialisiert werden. Die Daten können nur in Bytes geschickt werden. Um die Werte der entsprechenden Variable zuordnen zu können, schicken wir zwischen den Werten immer Buchstaben. Diese erkennt der Teensy dann und ordnet den Wert der gleichen Variable, wie auf dem Surface zu.

Code auf der Seite des Surfaces:

mySerial.writeByte('a');
mySerial.writeByte(motorLinksRichtung);
mySerial.writeByte('b');	
mySerial.writeByte(motorRechtsRichtung);
mySerial.writeByte('c');
mySerial.writeByte(motorGeschwindigkeit);

Code auf der Seite des Teensys:

if (Serial.available() > 2)
{
	char inByte = Serial.read();
	switch (inByte)
	{
		case 'a':
		{
			unsigned char inValue;
			Serial.readBytes((char*) &inValue, 1);
			motorLinksRichtung = (int) inValue;
			break;
		}
		case 'b':
		{
			unsigned char inValue;
			Serial.readBytes((char*) &inValue, 1);
			motorRechtsRichtung = (int) inValue;
			break;
		}
		case 'c':
		{
			unsigned char inValue;
			Serial.readBytes((char*) &inValue, 1);
			motorGeschwindigkeit = (int) inValue;
			break;
		}
		break;
	}
}

Auf der Seite des Teensys muss der Wert der Eingabe mehrmals gecastet werden, da sonst das falsche Dateiformat vorliegt und die Werte fehlerhaft sind.

Erkennen von Wärmequellen

Die Infrarotkamera hat eine Auflösung von 16×4. Eine Messung findet hier ähnlich wie bei der Helligkeit durch das Durchgehen durch ein Pixelarray statt. An jeder Position im Array wird die entsprechende Temperatur dieser Position gespeichert. Auch hier wird das Array spalten- und zeilenweise durchgegangen und der maximale Temperaturwert mit der entsprechenden Position gespeichert. Danach kann sich der Stepper mit der Spritze dann ausrichten.

Die Messung sieht im Code wie folgt aus:

void ircam()
{
	tempMax = 0;
	tempMaxAtX = 0;
 
	sensor.readTemperatures();
	double* pixelTemps = sensor.getPixelTemperatures();
	for (int x = 0; x < 16; x++)
	{
		for (int y = 0; y < 4; y++)
		{
			if (pixelTemps[y+x*4] > tempMax)
			{
				tempMax = pixelTemps[y+x*4];
				tempMaxAtX = x;
			}
		}
	}
}

Wenn man das Array in Processing ausgibt und die unterschiedlichen Temperaturen farbig markiert, erhält man von der Infrarotkamera folgende Bilder:

Ansteuerung der Motoren

Die Motoren werden mit bestimmten Codes angesprochen, die im Hexadezimalsystem an die serielle Schnittstelle der H-Brücke übertragen werden. Neben den Motorbefehlen kann man allerdings auch Werte von 0-127 übertragen, welche für die Geschwindigkeit stehen. Diese werden immer an den jeweils zuvor angesprochenen Code übertragen.

Die Fahrenfunktion sieht somit wie folgt aus:

void fahren ()
{
	if (motorLinksRichtung > 0) Serial2.write(0xC2);
	else Serial2.write(0xC1);
	Serial2.write(motorGeschwindigkeit);
	if (motorRechtsRichtung > 0) Serial2.write(0xCA);
	else Serial2.write(0xC9);
	Serial2.write(motorGeschwindigkeit);
	if (motorLinksRichtung == 1 && motorRechtsRichtung == 1 && motorGeschwindigkeit < 25)
	{
		angekommen = 1;
	}
}

Ansteuerung des Steppers

Der Stepper wird mit zwei Signalen angesprochen. Das eine Signal legt die Richtung des Steppers fest und das andere ob der Stepper dreht oder nicht. Auf letzterem Signal wird ein, von uns erzeugtes, PWM-Signal übertragen, welches wir darauf abgestimmt haben, dass der Stepper genau einen Schritt in die vorgegebene Richtung macht. Diese Funktion lässt den Stepper genau einen Step in die vorher definierte Richtung machen:

void drehen(int s)
{
	for(int i = 0; i < s; i++)
	{ 
		digitalWrite(14,HIGH);
		delayMicroseconds(500);
		digitalWrite(14,LOW);
		delayMicroseconds(500);
	}
}

Pinbelegung

Pin Funktion Kabelfarbe
2 Encoder A [Motor 2] Weiß
3 Encoder B [Motor 2] Gelb
4 Encoder A [Motor 1] Weiß
5 Encoder B [Motor 1] Gelb
6 Sirene Blau
9 SO [H-Brücke] Orange
10 SI [H-Brücke] Grün
14 Motor [Stepper] Gelb
15 Richtung [Stepper] Grün
18 SDA [IR-Kamera] Rot
19 SCL [IR-Kamera] Orange
21 Pumpe Violett

Fazit


aktuelle Probleme

  • Der Roboter kennt zurzeit nur zwei Fahrmodi: entweder drehen oder vorwärts fahren. Dadurch, dass er immer wieder stehen bleiben muss, um die Richtung zu korriegieren, entstehen ruckelnde Bewegungen.
  • Die Motoren können den LöschBot nur ab einem relativen Geschwindigkeitswert von 20 bewegen. Damit er sich also so gut wie möglich Richtung Kerze bewegt, musste eine sehr hohe Toleranz von 50 Pixeln in beide Richtungen implementiert werden. Die sorgt jedoch dafür, dass der Roboter nicht exakt mittig zur Kerze ausgerichtet ist.
  • Wenn kein hellster Punkt gefunden wird, dreht sich der Roboter immer weiter auf der Stelle. So findet er auch keine Kerzen, die sich zum Beispiel um die Ecke oder hinter einem Tischbein befinden.
  • Sind mehrere Kerzen im Blickfeld der Kamera, springt der hellste Punkt oft zwischen den Kerzen und der Roboter steuert immer den aktuell hellsten an. So fährt er auch zwischen Kerzen hin und her, da er im Wechsel versucht, die jeweils hellste zu zentrieren.

Ausblick

In Zukunft würden wir die Fehler ersteinmal ausbessern, bevor wir neue Funktionen implementieren würden:

  • Die Fahrenfunktion würde so verändert werden, dass der Roboter flüssig seine Richtung ändert. Dazu würde jeder Motor eine eigene Geschwindigkeit übertragen bekommen und kann so auch während des Geradeausfahrens seine Richtung so anpassen, dass die Kerze mittig steht. Da der Roboter dann nicht mehr aus dem Stand korrigiert, kann er so auch genauer die Kerze zentrieren.
  • Darüber hinaus soll das Fahren so geändert werden, dass er nach einer vollständigen Drehung den Suchkreis ausdehnt, um auch Kerzen außerhalb des Blickfeldes zu finden, sofern sich kein Hindernis im Weg befindet. Dazu werden allerdings Abstandssensoren benötigt.
  • Desweiteren sollen die Kerzen, die sich am dichtesten am Roboter befinden, priorisiert werden. Dazu kann man helle Punkte, die sich weiter unten im Bild, also dichter am LöschBot befinden, verstärken. Somit werden sie mit einer höheren Wahrscheinlichkeit der hellste Punkt sein, als Kerzen, die weiter entfernt stehen.

Code

Libraries

projektesose2015/loeschbot_clean/start.txt · Zuletzt geändert: 2016/01/21 12:45 (Externe Bearbeitung)