
Dies ist die von Julian Mueller überarbeitete Bahnkantenregelung.
edge_func.cpp
- Committer:
- Jules20
- Date:
- 2016-05-31
- Revision:
- 0:b72d86a7b005
File content as of revision 0:b72d86a7b005:
/** *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; }