Dies ist die von Julian Mueller überarbeitete Bahnkantenregelung.

Dependencies:   TextLCD mbed

Revision:
0:b72d86a7b005
diff -r 000000000000 -r b72d86a7b005 edge_func.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_func.cpp	Tue May 31 03:06:27 2016 +0000
@@ -0,0 +1,283 @@
+/**
+*Funktionen zum Auslesen der Linienkamera und zur Detektion der Kante
+*
+*CPP-Datei edge_func.cpp
+*
+*@version: 01.11.2015
+*@author: Gustav Grether
+*/
+
+#include "edge_func.h"
+
+//Definiton zur Anzeige von Fehlern
+DigitalOut errorLED(LED1); //zeigt an, dass Fehler auftritt
+
+// Definition der Pins des Sensors
+DigitalOut clk(p18); //Clock Pin
+DigitalOut si(p19); //SI Pin
+//analoger Eingang Wertebereich [0..1] mit ao.read()
+// misst die Spannung die am Sensorausgang anliegt
+AnalogIn ao(p20); 
+
+//Variablen fuer alle Funktionen der Datei
+const int numPx =128; // Anzahl der Pixel
+const int leftbound = 8; // linker Randbereich des Sensors, nicht betrachtet
+const int rightbound = numPx - leftbound; //rechter Randbereich des Sensors, nicht betrachtet
+queue<int> possEdgePx; //enthaelt die Pixel die als Kante in Frage kommen
+int tmpPossEdgePx; //temporaeres moegliches Kantenpixel
+int numPossEdgePx; //Anzahl der moeglichen Kantenpixel
+
+//Variablen fuer read()
+float currentVal[numPx]; //Werte der Pixel einer Messung
+const int numMeas =3; //Werte werden ueber numMeas Messungen gemittelt
+float meanVal[numPx]; //Mittelwerte jedes Pixels ueber die (NumMeas) Messungen
+float currentPx;
+int delay=2; //Verzoegerung zum Einstellen der Belichtungszeit in [10⁻³ s]
+//Variablen zur Detektion einer Fehlfunktion des Sensors
+const float epsilon=0.01; //minimal zulaessiger Wert eines Pixels
+int cntZero; //Anzahl ungueltiger Pixel(<epsilion)
+const int zeroMax=5; //maximale Anzahl ungueltiger Pixel pro Messung
+bool validMeas; //zeigt ob eine Messungen gueltig ist
+
+//Variablen fuer gaussian_calc()
+float gaussian[numPx]; //gauss gefilterte Grauwerte
+
+//Variablen fuer gradient_calc()
+float gradient[numPx]; //Gradienten der Pixel
+
+//Variablen fuer nonMaxSupr()
+//Gradienten liegt in [-1.0,1.0]
+// relevant ist nur [-1.0,0.0]
+// Anzahl der Quanten in Intervall=numQuant+1 
+const int numQuant=15;
+float quantStepSize=1.0/numQuant; // Schrittweite eines Quants
+float quantStep[numQuant]; //Quantenstufen
+float quant[numPx]; //quantisierte Werte des Gradienten
+
+//Variablen fuer plausible()
+float meanLeft; //Mittelwert der Pixel links eines moeglichen Kantenpixels
+float meanRight; //Mittelwert der Pixel rechts eines moeglichen Kantenpixels
+const float threshBlack=0.4; //Grenzwert definiert Beschichtung
+const float threshFoil=0.7; //Grenzwert definiert Metallfolie
+
+//Variablen fuer edge_calc()
+float gradmin; //minimaler Gradient
+int edgePx; //gefundenes Kantenpixel Wertebereich [leftbound..rightbound]
+
+void clockPulse()
+{
+    clk=1;
+    clk=0;
+}
+
+void siClkPulse()
+{
+    si=1;
+    clockPulse();
+    si=0;
+}
+
+void sens_setup()
+{
+    errorLED=0;
+    edgePx=-1;
+    clk=0;
+    si=0;
+
+    //linker und rechter Randbereich werden nicht betrachtet
+    for (int i = 0; i < leftbound - 1; i++) {
+        gaussian[i]= 0.0;
+        gradient[i]= 0.0;
+        quant[i]= 0.0;
+    }
+    for (int i = rightbound + 1; i < numPx; i++) {
+        gaussian[i]= 0.0;
+        gradient[i]= 0.0;
+        quant[i]= 0.0;
+    }
+
+    //QuantenStufen zur Quantisierung des Gradienten
+    for(int k=0; k<numQuant; k++) {
+        quantStep[k]=-(k+1)*quantStepSize;
+    }
+}
+
+void read()
+{
+    
+    edgePx=-10; //Fehler in Algorithmus wenn Wert -10 bleibt
+    for(int j=0; j<numMeas; j++) {
+        validMeas=1; // setze Messung gueltig
+        cntZero=0;  // setze Anzahl ungueltiger Pixel=0
+        
+        siClkPulse(); //stoppt Belichtung der Pixel und startet sie erneut
+        for(int k = 0; k < 130; k++) {
+            //neue Belichtung der Pixel beginnt bei k=18
+            //jeder clock-Puls eliminiert den alten Wert eines Pixels
+            clockPulse();
+        }
+
+        wait_ms(delay); // Verzoegerung um die Belichtungszeit zu vergroessern
+        siClkPulse(); //stoppt Belichtung der Pixel und startet sie erneut
+
+        //Auslesen und Speichern der Werte der Pixel
+        //jeder Clock Puls legt an ao den Wert(Spannung) des naechsten Pixels an
+        for(int i=0; i < numPx; i++) {
+            wait_us(5);//Verzoegerung um den analogen Ausgang des Sensors zu stabilisieren
+            currentPx= ao.read(); //einlesen des Wertes
+            if(currentPx < epsilon) {
+                cntZero++; //zaehlen der ungueltigen Pixel
+            }
+            currentVal[i]=currentPx;
+            clockPulse();
+
+            //ueberpruefen ob Messung noch gueltig ist
+            if (cntZero > zeroMax) {
+                errorLED=!errorLED;
+                edgePx= -1; //Fehler Nummer 1
+                validMeas=0; // setze Messung fehlerhaft
+                break; //stoppt Auslesen des Sensors, startet neue Belichtung
+            }
+        }
+
+        //Mittelung der Werte mit vorherigen Messungen wenn neue Messung gueltig
+        if(validMeas) {
+            if(j>0) {
+                for(int i=0; i<numPx; i++) {
+                    meanVal[i]=(meanVal[i]+currentVal[i])/2;
+                }
+            } else { //j==0
+                for(int i=0; i<numPx; i++) {
+                    meanVal[i]=currentVal[i];
+                }
+            }
+        }
+    }
+}
+
+void gaussian_calc()
+{
+    //Gauß Filter sigma=2, k=5, G(x,sigma)=1/113*[1,3,7,14,20,23,20,14,7,3,1]
+    for (int i = leftbound - 1; i < rightbound + 1; i++) {
+        gaussian[i] = (meanVal[i-5]+meanVal[i-4]*3
+                       +meanVal[i-3]*7+meanVal[i-2]*14
+                       + meanVal[i-1]*20+meanVal[i]*23
+                       + meanVal[i+1]*20+meanVal[i+2]*14
+                       + meanVal[i+3]*7+meanVal[i+4]*3+
+                       meanVal[i+5])/113;
+    }
+
+}
+
+void gradient_calc()
+{
+    for (int i = leftbound; i < rightbound; i++) {
+        gradient[i] = (meanVal[i-1]- meanVal[i+1]) / 2;
+    }
+
+}
+
+
+void nonMaxSupr()
+{
+    //Quantisierung des Gradienten
+    for(int i=leftbound; i<rightbound; i++) {
+        if(gradient[i]> quantStep[0]) {
+            quant[i]=0.0;//keine Kante
+        } else {
+            for(int k=1; k<numQuant; k++) {
+                if(gradient[i]> quantStep[k]) {
+                    quant[i]=quantStep[k-1];
+                    possEdgePx.push(i); //moegliche Kante
+                    break;
+                }
+            }
+        }
+    }
+
+    //Non-Maxima-Supression
+
+    numPossEdgePx=possEdgePx.size();
+
+    for (int i=0; i<numPossEdgePx; i++) {
+        tmpPossEdgePx=possEdgePx.front();
+        possEdgePx.pop();
+        //Bedingung fuer Kante if(quant[tmpPossEdgePx]<=quant[tmpPossEdgePx-1] && quant[tmpPossEdgePx]<=quant[tmpPossEdgePx+1] )
+        //negiert damit Gleichheit zwischen Float nicht ueberprüft werden muss
+        if(!(quant[tmpPossEdgePx]>quant[tmpPossEdgePx-1] || quant[tmpPossEdgePx]>quant[tmpPossEdgePx+1]))  {
+            possEdgePx.push(tmpPossEdgePx); //moegliche Kante
+        }
+    }
+}
+
+void plausible()
+{
+//Plausibilitaetspruefung
+    if(possEdgePx.empty()) {
+        errorLED=!errorLED;
+        edgePx=-2; // Fehler Nummer 2
+    }
+
+    //Plausibilitaetspruefung: ueberpruefe die Umgebung jedes moeglichen Kantenpixels
+    // die Pixel links davon muessen im Mittelwert < threshblack
+    // die Pixel rechts davon >threshfoil
+    numPossEdgePx=possEdgePx.size();
+
+    for (int j=0; j<numPossEdgePx; j++) {
+        tmpPossEdgePx=possEdgePx.front();
+        possEdgePx.pop();
+        meanLeft=0.0;
+        meanRight=0.0;
+        for(int i=1; i<6; i++) {
+            meanLeft+=meanVal[tmpPossEdgePx-i];
+            meanRight+=meanVal[tmpPossEdgePx+i];
+        }
+        meanLeft=meanLeft/5;
+        meanRight=meanRight/5;
+
+        if(meanLeft < threshBlack && meanRight> threshFoil) {
+            possEdgePx.push(tmpPossEdgePx);
+        }
+    }
+
+}
+
+void edgePx_calc()
+{
+    if(possEdgePx.empty()) {
+        errorLED=!errorLED;
+        edgePx=-3; //Fehler Nummer 3
+    } else if (possEdgePx.size()==1) {
+        //nur ein moegliches Kantenpixel uebrig
+        edgePx=possEdgePx.front();
+        possEdgePx.pop();
+    } else {
+        //mehrere moegliche Kantenpixel;
+        //bei richtig eingestelltem Sensor sollten hier durch die Plausibilitaetspruefung
+        //nur noch Nachbarpixel mit gleich großem quantisiertem Gradient uebrig sein
+        //waehle Pixel mit minimalem Gradient(float)
+        gradmin = 0.0;
+        numPossEdgePx = possEdgePx.size();
+        for (int i = 0; i < numPossEdgePx; i++) {
+            tmpPossEdgePx=possEdgePx.front();
+            possEdgePx.pop();
+            if ( gradient[tmpPossEdgePx]< gradmin) {
+                gradmin=gradient[tmpPossEdgePx];
+                edgePx=tmpPossEdgePx;//gefundenes Kantenpixel, Algorithmus erfolgreich
+                errorLED=0;
+            }
+        }
+    }
+}
+
+int edgePx_get()
+{
+    read();
+    gaussian_calc();
+    gradient_calc();
+    nonMaxSupr();
+    plausible();
+    edgePx_calc();
+    return edgePx;
+}
+