
Dies ist die von Julian Mueller überarbeitete Bahnkantenregelung.
Diff: edge_func.cpp
- 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; +} +